繼續上一篇文章的內容,工具介紹篇:
一、class-dump
簡介:顧名思義,就是用來匯出目標物件的class資訊的工具,私有方法宣告也能匯出來。
原理:利用 Objective-C語言的 runtime 特性,將存 在Mach-O 檔案中的標頭檔案資訊提 出來,並生成對應的 .h 檔案。
使用方法:
1,下載然後將class-dump 複製到“ /usr/bin”目錄下。
2,執行sudo chmod 777 /usr/bin/class-dump”命令賦予其執行許可權。
3,class-dump執行:
1 2 |
class-dump -S -s -H /Applications/Calculator.app -o /Users/zhangdasen/Desktop/test |
4,上面一段程式碼就是匯出Mac下計算器app的標頭檔案,到桌面test資料夾,並且排序,class-dump的一些引數,大家可以自己在命令列輸入class-dump然後回車就有相關說明。
使用注意
從 AppStore 下 的 App 都是經過加密的,可執行檔案被加上了一層”殼”。
class-dump 應付不了這樣的檔案,此時使用 class-dump 看上去會“失效”。還得先用別的工具把殼砸開才行,這個後面會說到。
class-dump下載地址:http://stevenygard.com/projects/class-dump
二、Theos越獄開發工具包
簡介
Theos:是一個越獄開發工具包,由iOS越獄界知名人士Dustin Howett(@DHowett)開發並分享到 GitHub 上。
iOSOpenDev:是整合在 Xcode裡的越獄開發工具, 熟悉Xcode 的朋友可能會對它更感興趣。但逆向工程接觸底層知識較多,很多東西無法自動化,因此推薦使用整合度並不算高的 Theos,當你手動完成一個又一個練習時,對逆向工程的理解一定會更深。
(1) Theos的安裝:
1,設定xcode
假設安裝了3 個 Xcode,並將它們分別命名為 Xcode1.app、Xcode2.app 和 Xcode3.app, 要指定 Xcode3 為活動 Xcode,則執行如下命令 :
1 |
sudo xcode-select -s /Applications/Xcode3.app/Contents/Developer |
2, Theos下載
從 GitHub 上下 Theos, 操作如下:(在終端中執行)
1 2 |
export THEOS=/opt/theos sudo git clone git://github.com/DHowett/theos.git$THEOS |
export THEOS=/opt/theos
這句話是設定環境變數,上面兩句話指的就是git克隆theos到系統的/opt/theos目錄下.小問題:git 克隆下來的theos由於缺少檔案,在後面make packget install 會提示缺少 _Prefix/NullabilityCompat.h 等檔案,需要我們去https://github.com/theos/headers 把這個標頭檔案放到/opt/theos/include目錄中就行了。(可直接克隆到目錄中去)
1 sudo git clone <span class="hljs-symbol">https:</span>/<span class="hljs-regexp">/github.com/theos</span><span class="hljs-regexp">/headers /opt</span><span class="hljs-regexp">/theos/includ</span>不過我這邊已經有一個封好的theos,下面會提到。
3,配置ldid
ldid 是專門用來 名 iOS 可執行檔案的工具,用以在越獄 iOS 中 代 Xcode 自帶的codesign。從 http://joedj.net/ldid 下 ldid,把它放在“ /opt/theos/bin/ ”下,然後用以下命令賦予它可執行許可權:
1 |
sudo chmod 777 /opt/theos/bin/ldid |
4,配置CydiaSubstrate
因為Theos 的一個 bug,它無法自動生成一個有效的 libsubstrate.dylib 檔案,需要手動操作。
在 Cydia 中搜尋安裝“CydiaSubstrate”,然後用 iFunBox 或 scp 等方式將 iOS 上的“/Library/Frameworks/CydiaSubstrate.framework/CydiaSubstrate” 到 OSX 中,將其重新命名為 libsubstrate.dylib 後放到
“ /opt/theos/vendor/lib/libsubstrate.dylib”中, 替換掉無效的檔案即可。
5,dpkg-deb
deb 是越獄開發安裝包的標準格式,dpkg-deb 是一個用於操作 deb 檔案的工具,有了這個工具,Theos 才能正確地把工程打包成為 deb 檔案。
從 https://raw.githubusercontent.com/DHowett/dm.pl/master/dm.pl 下 dm.pl,將其重新命名為 dpkg-deb 後,放到“/opt/theos/bin/”目錄下,然後用以下命令賦予其可執行許可權:
1 |
sudo chmod 777 /opt/theos/bin/dpkg-deb |
Theos操作這些移動檔案設定許可權這些步驟很囉嗦。
鑑於這些,我自己這邊已經封裝了一個整合好的Theos,附帶一個自動下載的小指令碼TheosScript.sh,不需要手動新增ldid、libsubstrate、dpkg-deb等。
指令碼下載地址:https://github.com/DaSens/Theos-Script
進行簡單演示
(2) Theos的用法介紹:
1,更改工作目錄
更改工作目錄至常用的 iOS 工程目錄(如 “ /Users/zhangdasen/Code/”)
注:為何要做這一步呢,因為使用Theos建立的工程,是你在哪個目錄執行的nic.pl啟動的,就會在建立完成後在這個目錄生成建立的Theos專案。
2,建立工程
終端輸入“/opt/theos/bin/nic.pl”,啟動 NIC(New Instance Creator),下面進行簡單演示:
3,簡單說明
上面建立工程輸入了一大堆東西,下面用一張圖來說明:
4,工程檔案說明
建立好工程就會生成四個檔案:
Makefile、Tweak.xm、control、iOSREProject.plist 下面進行簡單說明。
(1) Makefile
Makefile 檔案指定工程用到的檔案、框架、庫等資訊,將整個過程自動化,下圖為裡面內容說明。
下圖是我自己修改過後的Makefile檔案。
補充:
1,匯入 private framework
1 |
iOSREProject_PRIVATE_FRAMEWORKS = private framework name |
2,連結 Mach-O 物件(Mach-O object)
1 |
iOSREProject_LDFLAGS = -lz –lsqlite3.0 –dylib1.o |
(2) Tweak.xm
用 Theos 建立 tweak 工程, 認生成的原始檔是 Tweak.xm。
如果字尾名是單獨一個“ x”,說明原始檔支援 Logos 和 C 語法;
如果字尾名是“ xm ”,說明原始檔支援 Logos 和 C/C++ 語法,與“ m ”和“ mm ”的區別類似。
Tweak.xm 語法眾多,在這裡簡單介紹一些,詳細語法大家可以去看書籍。
● %hook
指定需要 hook 的 class, 必須以 %end 結尾
1 2 3 4 5 6 7 |
%hook SpringBoard - (void)_menuButtonDown:(id)down { NSLog(@"You've pressed home button."); %orig; // call the original _menuButtonDown: } %end |
● %orig該指 在 %hook 內部使用,執行被 (hook)的 數的原始程式碼,如下:
1 2 3 4 5 6 |
%hook SpringBoard - (void)_menuButtonDown:(id)down { NSLog(@"You've pressed home button."); %orig; // call the original _menuButtonDown: } %end |
1 2 3 4 5 |
%hook SBLockScreenDateViewController - (void)setCustomSubtitleText:(id)arg1 withColor:(id)arg2 { %orig(@"iOS 8 App Reverse Engineering", arg2); } %end |
● %group
該指 用於將 %hook 分組,便於程式碼管理及按條件初始化分組(含義 後有 細解 ),必須以 %end 結 ;一個 %group可以包含多個 %hook,所有不 於某個自定義 group 的 %hook會被隱式歸類到 %group _ungrouped 中。
用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
%group iOS7Hook %hook iOS7Class - (id)iOS7Method { id result = %orig; NSLog(@"This class & method only exist in iOS 7."); return result; } %end %end // iOS7Hook %group iOS8Hook %hook iOS8Class - (id)iOS8Method { id result = %orig; NSLog(@"This class & method only exist in iOS 8."); return result; } %end %end // iOS8Hook |
● %init
該指令用於初始化某個 %group,必須在 %hook 或 %ctor 內呼叫;如果帶引數,則初始化指定的 group,如果不帶引數,則初始化 _ungrouped,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#ifndef kCFCoreFoundationVersionNumber_iOS_8_0 #define kCFCoreFoundationVersionNumber_iOS_8_0 1140.10 #endif %hook SpringBoard - (void)applicationDidFinishLaunching:(id)application { %orig; %init; // Equals to %init(_ungrouped) if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_8_0) %init(iOS7Hook); if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0) %init(iOS8Hook); }%end 只有呼叫了 %init,對應的 %group 才能起作用,切 切 ! |
● %new
在 %hook 內部使用,給一個現有 class 加新函式,功能與 class_addMethod 相同。它的用法如下:
1 2 3 4 5 6 |
%hook SpringBoard %new - (void)namespaceNewMethod { NSLog(@"We've added a new method to SpringBoard."); } %end |
● %ctor
tweak的constructor,完成初始化工作;如果不顯式定義,Theos會自動生成一個%ctor,並在其中呼叫 %init(_ungrouped)。因此,
%hook SpringBoard – (void)reboot {
NSLog(@”If rebooting doesn’t work then I’m screwed.”);
%orig;
}
%end
可以成功生效,因為 Theos 隱式定義瞭如下內容:%ctor
1 2 3 |
{ %init(_ungrouped); } |
而
1 2 3 4 5 6 7 |
%hook SpringBoard - (void)reboot{ NSLog(@"If rebooting doesn't work then I'm screwed."); %orig; } %end |
裡的 %hook無法生效,因為這裡顯式定義了%ctor,卻沒有顯式呼叫 %init,
%group(_ungrouped) 不起作用。
%ctor 一般可以用來初始化 %group,以及進行 MSHookFunction 等操作,如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
#ifndef kCFCoreFoundationVersionNumber_iOS_8_0 #define kCFCoreFoundationVersionNumber_iOS_8_0 1140.10 #endif %ctor{ %init; if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_7_0 && kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_8_0) %init(iOS7Hook); if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_8_0) %init(iOS8Hook); MSHookFunction((void *)&AudioServicesPlaySystemSound, (void *)&replaced_AudioServicesPlaySystemSound, (void **)&original_AudioServicesPlaySystemSound); } |
注意,%ctor 不需要以 %end 結 。
● %c
該指 的作用等同於 objc_getClass 或 NSClassFromString,即動態獲 一個類的定義,在 %hook 或 %ctor 內使用。
(3) control檔案
control檔案 錄了deb包管理系統所需的基本資訊,會被打包進deb包裡。
iOSREProject 裡 control 檔案的內容如下:
control 檔案中可以自定義的欄位還有很多,但上面這些資訊就已經足夠了。更全面的
說明可以參閱 debian 的官方網站(http://www.debian.org/doc/debian-policy/ch-controlfields.html)
(3)iOSREProject.plist檔案
簡單來說就是裡面描述了tweak 的作用範圍,也就是需要作用的APP的bundle identifier。
也就是在建立專案的時候填寫的這個地方:
下個文章繼續更新內容 —- 手動HOOK一個自己的APP,和剩餘越獄開發工具簡單介紹。
由於本書筆者還沒看完呢,所以更新會比較慢,或者有段時間不更新,再次說明,整理這些內容只是為了自己方便查閱筆記,順便分享給大家,沒有它意,希望大家支援原版書籍。
iOS逆向知識,千變萬化,無窮無盡,需要學習的太多了,國內文章知識還是比較少,逆向的書籍也是比較少,逆向開發方面的進步也需要我們國人也要努力。
參考書籍: <iOS應用逆向工程-第2版> 沙梓社 吳航 * 著
感謝作者。