Theos 是一款越狱开发工具包。
安装
Dpkg
Dpkg(Debian Packager) 是 Theos 的依赖工具,用于制作 deb(发布格式)。
安装命令:
1 | brew install dpkg |
Ldid
Ldid 是一款签名工具,参考iOS-Security[4]-调试。
Theos
将 Theos 安装到 /opt/ 目录下:
1 | cd /opt |
流程
创建
先设置路径变量:
1 | export THEOS=/opt/theos |
然后输入命令:
1 | $THEOS/bin/nic.pl |
紧接着,选择要创建的模板,这里是 application_modern, 接着输入项目信息即可:
这里,注意,包名只能是小写字母和’-+.’三个字母组成。
创建的项目如下:
编译
查看 XCode 的 SDK 版本,路径为:
1 | /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/ |
设置 SDK 版本, 这里为 10.3:
1 | export SDKVERSION=10.3 |
设置设备的 IP 地址:
1 | export THEOS_DEVICE_IP=192.168.2.31 |
这里,注意,设备必须支持 SSH。
cd 到项目目录下,执行:
1 | make |
打包
打包命令:
1 | make package |
如果报错:
1 | > Making all for application YI_Theos_Application… |
修改以下文件:
1 | /opt/theos/makefiles/package/deb.mk |
将其第六行修改的 lzma:
1 | _THEOS_PLATFORM_DPKG_DEB_COMPRESSION ?= lzma |
改为 xz:
1 | _THEOS_PLATFORM_DPKG_DEB_COMPRESSION ?= xz |
打包成功:
在项目的 Packages 目录下生成了 Deb 文件:
发布
发布到设备命令:
1 | make install |
如果报错:
1 | Selecting previously unselected package com.yi.theos. |
修改上面提到的 Deb.mk 文件:
1 | /opt/theos/makefiles/package/deb.mk |
将以下语句:
1 | $(ECHO_NOTHING)COPYFILE_DISABLE=1 $(FAKEROOT) -r $(_THEOS_PLATFORM_DPKG_DEB) -Z$(_THEOS_PLATFORM_DPKG_DEB_COMPRESSION) -b "$(THEOS_STAGING_DIR)" "$(_THEOS_DEB_PACKAGE_FILENAME)"$(ECHO_END) |
替换成:
1 | $(ECHO_NOTHING)COPYFILE_DISABLE=1 $(FAKEROOT) -r dpkg-deb -Zgzip -b "$(THEOS_STAGING_DIR)" "$(_THEOS_DEB_PACKAGE_FILENAME)" $(STDERR_NULL_REDIRECT)$(ECHO_END) |
如果报错:
1 | (Reading database ... 4355 files and directories currently installed.) |
怀疑是分区空间不足,通过 SSH 命令查看:
1 | df -h |
结果,确实是占用率百分百了。
解决办法:在 Cydia 中添加源 https://coolstar.org/publicrepo, 并安装 “Stashing for iOS 9.2 - 9.3.3”。
重新发布:
1 | make install |
可以看到,其删除了一些原来的插件 app,腾出了空间,安装成功了。
Tweak
创建
Tweak 的工程创建参考上文。
Makefile文件
在 Makefile 文件头加上一些必要的信息:
Tweak.xm文件
Tweak.xm文件是用 Logos 语法和 OC 混编的文件,可以对特定的 Class 的特定方法进行 Hook,修改其实现。
默认格式为:
以 QQ 音乐为例,先破壳,然后导出头文件,从头文件中查看想要 Hook 的方法,这里以跳转到语音识别页面的方法为例:
1 | %hook QMRootTabBarVC |
编译打包发布
编译打包发布流程参考上文。
启动 QQ 音乐后,点击右上角,效果如下:
Logify
Logify 是 Theos 的一个工具,可以对一个 .h 头文件,生成一个 Tweak.xm 文件,该文件对 .h 所有方法都进行 hook,并打印出日志。
以 QQ 音乐的 QMRootTabBarVC 类为例,命令:
1 | THEOS/bin/logify.pl QMRootTabBarVC.h > Tweak.xm |
输出结果为:
其对每个方法都植入了:
1 | %log; |
同样,编译打包发布后,在 XCode->Device->Console 中可以看到日志:
通过日志,可以看出该类的方法调用次序。
异常
这里,在编译时候,遇到一些异常,总结如下:
unknown type
1 | Tweak.xm:25:2288: error: unknown type name 'DiscoverRootViewController' |
处理方法是,在文件头引入前置定义:
1 | @class DiscoverRootViewController; |
如果是遇到常量类型的,例如下面的 CDUnknownBlockType:
1 | - (void)delayPlaySong:(unsigned long long)arg1 song:(id)arg2 block:(CDUnknownBlockType)arg3 { %log; %orig; } |
直接替换成 id:
1 | - (void)delayPlaySong:(unsigned long long)arg1 song:(id)arg2 block:(id)arg3 { %log; %orig; } |
cxx_destruct
1 | Tweak.xm:25:9: error: expected selector for Objective-C method |
直接删除该方法。
丢失精度
1 | Tweak.xm:80:401: error: cast from pointer to smaller type 'unsigned int' loses |
原因是 clang 严格的类型转换限制,在 64 位机子上,指针为 64 位,而 int 为 32 位导致的,解决办法为,加多一次 size_t 的类型转换,因为 size_t 跟指针的位数为一致的,而 size_t 转换到 int 不会报错:
1 | HBLogDebug(@" = 0x%x", (unsigned int)(size_t)r); |