转载自http://www.cnblogs.com/xiongwj0910/archive/2012/08/16/2642992.html
针对越狱手机软件开发,由于需要截获系统函数等功能,选择采用TheOS编译环境。
一.TheOS环境搭建
http://www.thising.com/blog/2012/01/ios越狱开发起步教程/
之前给的链接由于中文不能识别结果跳错了地址,这里我就直接给中文了。
这里已经说的很详细了,按照步骤一步一步就可以搭建TheOS的环境。
http://brandontreb.com/beginning-jailbroken-ios-development-your-first-tweak/
这个是很全面的英文方面的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就可以打包了。打包方式这里不做介绍了。