浅谈Tweak 开发
作者:FloatingGuy 转载请注明出处:https://floatingguy.github.io/
环境配置
详情参考:iOS 越狱的Tweak开发
新版的已经是内置CydiaSubstrate.framework,不是网上其它教程中说的需要运行bootstrap.sh脚本或者是从手机上拷贝等方式.
Theos 使用方法
Theos 当前有12种模板,这里拿书中的 iOSREProject tweak 工程的例子做演示。
创建项目
nic.pl
模板类型:
123456789101112131415iOS_Tweak $ nic.plNIC 2.0 - New Instance Creator------------------------------[1.] iphone/activator_event[2.] iphone/application_modern[3.] iphone/cydget[4.] iphone/flipswitch_switch[5.] iphone/framework[6.] iphone/ios7_notification_center_widget[7.] iphone/library[8.] iphone/notification_center_widget[9.] iphone/preference_bundle_modern[10.] iphone/tool[11.] iphone/tweak[12.] iphone/xpc_service
初级阶段常用的类型是:2, 10, 11,
项目类型:
Choose a Template (required):11
工程名称:
Project Name (required):iOSREProject
deb 包名
Package Name [com.yourcompany.iosreproject]:com.iosre.iosreproject
tweak 作者:
Author/Maintainer Name [xx]:xx
tweak 作用的对象(指定要 hook的目标APP 的 bundle identifier)
[iphone/tweak] MobileSubstrate Bundle filter [com.apple.springboard]:com.apple.springboard
tweak 安装完以后要重启的应用
[iphone/tweak] List of applications to terminate upon installation (space-separated, ‘-‘ for none) [SpringBoard]:SpringBoard
Instantiating iphone/tweak in iosreproject/…
Done.
文件结构
当前创建了一个 tweak 项目,在工程目录下只有4个文件:
Makefile
control
iOSREProject.plist
Tweak.xm
Makefile
这是一个编译脚本
|
|
注意:private framework 中导入的包可能存在兼容性问题。比如 BaseBoard 这个 private framework只存在 8.0及以上版本的 SDK 里。这种情况在 ios7中无法正常运行,通过弱链接(makefile weak linking)或者 dlopen/dlsym/dlclose 系列函数调用 private framework。
control
control 中的信息会显示在 Cydia 中, 且 control 文件中内容可以修改。
更多字段在 debian 的官网。
iOSREProject.plist
此 plist 文件的作用和 app 开发时的 plist 文件作用相似, 记录配置信息 描述了 tweak 的作用范围。
Filter 包含 3类数组
- Bundles
- 指定 tweak 起作用的APP \< “bundle identifier” >
- Executables
- 指定作用的 可执行文件 \<文件名>
- Classes
- 指定 作用的 class \<类名>
注意: 当Filter 下包含不同的 Array 时需要添加一个 “Mode : Any”, 当只有一个 Array 时不需要。
校验 plist 文件格式:plutil -lint xx/xx/iOSREProject.plist
不熟悉 xml 语法,使用 xcode 编辑.
Tweak.xm
Tweak.xm 后缀 xm
代码文件使用的编程语言。x
源文件支持 Logos 和 C语法xm
源文件支持Logos 和 C/ C++ 语法
|
|
Logos 函数使用 % 开头。
这里用户定义了2个 group(iOS7Hook 和 iOS8Hook), 并且显示定义了 %ctor 负责初始化要使用的 group
编译 + 打包 + 安装
|
|
安装是通过 ssh 命令实现,要求越狱的 iOS 安装 OpenSSH, 需要在 makefile 中设置 THEOS_DEVICE_IP
。
还可以配置 公钥登录, 具体步骤略。
总结
上面使用大量篇幅介绍开发 tweak 的流程略显啰嗦,其实 tweak 开发的本质就是 Cydia Substrate 的 hook。
hook 的目标进程、可执行文件、类:通过
具体的 hook 代码:定义在 xm 文件中,可以使用 Object-C/C/C++ 开发
hook 实现:通过 Logos 语法封装。
更多关于 tweak 的高级玩法和 其框架的限制,还要在未来的实践中去摸索
逆向tweak
将deb 包解压会有2个重要的压缩文件:
control.tar.gz
安装控制文件data.tar.lzma
二进制程序(动态库,可执行文件等)
最后那个后缀是压缩类型,可能是lzma, gz,xz等。
解压上面的压缩包以后得到 control文件 和 data 目录。
control 文件
|
|
data 目录
我逆向了某个 tweak 解压data.tar.gz 发现Library 下有3个文件夹,而我写的ioreproject只有MobileSubstrate一个文件夹。
后来发现 PreferenceBundles 下面是一个设置里的一个插件(我们先不关注这个)。
直接分析 动态库 /data/Library/MobileSubstrate/DynamicLibraries/
。
采用标准的arm 汇编, 和android so 一样。
Logos 语法
指令集
%log
在%hook 内部使用。%orig
执行被 hook 的函数的原始代码%group
便于代码管理及按条件初始化分组。不属于某个自定义group 的 hook , 默认归类到%group _ungrouped
group 必须要配置 %init 使用才能生效。%init
只有调用了%init(group name) 才能使对应的%group 起作用%ctor
tweak 的构造函数, 完成初始化工作; 如果不定义,theos 会自动生成一个%ctor%c
动态获取一个类的定义%new
给一个现有的 class,添加新函数
指令 | 作用域 |
---|---|
%hook | %group |
%log | %hook |
%orig | %hook |
%init | %hook , %ctor |
%c | %hook , %ctor |
Logos 语言的本质是theos对cydia Substrate提供的函数的宏封装。
Cydia Substrate hook iOS
Cydia Substrate由三部分组成, 需要在越狱手机上通过 Cydia 安装。
- MobileHooker
- MobileLoader
- Safe mode
MobileHooker
此模块专门用来实现 hook, 下面3个函数就来执行 hook操作。
上面三个函数都是用来 hook,主要区别在于hook 的语言。
- 针对 C/C++ 函数, 使用
MSHookFunction(...)
, 使用 inline hook 的原理在函数头部添加汇编指令跳转。 - 针对 Object-C 函数, 使用
MSHookMessageEx(...)
, 使用 OC 语言特性。
MSHookFunction(...)
和 MSHookMessageEx(...)
使用案例, 熟悉 hook 的 api 方便逆向 (不展示 hook C++ private method 的代码)
MSHookFunction(...)
|
|
MSHookMessageEx(...)
|
|
实际上 CydiaSubstarte 提供的 api 远不止上面的3个,还有很多功能的 api,比如:MSFindSymbole(..)、MSGetImageByName(…)等等,在官方文档中均有介绍。
这三个都是用来进行hook操作的,也就是我们在非越狱开发中常说的swizzle! cydia Substrate还提供了MobileLoader:“钩子”需要在运行时被加载,靠的就是MobileLoader的功劳。MobileLoader会在适当的时机加载/Library/MobileSubstrate/DynamicLibraries/
目录下的动态库(.dylib,这是tweak的最终产品)
MobileLoader
此模块用来加载手机中的 tweak,这些 tweak 最终是以 dylib 库的形式保存在/Library/MobileSubstrate/DynamicLibraries/
目录下。
需要注意的是 MobileLoader 的作用范围并不是全局 hook。 还记得我们在上面介绍的 plist 文件吗,其中只定义了Filter 过滤器,用来过滤要 hook 的目标进程、目标可执行文件、以及目标类。
那么 MobileLoader 就会根据 plist 中过滤器指定的作用范围,有选择的在不同进程里通过 dlopen 加载对应的 dylib。
注意:从 ios9 开始必须定义 plist 文件。没有相应的plist的Dylib将不被加载。 要复制以前没有过滤器plist的效果,导致将dylib加载到所有进程中,请将Filter设置为com.apple.Security。
Safe mode
为了防止编写的 tweak 不规范导致整个进程崩溃,所以 添加了 Safe Mode,它可以捕获 一下6种信号,然后进入安全模式。
- SIGABRT
- SIGILL
- SIGBUS
- SIGSEGV
- SIGSYS
其他技术
检查是否加壳
otool -l WeChat.app/WeChat | grep -B 2 crypt
1代表加密了,0代表被解密了:
Bugs
lzma
|
|
解决方案
dpkg 降级
|
|
解决方案