iOS越狱开发
转载自 http://www.cnblogs.com/xiongwj0910/archive/2012/08/16/2642992.html
针对越狱手机软件开发,由于需要截获系统函数等功能,选择采用 TheOS 编译环境。
一 .TheOS 环境搭建
先要按照步骤一步一步搭建 TheOS 的环境。
这个是很全面的英文方面的 TheOS 的环境搭建和打包工具安装以及一个简单的 TheOS 程序事例。
编译打包的以及在真机上运行测试的方法 没有采用这个教程上说的设置 IP 然后 ssh 连接的方法。
另外需要自己下载一个 class - dunp 最新的工具包,这个工具用于导出库的私有头文件。
下载地址https://github.com/nygard/class-dump
使用如下
下面导出 SPRINGBOARD
打开终端输入
class-dump -H /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.2.sdk/System/Library/CoreServices/SpringBoard.app -o /Users/lkk/Desktop/Spring
这样在用户目录就会生产 SPRINGBOARD 目录。导出的 .h 都放到这了。
class - dump 的完整路径- H 你要导出的框架的完整路径
导出来的头文件可能会又些许小语法错误 自己修改一下。常见的错误例如:
CTmessage.h 导出错误
改正部分 : 把 #import "NSObject.h" 改成 #import <Foundation/NSObject.h>
//@class CTPhoneNumber, NSArray, NSDate, NSDictionary, NSMutableArray, NSMutableDictionary, NSObject<CTMessageAddress, NSCopying>, NSString;
改成
@class NSDictionary, NSDate, NSString, NSMutableDictionary, NSArray, CTPhoneNumber, NSMutableArray;
@protocol CTMessageAddress, NSCopying;
定义部分语法错误改正一下。比如 NSObject<CTMessageAddress><NSCopying> 改成 NSObject<CTMessageAddress,NSCopying>
然后拷贝这个目录到
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.2.sdk/usr/include/SpringBoard/
关于 class - dump 在我的博文中有一篇专门讲述了。
二 . 编译打包
首先安装 dpkg 打包工具
这个是基于 MacPorts 的安装命令,记得先安装 Macports ,网上大把安装教程,这里就不说了,切记别重复安装。安装之前先检查一下是否安装过了。
$ port version 查看
/* 更新 2012 / 11 / 21 Macports 安装遇见的问题以及处理方法 */
之前在公司安装 Macport 的时候没有碰见什么异常,自己回去用自己的本装的时候,发现总是卡在剩余不到一分钟,然后就不动了。
于是在网上查了下解决方案。我的处理方法是,首先重启电脑,然后果断断网,再安装。
这个时候瞬间就装完了。装完之后,再升级。
下载地址是 http://distfiles.macports.org/MacPorts/
自己选一个合适的版本下载。
断网安装之后,打开控制台,输入
sudo port -v selfupdate
更新 Macport 。
更新完毕之后就可以了。
/* 更新 2012 / 11 / 21 Macports 安装遇见的问题以及处理方法 end*/
以下是安装 dpkg 的命令
sudo port install dpkg
这个执行之后如果报错
Error:
Error: No valid Xcode installation is properly selected.
Error: Please use xcode-select to select an Xcode installation:
Error: sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer # version 4.4
Error:
Warning: xcodebuild exists but failed to execute
Warning: Xcode does not appear to be installed; most ports will likely fail to build.
就直接执行 sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer 重新指定一下路径
三 . 了解 TheOS 生成的 makeFile 的文件中各行的意思
makefile 文件内容剖析
include theos/makefiles/common.mk
告诉 theOS 在编译脚本中包括共同的 make 命令,避免做重复的 make 编译工作
APPLICATION_NAME = fooProject
我们要编译的应用程序的名称。 makefile 将会用这个常量在内部做一些事情。除非你的应用程序改名称,否则不要修改这个值。
[applicationName]_FILES = main.m fooProjectApplication.mm RootViewController.mm
这里是需要编译的文件列表,注意:不要把头文件添加到这里。如果你要添加一个新的 .m 或者 .mm 文件到项目中,确保在这里添加新的文件的名称,否则将不会建立编译连接。
[applicationName]_FRAMEWORKS = UIKit Foundation QuartzCore AudioToolbox CoreGraphics
这里包括你想用到框架的名称
include $(THEOS_MAKE_PATH)/application.mk
更多默认的 用于帮助 TheOS 建立项目
四 . 使用 TheOS 生成第一个 HelloWord 后台程序
打开终端输入
export THEOS=/opt/theos/
export SDKVERSION=4.3 //sdk 版本号,如果是 5.1 就输入 5.1
$THEOS/bin/nic.pl // 执行 TheOS
NIC 1.0 - New Instance Creator
------------------------------
[1.] iphone/application
[2.] iphone/library
[3.] iphone/preference_bundle
[4.] iphone/tool
[5.] iphone/tweak
Choose a Template (required): 5
Project Name (required): WelcomeWagon
Package Name [com.yourcompany.welcomewagon]:
Author/Maintainer Name [Brandon Trebitowski]:
MobileSubstrate Bundle filter [com.apple.springboard]:
Instantiating iphone/tweak in welcomewagon/...
Done.
这里选择了 5,5 是一个后台程序。接下来我们要做的是当系统开机时候弹出 HelloWorld 字样的 Alert 框。
这里我们要用到 hook (钩子)钩取系统开机时候调用的其中一个函数 在那个函数中插入我们的 Alert 。
%hook and %end
%hook Springboard
// overwrite methods here
%end
% hook 后面跟一个类名% hook 要与% end 配对使用中间为你想要截获的这个类的函数。
打开 Tweak.xm 添加如下代码
#import <SpringBoard/SpringBoard.h>
%hook SpringBoard
-(void)applicationDidFinishLaunching:(id)application {
%orig;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Welcome"
message:@"Hello World!"
delegate:nil
cancelButtonTitle:@"Thanks"
otherButtonTitles:nil];
[alert show];
[alert release];
}
%end
%orig; 功能是执行这个函数原来的动作。如果你想完完全全禁止某个函数的功能,不使用 %orig; 即可。
这里使用了 UIKit 框架的 Alert 类,所以需要在 makeFile 文件中添加
WelcomeWagon_FRAMEWORKS = UIKit
这一句。前面又说明 这句的意思 这里不做过多说明了
接下来编译使用命令
打开控制台,进入到你的这个工程文件夹,使用命令
make
然后会生成一个 .obj 的文件夹,在文件夹内又一个 dylib 的包,这个就是我们需要的动态库文件了。把这个 dylib 放入如下图所示路径下。( package / Library / MobileSubstrate / DynamicLibraries/ )
package 文件夹是自己创建的(由于这里我偷了个懒直接从开源项目里面搬过来了,所以那个 preferenceLoder 文件夹没用到),自己生成的工程是没有,为了让 dylib 和 plist 安装到系统指定文件夹目录下(/ Library / MobileSubstrate / DynamicLibraries/ )。使用 iFile 等等的文件管理工具 可以看见你设备中的文件路径情况。
/* 2012 年 10 月 18 日更新内容*/
另外,那个 DEBIAN 文件夹是需要的,里面放 control 文件即可。 control 文件再你的根目录可以找到。
/* 2012 年 10 月 18 日内容说明更新完毕/
打包成 deb 包
使用 dpkg -b 需要打包的文件夹路径
例如:
![2012081619420971.png]()
我要打包 package 这个文件夹
dpkg -b /Users/ws/Desktop/Theos 目录 /IconRenamer/package
使用这个命令即可生成一个 package.deb 文件在当前路径下
安装测试运行
这里的步骤和网上的一些教程有些不一样,首先在 iphone 上下载 iFile 这个工具。 pc 端下载 pp 助手 91 助手 iTools 等工具将 deb 安装包放置在 iphone 中的任意位置,例如:
![2012081619430369.png]()
使用 iFile 找到 package.deb 这个安装包,点击之后 会有一个安装选项。选择安装即可。然后重启,你的屏幕上就会华丽丽的出现 Hello World !的弹出框了。
这里插一句,我们的一个产品 friendIn 已经上线了, FriendIn 帮你整和所有社交平台的好友最新动态,你可以通过 FriendIn 随时随地关注你关心的朋友的最新动态。
第二弹 hook 的使用
上面只是介绍一种 hook 的使用方法,这里进行详细的介绍。
MobileHooker 用于替换覆盖系统的方法,这个过程被称为 Hooking( 挂钩 ). 将使用到 3 个 API :
IMP MSHookMessage(Class class, SEL selector, IMP replacement, const char* prefix); // prefix should be NULL.
void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP *result);
void MSHookFunction(void* function, void* replacement, void** p_original);
MSHookMessage() 在 Objective-C 中替换 implementation 。 [class Selector] 通过替换 并返回原来的执行。挂钩一个类的方法,
在 MSHookemessage(EX) 中调用 Objc_getMetaClass 得到提供的元数据和类检索,例如下面的注释。这种动态替换是 Objective-c 的一个功能 . 使用method_setImplementation。 MSHookMmessage() 是线程不安全的,不赞成使用,赞成 MSHookMessageEx()
MSHookFunction() 很像 MSHookMessage() 但是适合于 c/c++ 的函数。 MSHookFunctin() 将写入指令调入指定替换函数,并接会分配一些字节在内存地址,相当于原始切出指令并且跳入原始的挂钩方法。由于 iPhone 系统默认的内存页不能同时写和执行,一个内核补丁必须申请 MSHookFunction() 工作 .
截止 MobileSubstrate 的最新版本, MSHookMessage() 也需要一个内核补丁 调用关闭的挂钩的所有正确方法。
代码示例:
使用 MSHookfunction:
static void (*original_CFShow)(CFTypeRef obj); // a function pointer to store the original CFShow().
void replaced_CFShow(CFTypeRef obj) { // our replacement of CFShow().
printf("Calling original CFShow(%p)...", obj);
original_CFShow(obj); // calls the original CFShow.
printf(" done.\n");
}
...
// hook CFShow to our own implementation.
MSHookFunction(CFShow, replaced_CFShow, &original_CFShow);
// From now on any call to CFShow will pass through replaced_CFShow first.
...
CFShow(CFSTR("test"));
使用 MSHookMessageEX:
static IMP original_UIView_setFrame_;
void replaced_UIView_setFrame_(UIView* self, SEL _cmd, CGRect frame) { // Note the implicit self and _cmd parameters are needed explicitly here.
CGRect originalFrame = self.frame;
NSLog("Changing frame of %p from %@ to %@", self, NSStringFromCGRect(originalFrame), NSStringFromCGRect(frame));
original_UIView_setFrame_(self, _cmd, frame); // Remember to pass self and _cmd.
}
...
MSHookMessageEx([UIView class], @selector(setFrame:), (IMP)replaced_UIView_setFrame_,(IMP *)&original_UIView_setFrame_);
...
myView.frame = CGRectMake(0, 0, 100, 100);
注意,如果你挂钩一个类的方法,有必须放一个元类在类参数中。
MSHookMessageEx(objc_getMetaClass("UIView"), @selector(commitAnimations), replaced_UIView_commitAnimations, (IMP *)&original_UIView_commitAnimations);
这里的 MSHookMessageEx 或者 MSHookMessage 方法等同于 % hook % end 的方法 建议使用% hook % end 对,比较方便和简洁。
这些方法只要是安装好了 TheOS 环境既可以使用。
TheOS 的一些设置 TheOS 默认警告级别很高,把所有的警告当成错误处理,如果想降低警告级别 只需要
TheOS 设置警告等级,默认是把警告当成错误处理
Now, all we need to do is fix Theos's treatment of errors.
In Makefile, add the following line BEFORE EVERYTHING:
GO_EASY_ON_ME = 1
This tells Theos not to treat warnings as errors. It removes the -Werror flag from the compiler arguments. We are ready to build the tweak!
基本上就这些内容了,虽然看起来很简单,但是寻找函数的工作是很艰难的。技术点就是是通过 hook 来钩取类方法。主要工作量在于猜测系统调用了什么函数。
由于 TheOS 开发界面不怎么好,还需要自己管理 makefile 文件,这里说一下 iOSOpenDev 这个环境,基于 Xcode 创建模板和编译打包。相信对于 makefile 不怎么熟悉的朋友比较倾向于使用这个。下面来说一下安装步骤。
一 . 安装
iOSOpenDev 安装步骤
http://www.jailbreaktweak.com/develop-jailbreak-tweaks-tool/41/
iOSOpenDev 安装失败解决方案
https://github.com/kokoabim/iOSOpenDev/wiki/Troubleshoot
指定 xcode 路径
http://icyleaf.com/2012/03/upgrade-xcode-431/
以上是安装步骤以及安装过程中可能出现的问题的解决方法。
二 . 创建一个简单的 HelloWorld 插件
安装好了之后 你会看见如下图的各个模板
![2012090309291010.png]()
这里列举 Logos tweak 工程模板的例子。创建这样一个工程。
创建的工程中有一个 xm 文件,这个文件和 TheOS 中的 xm 文件是一样的,之前给大家的 demo 中的 xm 文件内容可以直接 copy 过来, 可能需要注释几个头文件包含才能编译过。
xm 文件中有这样一段说明
#error iOSOpenDev post-project creation from template requirements (remove these lines after completed) -- \
Link to libsubstrate.dylib: \
(1) go to TARGETS > Build Phases > Link Binary With Libraries and add /opt/iOSOpenDev/lib/libsubstrate.dylib \
(2) remove these lines from *.xm files (not *.mm files as they're automatically generated from *.xm files)
意思是要把 libsubstrate.dylib 添加到工程中 ( 在安装好的 /opt/iOSOpenDev/lib 目录下 ) ,然后把 xm 中的内容清空。 mm 文件的内容会根据 xm 文件中的内容编译后自动生成。
接下来添加 libsubstrate.dylib 到你的工程中去 , 再添加 UIKit 框架。然后让我们来写 helloWorld 把, hook 的使用方法前面的文章中已经有介绍了,这里就不多做说明,直接上代码
再 xm 文件中添加如下代码。
![2012090309573575.png]()
这段代码大家应该不陌生把。之前在写 TheOS 一篇中也是这个例子。
三 . 编译打包
代码写完了,应该进行编译,如下图
![2012090310020228.png]()
product -》 Bulid for -》 profiling
编译时候记得选择自己的设备,每次编译前记得 clean 一下,编译结束之后你会看见一个错误。
Command /bin/sh failed with exit code 1
这个意思是没有成功在设备上运行,这个可以不用管,实际上系统已经帮你把 deb 包生成好了。
在你的工程目录的 Packages 下有一个 deb 包,就是那个。
如果你想自己使用 dpkg 打包一个 deb ,也是可以的。在你的工程目录下找到与工程同名的文件夹,那下面有一个 package ,这个文件夹相信看过前面几篇文章的朋友应该不会陌生。使用 dpkg 就可以打包了。打包方式这里不做介绍了。
转载自 http://www.cnblogs.com/xiongwj0910/archive/2012/08/16/2642992.html
针对越狱手机软件开发,由于需要截获系统函数等功能,选择采用 TheOS 编译环境。
一 .TheOS 环境搭建
先要按照步骤一步一步搭建 TheOS 的环境。
这个是很全面的英文方面的 TheOS 的环境搭建和打包工具安装以及一个简单的 TheOS 程序事例。
编译打包的以及在真机上运行测试的方法 没有采用这个教程上说的设置 IP 然后 ssh 连接的方法。
另外需要自己下载一个 class - dunp 最新的工具包,这个工具用于导出库的私有头文件。
下载地址https://github.com/nygard/class-dump
使用如下
下面导出 SPRINGBOARD
打开终端输入
class-dump -H /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.2.sdk/System/Library/CoreServices/SpringBoard.app -o /Users/lkk/Desktop/Spring
这样在用户目录就会生产 SPRINGBOARD 目录。导出的 .h 都放到这了。
class - dump 的完整路径- H 你要导出的框架的完整路径
导出来的头文件可能会又些许小语法错误 自己修改一下。常见的错误例如:
CTmessage.h 导出错误
改正部分 : 把 #import "NSObject.h" 改成 #import <Foundation/NSObject.h>
//@class CTPhoneNumber, NSArray, NSDate, NSDictionary, NSMutableArray, NSMutableDictionary, NSObject<CTMessageAddress, NSCopying>, NSString;
改成
@class NSDictionary, NSDate, NSString, NSMutableDictionary, NSArray, CTPhoneNumber, NSMutableArray;
@protocol CTMessageAddress, NSCopying;
定义部分语法错误改正一下。比如 NSObject<CTMessageAddress><NSCopying> 改成 NSObject<CTMessageAddress,NSCopying>
然后拷贝这个目录到
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.2.sdk/usr/include/SpringBoard/
关于 class - dump 在我的博文中有一篇专门讲述了。
二 . 编译打包
首先安装 dpkg 打包工具
这个是基于 MacPorts 的安装命令,记得先安装 Macports ,网上大把安装教程,这里就不说了,切记别重复安装。安装之前先检查一下是否安装过了。
$ port version 查看
/* 更新 2012 / 11 / 21 Macports 安装遇见的问题以及处理方法 */
之前在公司安装 Macport 的时候没有碰见什么异常,自己回去用自己的本装的时候,发现总是卡在剩余不到一分钟,然后就不动了。
于是在网上查了下解决方案。我的处理方法是,首先重启电脑,然后果断断网,再安装。
这个时候瞬间就装完了。装完之后,再升级。
下载地址是 http://distfiles.macports.org/MacPorts/
自己选一个合适的版本下载。
断网安装之后,打开控制台,输入
sudo port -v selfupdate
更新 Macport 。
更新完毕之后就可以了。
/* 更新 2012 / 11 / 21 Macports 安装遇见的问题以及处理方法 end*/
以下是安装 dpkg 的命令
sudo port install dpkg
这个执行之后如果报错
Error:
Error: No valid Xcode installation is properly selected.
Error: Please use xcode-select to select an Xcode installation:
Error: sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer # version 4.4
Error:
Warning: xcodebuild exists but failed to execute
Warning: Xcode does not appear to be installed; most ports will likely fail to build.
就直接执行 sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer 重新指定一下路径
三 . 了解 TheOS 生成的 makeFile 的文件中各行的意思
makefile 文件内容剖析
include theos/makefiles/common.mk
告诉 theOS 在编译脚本中包括共同的 make 命令,避免做重复的 make 编译工作
APPLICATION_NAME = fooProject
我们要编译的应用程序的名称。 makefile 将会用这个常量在内部做一些事情。除非你的应用程序改名称,否则不要修改这个值。
[applicationName]_FILES = main.m fooProjectApplication.mm RootViewController.mm
这里是需要编译的文件列表,注意:不要把头文件添加到这里。如果你要添加一个新的 .m 或者 .mm 文件到项目中,确保在这里添加新的文件的名称,否则将不会建立编译连接。
[applicationName]_FRAMEWORKS = UIKit Foundation QuartzCore AudioToolbox CoreGraphics
这里包括你想用到框架的名称
include $(THEOS_MAKE_PATH)/application.mk
更多默认的 用于帮助 TheOS 建立项目
四 . 使用 TheOS 生成第一个 HelloWord 后台程序
打开终端输入
export THEOS=/opt/theos/
export SDKVERSION=4.3 //sdk 版本号,如果是 5.1 就输入 5.1
$THEOS/bin/nic.pl // 执行 TheOS
NIC 1.0 - New Instance Creator
------------------------------
[1.] iphone/application
[2.] iphone/library
[3.] iphone/preference_bundle
[4.] iphone/tool
[5.] iphone/tweak
Choose a Template (required): 5
Project Name (required): WelcomeWagon
Package Name [com.yourcompany.welcomewagon]:
Author/Maintainer Name [Brandon Trebitowski]:
MobileSubstrate Bundle filter [com.apple.springboard]:
Instantiating iphone/tweak in welcomewagon/...
Done.
这里选择了 5,5 是一个后台程序。接下来我们要做的是当系统开机时候弹出 HelloWorld 字样的 Alert 框。
这里我们要用到 hook (钩子)钩取系统开机时候调用的其中一个函数 在那个函数中插入我们的 Alert 。
%hook and %end
%hook Springboard
// overwrite methods here
%end
% hook 后面跟一个类名% hook 要与% end 配对使用中间为你想要截获的这个类的函数。
打开 Tweak.xm 添加如下代码
#import <SpringBoard/SpringBoard.h>
%hook SpringBoard
-(void)applicationDidFinishLaunching:(id)application {
%orig;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Welcome"
message:@"Hello World!"
delegate:nil
cancelButtonTitle:@"Thanks"
otherButtonTitles:nil];
[alert show];
[alert release];
}
%end
%orig; 功能是执行这个函数原来的动作。如果你想完完全全禁止某个函数的功能,不使用 %orig; 即可。
这里使用了 UIKit 框架的 Alert 类,所以需要在 makeFile 文件中添加
WelcomeWagon_FRAMEWORKS = UIKit
这一句。前面又说明 这句的意思 这里不做过多说明了
接下来编译使用命令
打开控制台,进入到你的这个工程文件夹,使用命令
make
然后会生成一个 .obj 的文件夹,在文件夹内又一个 dylib 的包,这个就是我们需要的动态库文件了。把这个 dylib 放入如下图所示路径下。( package / Library / MobileSubstrate / DynamicLibraries/ )
package 文件夹是自己创建的(由于这里我偷了个懒直接从开源项目里面搬过来了,所以那个 preferenceLoder 文件夹没用到),自己生成的工程是没有,为了让 dylib 和 plist 安装到系统指定文件夹目录下(/ Library / MobileSubstrate / DynamicLibraries/ )。使用 iFile 等等的文件管理工具 可以看见你设备中的文件路径情况。
/* 2012 年 10 月 18 日更新内容*/
另外,那个 DEBIAN 文件夹是需要的,里面放 control 文件即可。 control 文件再你的根目录可以找到。
/* 2012 年 10 月 18 日内容说明更新完毕/
打包成 deb 包
使用 dpkg -b 需要打包的文件夹路径
例如:
我要打包 package 这个文件夹
dpkg -b /Users/ws/Desktop/Theos 目录 /IconRenamer/package
使用这个命令即可生成一个 package.deb 文件在当前路径下
安装测试运行
这里的步骤和网上的一些教程有些不一样,首先在 iphone 上下载 iFile 这个工具。 pc 端下载 pp 助手 91 助手 iTools 等工具将 deb 安装包放置在 iphone 中的任意位置,例如:
使用 iFile 找到 package.deb 这个安装包,点击之后 会有一个安装选项。选择安装即可。然后重启,你的屏幕上就会华丽丽的出现 Hello World !的弹出框了。
这里插一句,我们的一个产品 friendIn 已经上线了, FriendIn 帮你整和所有社交平台的好友最新动态,你可以通过 FriendIn 随时随地关注你关心的朋友的最新动态。
第二弹 hook 的使用
上面只是介绍一种 hook 的使用方法,这里进行详细的介绍。
MobileHooker 用于替换覆盖系统的方法,这个过程被称为 Hooking( 挂钩 ). 将使用到 3 个 API :
IMP MSHookMessage(Class class, SEL selector, IMP replacement, const char* prefix); // prefix should be NULL.
void MSHookMessageEx(Class class, SEL selector, IMP replacement, IMP *result);
void MSHookFunction(void* function, void* replacement, void** p_original);
MSHookMessage() 在 Objective-C 中替换 implementation 。 [class Selector] 通过替换 并返回原来的执行。挂钩一个类的方法,
在 MSHookemessage(EX) 中调用 Objc_getMetaClass 得到提供的元数据和类检索,例如下面的注释。这种动态替换是 Objective-c 的一个功能 . 使用method_setImplementation。 MSHookMmessage() 是线程不安全的,不赞成使用,赞成 MSHookMessageEx()
MSHookFunction() 很像 MSHookMessage() 但是适合于 c/c++ 的函数。 MSHookFunctin() 将写入指令调入指定替换函数,并接会分配一些字节在内存地址,相当于原始切出指令并且跳入原始的挂钩方法。由于 iPhone 系统默认的内存页不能同时写和执行,一个内核补丁必须申请 MSHookFunction() 工作 .
截止 MobileSubstrate 的最新版本, MSHookMessage() 也需要一个内核补丁 调用关闭的挂钩的所有正确方法。
代码示例:
使用 MSHookfunction:
static void (*original_CFShow)(CFTypeRef obj); // a function pointer to store the original CFShow().
void replaced_CFShow(CFTypeRef obj) { // our replacement of CFShow().
printf("Calling original CFShow(%p)...", obj);
original_CFShow(obj); // calls the original CFShow.
printf(" done.\n");
}
...
// hook CFShow to our own implementation.
MSHookFunction(CFShow, replaced_CFShow, &original_CFShow);
// From now on any call to CFShow will pass through replaced_CFShow first.
...
CFShow(CFSTR("test"));
使用 MSHookMessageEX:
static IMP original_UIView_setFrame_;
void replaced_UIView_setFrame_(UIView* self, SEL _cmd, CGRect frame) { // Note the implicit self and _cmd parameters are needed explicitly here.
CGRect originalFrame = self.frame;
NSLog("Changing frame of %p from %@ to %@", self, NSStringFromCGRect(originalFrame), NSStringFromCGRect(frame));
original_UIView_setFrame_(self, _cmd, frame); // Remember to pass self and _cmd.
}
...
MSHookMessageEx([UIView class], @selector(setFrame:), (IMP)replaced_UIView_setFrame_,(IMP *)&original_UIView_setFrame_);
...
myView.frame = CGRectMake(0, 0, 100, 100);
注意,如果你挂钩一个类的方法,有必须放一个元类在类参数中。
MSHookMessageEx(objc_getMetaClass("UIView"), @selector(commitAnimations), replaced_UIView_commitAnimations, (IMP *)&original_UIView_commitAnimations);
这里的 MSHookMessageEx 或者 MSHookMessage 方法等同于 % hook % end 的方法 建议使用% hook % end 对,比较方便和简洁。
这些方法只要是安装好了 TheOS 环境既可以使用。
TheOS 的一些设置 TheOS 默认警告级别很高,把所有的警告当成错误处理,如果想降低警告级别 只需要
TheOS 设置警告等级,默认是把警告当成错误处理
Now, all we need to do is fix Theos's treatment of errors.
In Makefile, add the following line BEFORE EVERYTHING:
GO_EASY_ON_ME = 1
This tells Theos not to treat warnings as errors. It removes the -Werror flag from the compiler arguments. We are ready to build the tweak!
基本上就这些内容了,虽然看起来很简单,但是寻找函数的工作是很艰难的。技术点就是是通过 hook 来钩取类方法。主要工作量在于猜测系统调用了什么函数。
由于 TheOS 开发界面不怎么好,还需要自己管理 makefile 文件,这里说一下 iOSOpenDev 这个环境,基于 Xcode 创建模板和编译打包。相信对于 makefile 不怎么熟悉的朋友比较倾向于使用这个。下面来说一下安装步骤。
一 . 安装
iOSOpenDev 安装步骤
http://www.jailbreaktweak.com/develop-jailbreak-tweaks-tool/41/
iOSOpenDev 安装失败解决方案
https://github.com/kokoabim/iOSOpenDev/wiki/Troubleshoot
指定 xcode 路径
http://icyleaf.com/2012/03/upgrade-xcode-431/
以上是安装步骤以及安装过程中可能出现的问题的解决方法。
二 . 创建一个简单的 HelloWorld 插件
安装好了之后 你会看见如下图的各个模板
这里列举 Logos tweak 工程模板的例子。创建这样一个工程。
创建的工程中有一个 xm 文件,这个文件和 TheOS 中的 xm 文件是一样的,之前给大家的 demo 中的 xm 文件内容可以直接 copy 过来, 可能需要注释几个头文件包含才能编译过。
xm 文件中有这样一段说明
#error iOSOpenDev post-project creation from template requirements (remove these lines after completed) -- \
Link to libsubstrate.dylib: \
(1) go to TARGETS > Build Phases > Link Binary With Libraries and add /opt/iOSOpenDev/lib/libsubstrate.dylib \
(2) remove these lines from *.xm files (not *.mm files as they're automatically generated from *.xm files)
意思是要把 libsubstrate.dylib 添加到工程中 ( 在安装好的 /opt/iOSOpenDev/lib 目录下 ) ,然后把 xm 中的内容清空。 mm 文件的内容会根据 xm 文件中的内容编译后自动生成。
接下来添加 libsubstrate.dylib 到你的工程中去 , 再添加 UIKit 框架。然后让我们来写 helloWorld 把, hook 的使用方法前面的文章中已经有介绍了,这里就不多做说明,直接上代码
再 xm 文件中添加如下代码。
这段代码大家应该不陌生把。之前在写 TheOS 一篇中也是这个例子。
三 . 编译打包
代码写完了,应该进行编译,如下图
product -》 Bulid for -》 profiling
编译时候记得选择自己的设备,每次编译前记得 clean 一下,编译结束之后你会看见一个错误。
Command /bin/sh failed with exit code 1
这个意思是没有成功在设备上运行,这个可以不用管,实际上系统已经帮你把 deb 包生成好了。
在你的工程目录的 Packages 下有一个 deb 包,就是那个。
如果你想自己使用 dpkg 打包一个 deb ,也是可以的。在你的工程目录下找到与工程同名的文件夹,那下面有一个 package ,这个文件夹相信看过前面几篇文章的朋友应该不会陌生。使用 dpkg 就可以打包了。打包方式这里不做介绍了。