Theos的安装
签名工具ldid安装
- ldid需要通过brew安装,如果mac上没有安装brew,可以通过以下命令安装HomeBrew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
- 安装完brew之后,通过brew安装ldid
brew install ldid
修改环境变量
-
Theos官方建议我们将Theos克隆到~/theos目录下,而且~/theos路径之后需要多次使用,所以将~/theos配置为环境变量
-
访问根目录下的.bash_profile文件
vim ~/.bash_profile
- 在.bash_profile文件最后加入下面两行
export THEOS=~/theos
export PATH=$THEOS/bin:$PATH
此处将~/theos/bin配置进PTAH中,PATH通过:来配置多个路径,配置好Path之后,在终端输入某一个指令时,会到PATH里的所有目录下去寻找可执行文件。注意:此处的:$PATH一定不能遗漏(加上原来配置的路径),否则原来设置的PATH会被THEOS的目录覆盖。
- 配置完成之后,在终端执行source命令,使.bash_profile文件的配置立即生效
source ~/bash_profile
- 此时我们通过$PATH来打印出PATH信息,就可以看到THEOS目录已经添加到了PATH中
echo $PATH
下载Theos
- 通过以下命令将Theos下载到上面配置的$THEOS目录中
git clone --recursive https://github.com/theos/theos.git $THEOS
- --recursive表示递归下载,因为Theos会依赖其它库,使用此命令可以递归的将所有依赖的库都下载下来
Tweak项目
创建tweak项目
- cd到存放项目的目录,执行nic.pl指令,选择iphone/tweak对应的序号。
cd ~/Desktop/tweak
nic.pl
- 填写项目所需要的信息
#项目名称
Project Name
#项目ID,按规则填写即可
Package Name
#作者名,直接按回车使用默认名
Author/Maintainer Name
#需要hook的App的Bundle Identifier,可以使用Cycript查看
[iphone/tweak] MobileSubstrate Bundle filter
#直接回车,使用默认配置就可以
[iphone/tweak] List of applications to terminate upon installation
tweak项目配置
- 编辑Makefile文件,需要在Makefile文件中增加以下环境变量,指明通过哪个IP和端口号访问手机,由于之前使用的是USB的方式访问,所以IP写本机地址即可
export THEOS_DEVICE_IP=127.0.0.1 #本机IP地址
export THEOS_DEVICE_PORT=10088 #本机端口号
INSTALL_TARGET_PROCESSES = SpringBoard
include $(THEOS)/makefiles/common.mk
TWEAK_NAME = test_tweak
test_tweak_FILES = Tweak.x
test_tweak_CFLAGS = -fobjc-arc
include $(THEOS_MAKE_PATH)/tweak.mk
- 上述方式配置的环境变量只能在当前的tweak项目中生效,以后如果有新的tweak项目,就需要重新配置。如果不希望每个项目都要重新编写IP和端口号的环境变量,可以将这两个变量配置到.bash_profile中
export THEOS=~/theos
export PATH=$THEOS/bin:$PATH
export THEOS_DEVICE_IP=127.0.0.1
export THEOS_DEVICE_PORT=10088
复制代码配置完成后,使用source让配置生效
source ~/.bash_profile
tweak项目编写代码
- 代码编写
tweak项目的拦截代码编写在Tweak.x文件中,代码如下
%hook ClassName
// Hooking a class method
+ (id)sharedInstance {
return %orig;
}
// Hooking an instance method with an argument.
- (void)messageName:(int)argument {
%log; // Write a message about this call, including its class, name and arguments, to the system log.
%orig; // Call through to the original function with its original arguments.
%orig(nil); // Call through to the original function with a custom argument.
// If you use %orig(), you MUST supply all arguments (except for self and _cmd, the automatically generated ones.)
}
// Hooking an instance method with no arguments.
- (id)noArguments {
%log;
id awesome = %orig;
[awesome doSomethingElse];
return awesome;
}
%end
语法简介
- tweak使用的Logos语法简介,可以点击Logos官网查看完整的语法介绍。
%hook、%end :#表示hook一个类的开始和结束
%log :#打印方法调用详情,可以通过Xcode -> Window -> Devices and Simulators
HBDebugLog : #和NSLog类似
%new :#添加一个新的方法
%c(className) : #生成一个Class对象,比如%c(NSObject),类似于NSStringFromClass()、objc_getClass()
%orig :#调用原先的方法逻辑
%ctor :#加载动态库的时候调用
%dtor :#在程序退出时调用
logify.pl
- 此工具可以将一个头文件快速转换成已经包含打印信息的x文件,这可以为我们节省很多事,比如我们要监听一个页面所有方法的调用,使用此工具就能自动将所有的OC方法转换成Logos方法,并且在方法中为我们加上对应的log方法和返回值。具体转换指令如下:
logify.pl xx.h > xx.xm
- 但是使用这种自动转换的方法转换之后的代码在编译时会遇到很多问题。解决方法如下:
删除__weak
删除inout
删除掉协议,或者使用@protocol XXTestDelegate声明一下协议
删除掉- (void).cxx_destruct { %log; %orig; }方法
删除HBLogDebug(@" = 0x%x", (unsigned int)r)
替换类名为void,例如将XLPerson * 替换成void *,获取在头部声明一下类名@class Person
资源文件
如果有额外的资源文件,例如图片等等,放在项目的layout文件夹中,对应手机的根目录 /,
通常开发中可以将图片存放在以下目录中/Library/PreferenceLoader/preferences/和/Library/Caches下,
具体的做法是在tweak项目的layout文件夹中依次创建Library和Caches目录,将图片存放到此目录下。
加载图片的时候使用全路径即可
编译->打包->安装
#对项目进行编译
make
#打包成deb文件
make package
#安装,安装过程中会默认重启SpringBoard
make install
#以上命令也可写成如下格式
make && make package && make install
- 如果之前已经编译过,需要再次重新编译的话,执行make clean即可
去除hook程序
- 如果我们不想再hook别人的程序了,可以通过iFunBox,在~/Library/MobileSubstrate/DynamicLibraries/目录下找到我们的deb插件生成的.dylib和.plist文件,一般是以我们的tweak项目名命名的。删除这两个文件,然后重启SpringBoard就可以去除我们的hook插件。
- 第二种方式是通过Cydia来卸载,打开Cydia,在已安装插件中找到我们刚刚安装好的插件,点击卸载,完成之后重启SpringBoard即可
tweak执行原理
首先,当我们创建好tweak项目,并且编写好hook代码后,执行make操作,在tweak项目目录下会生成一个隐藏的文件夹.theos,在.theos/obj/debug/目录下会生成动态库.dylib文件
执行make package时,项目目录下的plist文件和第一步生成的.dylib文件打包成对应的deb文件,存放在packages目录下
执行make install时,首先会根据之前配置的THEOS_DEVICE_IP和THEOS_DEVICE_PORT两个变量去远程连接iPhone,然后通过iPhone上的Cydia来安装对应的deb插件
在App启动之后,会同时将dylib加载到内存中,App中如果访问被我们hook的类中的方法,会直接执行dylib中的方法。
- make package默认是debug模式,如果要发布release版本的包,执行make package debug=0即可
tweak多文件开发
在tweak项目开发中,如果我们需要Hook的方法过多,所有的hook方法都写在同一个类里,明显不是一种好的方式。这个时候就需要多文件开发。tweak支持多文件开发
- 首先在项目目录下增加src文件夹,然后将Tweak.x文件移到src目录下,这个时候执行make指令会提示
==> Error: File Tweak.x does not exist.
make[1]: *** [before-test_wechat-all] Error 1
make: *** [test_wechat.all.tweak.variables] Error 2
- tweak在编译时,会到Makefile中寻找可编译的文件路径,因为我们改变的Tweak.x的路径,相应的就要修改Makefile文件下的test_wechat_FILES,如下
INSTALL_TARGET_PROCESSES = SpringBoard
include $(THEOS)/makefiles/common.mk
TWEAK_NAME = test_wechat
test_wechat_FILES = src/Tweak.x
test_wechat_CFLAGS = -fobjc-arc
include $(THEOS_MAKE_PATH)/tweak.mk
tweak支持OC类,想tweak项目中的src目录下导入Person类,在Tweak.x中#import "Person.h",然后执行make编译,会出现以下错误
ndefined symbols for architecture armv7:
"_OBJC_CLASS_$_Person", referenced from:
objc-class-ref in Tweak.x.01c0bdf0.o
ld: symbol(s) not found for architecture armv7
- 修改Makefile中的test_wechat_FILES,增加Person.m的路径
INSTALL_TARGET_PROCESSES = SpringBoard
include $(THEOS)/makefiles/common.mk
TWEAK_NAME = test_wechat
test_wechat_FILES = src/Tweak.x src/*.m
test_wechat_CFLAGS = -fobjc-arc
include $(THEOS_MAKE_PATH)/tweak.mk
注意两个路径之间需要用空格分隔,Tweak支持通配符,可以使用*.m指定目录下的所有.m文件
Theos使用场景
- 如果要对某个app的view进行修改,我们可以通过Cycript获取到view对应的内存地址,通过对内存地址操作修改,但是这种方式仅仅是内存中修改,下一次再次进入此页面的时候,又会重新加载原来的view。显然,这不是我们想要的结果,那么怎么永久的修改view呢?这就要使用到了hook,通过hook某个view的指定方法改变成我们自己写的方法,然后将我们自己的代码注入到App中,就能实现永久修改view的效果。
- 如何进入hook操作呢?这就要使用到Theos,通过Thoes就可以创建tweak项目,添加需要hook的类以及方法,然后将tweak项目进行编译、打包成deb插件,最终安装到iPhone上。