iOS-Security[8]-插件开发

Theos 是一款越狱开发工具包。

安装

Dpkg

Dpkg(Debian Packager) 是 Theos 的依赖工具,用于制作 deb(发布格式)。

安装命令:

1
brew install dpkg

Ldid

Ldid 是一款签名工具,参考iOS-Security[4]-调试

Theos

将 Theos 安装到 /opt/ 目录下:

1
2
cd /opt
sudo git clone --recursive https://github.com/theos/theos.git

流程

创建

先设置路径变量:

1
export THEOS=/opt/theos

然后输入命令:

1
$THEOS/bin/nic.pl

紧接着,选择要创建的模板,这里是 application_modern, 接着输入项目信息即可:

iOS-Theos-Create

这里,注意,包名只能是小写字母和’-+.’三个字母组成。

创建的项目如下:

iOS-Theos-Create-Project

编译

查看 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

iOS-Theos-Make

打包

打包命令:

1
make package

如果报错:

1
2
3
4
5
6
7
8
9
> Making all for application YI_Theos_Application…
==> Copying resource directories into the application wrapper…
make[2]: Nothing to be done for `internal-application-compile'.
> Making stage for application YI_Theos_Application…
dpkg-deb: error: obsolete compression type 'lzma'; use xz instead

Type dpkg-deb --help for help about manipulating *.deb files;
Type dpkg --help for help about installing and deinstalling packages.
make: *** [internal-package] Error 2

修改以下文件:

1
/opt/theos/makefiles/package/deb.mk

iOS-Theos-Package-Error

将其第六行修改的 lzma:

1
_THEOS_PLATFORM_DPKG_DEB_COMPRESSION ?= lzma

改为 xz:

1
_THEOS_PLATFORM_DPKG_DEB_COMPRESSION ?= xz

打包成功:

iOS-Theos-Package-Make

在项目的 Packages 目录下生成了 Deb 文件:

iOS-Theos-Package-Deb

发布

发布到设备命令:

1
make install

如果报错:

1
2
3
4
5
6
7
8
9
10
11
12
Selecting previously unselected package com.yi.theos.
(Reading database ... 4355 files and directories currently installed.)
Preparing to unpack /tmp/_theos_install.deb ...
Unpacking com.yi.theos (0.0.1-1+debug) ...
dpkg-deb (subprocess): unable to execute decompressing archive member (xz): No such file or directory
dpkg-deb (subprocess): subprocess decompressing archive member returned error exit status 2
dpkg-deb: error: subprocess <decompress> returned error exit status 2
dpkg: error processing archive /tmp/_theos_install.deb (--install):
subprocess dpkg-deb --fsys-tarfile returned error exit status 2
Errors were encountered while processing:
/tmp/_theos_install.deb
make: *** [internal-install] Error 1

修改上面提到的 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
2
3
4
5
6
7
8
(Reading database ... 4355 files and directories currently installed.)
Preparing to unpack /tmp/_theos_install.deb ...
Unpacking com.yi.theos (0.0.1-2+debug) ...
dpkg: error processing archive /tmp/_theos_install.deb (--install):
cannot copy extracted data for './Applications/YI_Theos_Application.app/Info.plist' to '/Applications/YI_Theos_Application.app/Info.plist.dpkg-new': failed to write (No space left on device)
Errors were encountered while processing:
/tmp/_theos_install.deb
make: *** [internal-install] Error 1

怀疑是分区空间不足,通过 SSH 命令查看:

1
df -h

结果,确实是占用率百分百了。

iOS-Theos-Install-Error

解决办法:在 Cydia 中添加源 https://coolstar.org/publicrepo, 并安装 “Stashing for iOS 9.2 - 9.3.3”。

重新发布:

1
make install

iOS-Theos-Install-Success

可以看到,其删除了一些原来的插件 app,腾出了空间,安装成功了。

iOS-Theos-Install-Result

Tweak

创建

Tweak 的工程创建参考上文。

iOS-Theos-Tweak-Creat

Makefile文件

在 Makefile 文件头加上一些必要的信息:

iOS-Theos-Tweak-Makefile

Tweak.xm文件

Tweak.xm文件是用 Logos 语法和 OC 混编的文件,可以对特定的 Class 的特定方法进行 Hook,修改其实现。

默认格式为:

iOS-Theos-Tweak-XM-Default

以 QQ 音乐为例,先破壳,然后导出头文件,从头文件中查看想要 Hook 的方法,这里以跳转到语音识别页面的方法为例:

1
2
3
4
5
6
7
8
%hook QMRootTabBarVC

- (void)jumpToRecognizeVC {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"YI" message:@"就不让你跳.." delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
[alert show];
}

%end

编译打包发布

编译打包发布流程参考上文。

iOS-Theos-Tweak-QQMusic

启动 QQ 音乐后,点击右上角,效果如下:

iOS-Theos-Tweak-QQMusic-Result

Logify

Logify 是 Theos 的一个工具,可以对一个 .h 头文件,生成一个 Tweak.xm 文件,该文件对 .h 所有方法都进行 hook,并打印出日志。

以 QQ 音乐的 QMRootTabBarVC 类为例,命令:

1
THEOS/bin/logify.pl QMRootTabBarVC.h  > Tweak.xm

输出结果为:

iOS-Theos-Tweak-Logify

其对每个方法都植入了:

1
%log;

同样,编译打包发布后,在 XCode->Device->Console 中可以看到日志:

iOS-Theos-Tweak-Logify-Result

通过日志,可以看出该类的方法调用次序。

异常

这里,在编译时候,遇到一些异常,总结如下:

unknown type

1
2
3
Tweak.xm:25:2288: error: unknown type name 'DiscoverRootViewController'
Tweak.xm:25:3166: error: unknown type name 'SkinViewController'; did you mean
'UIViewController'?

处理方法是,在文件头引入前置定义:

1
2
3
4
5
6
@class DiscoverRootViewController;
@class SkinViewController;
@class QMTabBar;
@class QMMoreVC;

%hook QMRootTabBarVC

如果是遇到常量类型的,例如下面的 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
2
Tweak.xm:25:9: error: expected selector for Objective-C method
- (void).cxx_destruct { HBLogDebug(@"-[<QMRootTabBarVC: %p> tabBar]", se...

直接删除该方法。

丢失精度

1
2
3
Tweak.xm:80:401: error: cast from pointer to smaller type 'unsigned int' loses
information
..._cmd); HBLogDebug(@" = 0x%x", (unsigned int)r); return r; }

原因是 clang 严格的类型转换限制,在 64 位机子上,指针为 64 位,而 int 为 32 位导致的,解决办法为,加多一次 size_t 的类型转换,因为 size_t 跟指针的位数为一致的,而 size_t 转换到 int 不会报错:

1
HBLogDebug(@" = 0x%x", (unsigned int)(size_t)r);