逆向第三天-Theos
前言
由于前两天周末就没有更新博客,好好的玩了两天~ 今天要说的是一个重要的越狱开发工具包-Thoes,它是iOS越狱界知名人士Dustin Howett开发并分享到GitHub上。它和其他的越狱开发工具相比,最大的特点就是简单:下载安装简单、Logos语法简单、编译发布简单,可以让使用者把精力放在开发工作上。
安装
下面第三步、第四步需要的东西 我已经上传到了我的网盘 提取密码:wtxn 大家可以去下载使用。
1.下载
下面给出在终端下的操作:
1. export THEOS=/opt/theos 配置环境变量(可以了解一下export命令)
2. sudo git clone git://github.com/DHowett/theos.git $THEOS
2.配置ldid
ldid是专门用来签名iOS可执行文件的工具,用以在越狱iOS中取代Xcode自带的codesign下载地址 。下载后,把它放在“/opt/theos/bin/”下,然后用下面的命令赋予它可执行权限:
sudo chmod 777 /opt/theos/bin/ldid
3.配置CydiaSubstrate
首先运行Theos的自动化配置脚本
sudo /opt/theos/bin/bootstrap.sh substrate
此处会遇到Theos的一个bug,它无法自动生成一个有效的libsubstrate.dylib文件,需要手动替换一下。解决方法:首先在手机Cydia中搜索安装“Cydia Substrate”。然后用iFunBox或sip等方式将iOS上的“/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate”拷贝到电脑上,重命名为libsubstrate.dylib后,放到“/opt/theos/lib/”中,替换之前无效的libsubstrate.dylib即可。
4.配置dpkg-deb
deb是越狱开发安装包的标准格式,dkpg-deb是一个用于操作deb文件的工具,有了这个工具,Theos才能正确地把工程打包成为deb文件下载地址下载dm.pl,将下载的dm.pl重命名为dpkg-deb后,放到“/opt/theos/bin/”目录下,然后用以下命令赋予其可执行权限:
sudo chmod 777 /opt/theos/bin/dpkg-deb
我看到网上有另一种方法配置dpkg 用的命令是:
sudo port install dpkg 不需要再下载上面说的dpkg-deb了(这种方式我没有去试 不知道可不可以)
5.配置Theos NIC templates(可选)
就是额外多添加5个Theos工程模板,可从https://codeload.github.com/DHowett/theos-nic-templates/zip/master 下载,然后将解压后的5个.tar放到“/opt/theos/templates/iphone/”下即可。
用法
1.创建工程
- 1.在终端里cd到你常用的工程目录下,然后输入
/opt/theos/bin/nic.pl
启动NIC,如下图:
97F321B9-7321-4A8F-BAA2-0527423961AE.png
可以看到,我这里有10种模板可供选择,1、4、6、8、9是Theos的自带模板,剩下的5种是我在上面第五步中下载的。在逆向工程初级阶段,所开发的程序主要类型是tweak,其他模板的用法大家可以在iOSRE讨论交流。这里咱们以tweak来说。
- 2.选择9:
Choose a Template (required): 9
- 3.输入工程名称:
Project Name (required): FirstProject
- 4.输入deb包的名字(类似于bundle identifier):
Package Name [com.yourcompany.firstproject]: com.myj.firstproject
- 5.输入作者的名字
Author/Maintainer Name [mengyijie]: mengyijie
- 6.输入“MobileSubstrate Bundle filter”,也就是tweak作用对象的bundle identifier
com.apple.springboard
- 7.输入tweak安装完成后需要重启的应用,以进程名表示
SpringBoard
以上简单的7步完成后,就会生成一个名为firstproject的文件夹,这个文件夹里就是刚创建的tweak工程。
2.修改工程文件
- 1.修改Makefile
Makefile文件指定工程用到的文件、框架、库等信息,将整个过程自动化。咱们刚才生成的工程里面 Makefile的内容如下
include theos/makefiles/common.mk
TWEAK_NAME = FirstProject
FirstProject_FILES = Tweak.xm
include $(THEOS_MAKE_PATH)/tweak.mk
after-install::
install.exec "killall -9 SpringBoard"
第一句是固定写法不要修改;
第二句是tweak的名字,刚才创建的时候跟control文件中的“Name”字段对应,不要修改;
第三句tweak包含的源文件(不包括头文件),多个文件间以空格分隔,可以按需修改 ;
第四句根据不同的Theos工程类型,通过include命令指定不同的.mk文件。在初级阶段,我们一般开发的是Application、Tweak、Tool三种类型的程序,它们对应的.mk文件分别是application.mk 、tweak.mk、tool.mk,可以按需修改;
第五句是在tweak安装之后杀掉SpringBoard进程,好让CydiaSubstrate在进程启动时加载对应的dylib。
这也太过于简单了吧,如何指定SDK版本?怎么导入framework?lib文件在那链接?这些都没有告诉我们。下面将告诉你如何去做:
- 指定处理器架构
ARCHS = arm64 armv7s
- 指定SDK版本
TARGET = iphone:Base SDK:Deployment Target
比如:
TARGET = iphone:8.1:8.0
代表采用8.1版本的SDK,且发布对象为iOS8.0及以上版本。也可以把“Base SDK”设置为“latest”,指定以Xcode附带的最新版本SDK编译,如:
TARGET = iphone:latest:8.0
- 导入framework
firstproject_FRAMEWORKS = framework name
例如:
firstproject_FRAMEWORKS = UIKit CoreTelephony CoreAudio
那怎么导入private framework呢?用下面的语句:
firstproject_PRIVATE_FRAMEWORKS = private framework name
例如:
firstproject_PRIVATE_FRAMEWORKS = AppSupport ChatKit IMCore
虽然只是多了一个“PRIVATE”,但是有一点要注意:private framework是AppStore开发所不允许使用的,它的内容在每个iOS版本之间可能发生变化,在导入之前,一定要确定导入的private framework确实存在。下面举个例子:
如果你的tweak打算兼容iOS 7和iOS 8两个版本,那么Makefile可写成如下内容:
ARCHS = armv7 arm64
TARGET = iphone:latest:7.0 include theos/makefiles/common.mk TWEAK_NAME = firstproject
firstproject_FILES = Tweak.xm
firstproject_PRIVATE_FRAMEWORK = BaseBoard include $(THEOS_MAKE_PATH)/tweak.mk after-install::
install.exec "killall -9 SpringBoard"
这样可以成功编译和链接,并不报错;但是,因为BaseBoard这个private framework 只存在于iOS 8.0及以上版本的SDK里,在iOS 7 里并没有,所以这个tweak在iOS 7 中会因为找不到framework而报错。这种情况可以通过弱链接(谷歌搜索 “makefile weak linking”)或dlopen()、dlsym()和dlclose()系列函数动态调用private framework来解决。
- 链接Mach-O对象(Mach-O object)
firstproject_LDFLAGS = -lx
Theos采用GNU Linker来链接Mach-O对象,包括.dylib、.a和.o。在终端中输入“man ld”,定位到“-lx”部分,它是这么写的:
-lx This option tells the linker to search for libx.dylib or libx.a in the library search path.If string x is of the form y.o,then that file is searched for in the same places,but without prepending lib or appending .a or .dylib to the filename.
大致意思是说,-lx代表链接libx.a或libx.dylib,给“x”加上“lib”的前缀,以及“.a”或“.dylib”的后缀;如果x是“y.o”的形式,则直接链接y.o,不加任何前缀或后缀。iOS支持链接的Mach-O对象全是以“libx.dylib”(当然现在是"libx.tbd")和以“y.o”形式命名的,完全兼容GNU Linker。
这样链接Mach-O对象就很方便了。例如要链接libsqlite3.0.dylib、libz.dylib和dylibl.o,这样写:
firstproject_LDFLAGS = -lz –lsqlite3.0 –dylib1.o
- 2.Tweak.xm
用Theos创建tweak工程,默认生成的源文件是Tweak.xm。“xm”中的“x”代表这个文件支持Logos语法,如果后缀名是单独一个“x”,说明源文件支持Logos和C语法;如果后缀名是“xm”,说明源文件支持Logos和C/C++语法,与“m”和“mm”的区别类似。
Tweak.xm的内容这里就不展示了,只是讲一下里面的%hook、%log、%orig这3个预处理指令,他们的作用如下:
- %hook
指定需要hook的class,必须以%end结尾,如:
%hook SpringBoard
-(void)_menuButtonDown:(id)down
{
NSLog(@"You've pressed home button.");
%orig; // call the original _menuButtonDown:
} %end
这段代码的意思是钩住(hook)SpringBoard类里的_menuButtonDown:函数,先将一句话写入syslog,再执行函数的原始操作。
- %log
该指令在%hook内部使用,将函数的类名、参数等信息写入syslog,可以用%log([(<type>)<expr>,...])的格式追加其他打印信息:
%hook SpringBoard
-(void)_menuButtonDown:(id)down {
%log((NSString *)@"iOSRE", (NSString *)@"Debug"); %orig; // call the original _menuButtonDown:
} %end
打印结果如下:
Dec 3 10:57:44 FunMaker-5 SpringBoard[786]: - [<SpringBoard: 0x150eb800> _menuBu-
ttonDown:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
75607608282
20266 us 0x0000000100000190 1
16
01 00 00 00 00 00 00 00 00
Absolute Keyboard 12
64
1 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Timestamp:
Total Latency: SenderID:
BuiltIn: AttributeDataLength: AttributeData:
00 00 00 00 00 00 00 ValueType: EventType: UsagePage:
]: iOSRE, Debug
- %orig
该指令在%hook内部使用,执行被钩住(hook)的函数的原始代码。如果上面的%orig去掉,那么原始函数就不会得到执行。例如
%hook SpringBoard
-(void)_menuButtonDown:(id)down {
NSLog(@"You've pressed home button but it's not functioning.");
} %end
还可以利用%orig更改原始函数的参数,例如:
%hook SBLockScreenDateViewController
-(void)setCustomSubtitleText:(id)arg1 withColor:(id)arg2 {
%orig(@"iOS 8 App Reverse Engineering", arg2); }
%end
预处理命令还有很多,这里就不逐一介绍了,感兴趣的可以去这里看看
- Control
control文件记录了deb包管理系统所需要的基本信息,会被打包进deb包里。内容如下:
Package: com.myj.firstproject
Name: FirstProject
Depends: mobilesubstrate
Version: 0.0.1
Architecture: iphoneos-arm
Description: An awesome MobileSubstrate tweak!
Maintainer: mengyijie
Author: mengyijie
Section: Tweaks
.Package字段用于描述这个deb包的名字,采用的命名方式同bundle identifier类似,均为反向DNS格式,可以按需更改;
.Name字段用于描述这个工程的名字,可以按需更改;
.Depends字段用于描述这个deb包的“依赖”。“依赖”指的是这个程序运行的基本条件,可以填写固件版本或其他程序,如果当前iOS不满足“依赖”中定义的条件,则此tweak无法正常运行。
.Version字段用于描述这个deb包的版本号,可更改
.Architecture字段用于描述deb包安装的目标设备架构,不要更改
.Description字段是deb包的简单介绍,可以更改
.Maintainter字段用于描述deb包的维护人
.Author字段用于描述tweak的作者
.Section字段用于描述deb包所属的程序类别,不要更改
control文件中可以自定义的字段还有很多,请看这里
编译+打包+安装
- 1.编译
Theos采用“make”命令来编译Theos工程。在Theos工程目录下运行make命令:
mengyijiedeMacBook-Pro:firstproject mengyijie$ make
- 2.打包
使用“make package”命令,其实就是先执行“make”命令,然后再执行“dpkg-deb”命令:
mengyijiedeMacBook-Pro:firstproject mengyijie$ make package
生成一个名为XXXXX.deb文件,这就是可以最终发布的安装包。
- 3.安装
mengyijiedeMacBook-Pro:firstproject mengyijie$ make install
这里要求你在Makefile的最上一行加上手机ip地址
当然也可以用
mengyijiedeMacBook-Pro:firstproject mengyijie$ make package install
完成编译打包安装一条龙服务。
尾声
今天这篇说的有些多了,但还有一些没有详细给大家介绍。希望大家耐心的看~
其实命令没有多少 多的都是对文件的解释。。。
遇到的坑
Makefile里面下面这三句一定要放在最前面
THEOS_DEVICE_IP = 192.168.1.231
ARCHS = arm64 armv7s
TARGET = iphone:latest:8.0
不然会报这样的错误:
Making all for tweak Test...
Preprocessing Tweak.xm...
Compiling Tweak.xm...
Linking tweak Test...
clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of iOS 7
clang: warning: libstdc++ is deprecated; move to libc++ with a minimum deployment target of iOS 7
ld: library not found for -ldylib1.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [obj/Test.dylib.ba964c90.unsigned] Error 1
make[1]: *** [internal-library-all_] Error 2
make: *** [Test.all.tweak.variables] Error 2
参考资料:
书籍:iOS应用逆向工程(第2版)
网站:http://bbs.iosre.com/