工作中碰到了TouchSprite这款应用,很有想法的一个APP,通过模拟点击的方式来达到自动帮助玩家玩游戏的目的。而且还形成了一个小的生态圈子,TouchSprite提供这样一款模拟点击的工具,但针对各种游戏需要平台上的脚本开发者来具体开发与发布。玩家可以在这个平台上搜索自己感兴趣的游戏脚本并支付给开发者相应的费用。一个闭环的精致的生态链就这样建立了,完美。好了,不废话了,今天要写的话题就是跟这个TouchSprite有关。
TouchSprite是一款使用root账户运行的应用,从cydia中将它安装到手机后,可以在/Application目录下找到它,可以发现该目录下存在着大量的苹果原生应用。TouchSprite的具体构架这里不再介绍了,后面有时间的话,会单独的出一篇。在我的上篇文章《Cydia的基石:MobileSubstrate》中有提到有些APP通过在编译时通过设置__RESTRICT,__restrict编译参数来阻止dylib动态库的注入。而TouchSprite毫无疑问的采用了这种技术,我们可以能过MachOView来查看它的可执行文件TouchSprite.app/Weather来确认这一点(它的plist文件中注明的可执行文件是NewTouchSprite,如何跳转到Weather有待于进一步探索)。
既然传统的Tweak注入方式不顶用了,我们还有其它的Hook方式吗?当然有!App运行时所需要的信息,一般都存放在MachO文件的头部中,而dylib的信息是由load commands块来确定的。换名话说就是App在执行时,dylb会查看APP可执行文件的头部信息,并将包含在load commands块中由LC_LOAD_DYLIB指定的dylib加载到内存空间中去。我们使用machOView查看TouchSprite的load commands模块截图如下:
从这个图上我们可以看到,app运行时所需要链接的库文件信息全部都在这里了,还指明了加载库文件所要用到的绝对路径,甚至指明了一些库文件的weak加载方式。现在我们要做的就是想方设法的将我们自己的库用LC_LOAD_DYLIB的方式罗列在这里就OK了。怎么做呢?一个叫insert_dylib的开源工具为我们指明了方向,感谢这个工具的作者,工具的地址为https://github.com/Tyilo/insert_dylib。将代码clone到本地,编译,使用如下命令来达成目标。
这里要注意的是insert_dylib这个工具是mac端的,如果你将它scp到手机上使用的话,它会报错的。
这里还有一个小的技巧需要说明下:注意到上图那个TouchSpriteTweak.dylib了吗,它是我测试用的动态库,也是我想注入到TouchSprite中的动态库,它在mac上的绝对路径是不是与手机上一般情况下tweak所在的绝对路径完全一致,是的,这是我故意做的,这样我就能够使用传统的tweak编译导入方式将动态库上传到手机中去,然后应用会自动到这个路径下来加载我的库文件,这个想法有点高明哈。
当我完成以上操作后,我开始以为完成了所有的步骤。当我把重新生成的weather_patched文件重命名为Weather并拷贝替换TouchSprite.app下的文件,尝试在手机上运行该文件才发现,应用崩溃了,而且没有打印出我期望的运行日志。一番探究后发现问题出签名上。如何解决呢?
首先需要使用ldid工具对新生成的Weather_patched重签名,其次需要在手机上下载AppSync来过滤掉苹果官方的签名验证机制。
测试验证打包LOG如下,成功完成动态库的加载。
参考文章: