由於國內資料較少,並且還非常分散,無序,於是寫了這個分享,希望后來的人不要重新走彎路。本分享詳細的講述了從無到有的整個過程。整理這些花了不少時間,希望轉載請注明
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!
基本上就這些內容了.