iOS逆向工程 iOS工具篇

無情生哥最無情發表於2018-06-19

CydiaSubstrate

絕大部分tweak正常工作的基礎, 它由MobileHooker MobileLoader Safe mode 組成.

MobileHooker

替換系統函式. 也就是所謂的hook, 它主要包含以下兩個函式:

iOS逆向工程 iOS工具篇

(1) 其中MSHookMessageEx作用於OC函式, 通過呼叫method_setImplementation函式將[class selector] 的實現改為replacement, 達到hook的目的. 如 向一個NSString物件傳送hasSuffix訊息, 而做出hasPrefix的操作, 相當於把函式實現換了.

(2) MSHookFunction : 作用於C和C++函式, 通過編寫彙編指令, 在程式執行到function時轉而執行replacement, 同時保持function的指令及其返回地址, 使得使用者可以選擇性地執行function, 並保證程式能夠在執行完replacement後繼續正常執行. 而且MSHookFunction對function的指令總長度是有要求的, function所有指令加起來長度不能太短.(8位元組)

MSHookFunction三個引數作用分別是: 替換的原函式 替換函式 被MobileHooker儲存的原函式.這個體系寫法如下:

iOS逆向工程 iOS工具篇

iOS逆向工程 iOS工具篇

iOS逆向工程 iOS工具篇

MobileLoader

作用是載入第三方dylib. iOS 啟動時, 會由launchd將MobileLoader載入記憶體, 然後MobileLoader會根據dylib的同名plist檔案指定的作用範圍, 有選擇地在不同程式裡通過dlopen函式開啟目錄/Library/MobileSubstrate/DynamicLibraries/ 下的所有dylib.

Safe mode

由於tweak本質是dylib, 寄生在別的程式裡, 一旦出錯可能會導致程式崩潰, 而如果是SpringBoard等系統程式, 則會造成iOS 系統癱瘓, 所以CydiaSubstrate引入Safe mode, 他會捕獲SIGTRAP SIGABRT SIGILL SIGBUS SIGSEGV SIGSYS這六種訊號, 然後進入安全模式. 安全模式裡所有基於CydiaSubstrate的第三方均會被禁用. 而且這個外掛要自己去安裝, 越獄之後是不會自動安裝的, 所以本人之前的手機就白蘋果了, 如果有這個外掛可以避免一些問題的出現, 不過白蘋果也是可以解決的, 通過iTunes刷機就好了, 還是可以恢復正常的, 但系統就是最新的了.

iOS逆向工程 iOS工具篇

Cycript

iOS逆向工程 iOS工具篇
是由saurik推出的一款指令碼語言, 可以看作是Objective-JavaScript .

首先ssh到手機的程式, 然後 cycript, 出現cy# 的提示符就說明已成功啟動cycript.

iOS逆向工程 iOS工具篇

按下control + D , 先退出 Cycript. 如果要測試NSStrign類的 length函式功能, 則可注入任意連線了Foundation庫的程式.

通過程式注入方式呼叫Cycript測試函式的步驟很簡單, 以SpringBoard為例, 首先找到程式名或PID如下:

iOS逆向工程 iOS工具篇

SpringBoard的程式PID是4634, 接下來輸入 cycript-p 4634 或者 cycript-p SpringBoard, 把Cycript注入到SpringBoard, 這時Cycript已經執行到SpringBoard程式裡了.

如果知道物件的記憶體地址, 還可以通過# 操作符來獲取這個物件.

iOS逆向工程 iOS工具篇

如果知道物件的記憶體地址, 還可以通過# 操作符來獲取這個物件.

iOS逆向工程 iOS工具篇

通過choose命令, 可以獲取類物件的地址.

iOS逆向工程 iOS工具篇

LLDB和debugserver

LLDB

全稱 Low Level Debugger 蘋果出品, 內建Xcode中的動態除錯工具, 執行在Mac中. LLDB功能可以概括以下四點:

(1) 在指定的條件下啟動程式

(2) 在指定的條件下停止程式

(3) 在程式停止的時候對程式進行改動, 觀察程式的執行過程有什麼變化.

(4) 在程式停止的時候檢查程式內部發生的事.


debugserver

執行在iOS 上, 它作為服務端, 實際執行LLDB(客戶端)傳過來的命令, 再把執行結果反饋給LLDB顯示給使用者. 所謂的遠端除錯. 預設iOS 上沒有安裝debugserver, 只有裝置連線過Xcode, 並執行除錯過才會把debugserver安裝到iOS 的 /Developer/usr/bin/ 目錄. 因為缺少task_for_pid許可權,所以只能除錯自己的App.

配置debugserver

1.給debugserver減肥

由於本人用的是iPhone5s所以選擇arm64的架構.

首先將未處理過的debugserver拷貝到電腦中(~/debugserver)這裡可以直接用pp助手.

iOS逆向工程 iOS工具篇

然後幫助debugserver減肥.

lipo -thin armv7s ~/debugserver -output ~/debugserver
複製程式碼

2.給debugserver新增task_for_pid許可權

下載xml格式檔案配置資訊 iosre.com/ent.xml 到debugserver同級目錄.

然後執行如下命令:

codesign -s - --entitlements ent.xml -f debugserver
複製程式碼

執行前確保xml檔案和debugserver在同一個資料夾內, 而且執行當前命令時要在當前檔案的資料夾中.

如圖:

iOS逆向工程 iOS工具篇
出現這樣的提示就是成功了.


3.然後將處理過的debugserver拷貝到手機中(/usr/bin/)

這裡沒有覆蓋之前的檔案, 一是因為原版檔案是不可寫的, 無法覆蓋, 二是因為/usr/bin/下的命令無須輸入全路徑就可以執行, 即在任何路徑下執行debugserver都可以啟動處理過的debugserver.

最後還要給debugserver賦予執行許可權命令如下:

chmod +x /usr/bin/debugserver
複製程式碼

如果在電腦終端執行必須要ssh到當前手機才可以.


4.用debugserver啟動或附加程式

  • 啟動程式

      debugserver -x backboard *:1234 /Applications/MobileSMS.app/MobileSMS
    複製程式碼

    debugserver會啟動MobileSMS, 並開啟1234埠, 等待來自任何IP的LLDB接入.

    iOS逆向工程 iOS工具篇

    如果中途出現錯誤, 那麼就有可能是task_for_pid許可權沒加上.

  • 附加程式

     debugserver *:1234 -a "MobileSMS"
    複製程式碼

    iOS逆向工程 iOS工具篇

    其實附加程式和啟動程式區別就是需要手動開啟指定的App.

  • 錯誤

    如果出現如圖:

    iOS逆向工程 iOS工具篇

    說明iOS上的/Developer/目錄下缺少必要的除錯資料.因為沒有在Xcode的Window->Devices選單中新增此裝置, 重新新增即可.


LLDB使用說明

在終端中輸入lldb即可啟動lldb. 如圖:

iOS逆向工程 iOS工具篇

然後執行:

process connect connect://iOSIP:1234
複製程式碼

記得把iOSIP換成自己手機的IP.

成功後如圖:

iOS逆向工程 iOS工具篇

在這之前debugserver啟動過程式或者附加了程式才可以.

所以電腦終端最好開倆個視窗好操作些, 用手機終端則麻煩很多.

這個時候我們就可以開始除錯了, 下面看一下常用的LLDB命令.

1. image list

用於列舉當前程式中的所有模組, 因為ASLR的關係, 每次程式啟動時(就是當你開啟一個應用時), 同一程式的所有模組在虛擬記憶體中的起始地址都會產生隨機偏移. 個人理解其實就是App啟動時在手機記憶體中是有一個起始的記憶體地址的, 而ASLR其實就是讓App每次開啟時的起始地址隨機.

那麼怎麼獲取模組的起始地址呢? 待LLDB連結debugserver後, 先輸入如下口令:

image list -o -f
複製程式碼

iOS逆向工程 iOS工具篇

  • 模組基地址

上圖的輸出中 第一列 [x] 是模組的序號. 第二列是ASLR產生隨機偏移大小. 第三列是模組的全路徑, 括號裡是偏移之後的起始地址. 模組的起始地址術語叫模組基地址.

偏移後模組基地址 = 偏移前模組基地址 + ASLR偏移
複製程式碼

iOS逆向工程 iOS工具篇

如上圖MobileSubstrate.dylib的偏移前模組基地址 = 0x0000000104910000 - 0x0000000104910000 = 0

那這個0哪裡來的呢? 我們把MobileSubstrate.dylib放到IDA中.

iOS逆向工程 iOS工具篇

把View-A拉到最上面看到的第一行, 其中0就是我們計算後的偏移前基地址.

iOS逆向工程 iOS工具篇

  • 符號基地址

    偏移後符號的基地址 = 模組ASLR偏移 + 符號基地址

    如果是偏移前只要減去ASLR偏移即可.

    符號偏移前基地址可以在IDA中根據符號來獲取

    只要知道偏移前基地址從IDA看, ASLR偏移從LLDB看就可以了.

2. breakpoint

和Xcode中的斷點一樣, 只不過這裡不是圖形工具而已. 一般逆向工程中用到的:

b function 

在函式的起始位置設定斷點

br s –a address

br s –a 'ASLROffset+address'

在地址處設定斷點
複製程式碼

以我自己新建Xocde工程專案設定函式[ViewController buttonAction:]斷點為例:

iOS逆向工程 iOS工具篇

(1) 用IDA檢視這個專案偏移前的基地址, 把專案二進位制檔案放入IDA中, 定位到buttonAction:方法可以看到:

iOS逆向工程 iOS工具篇

第一條指令   SUB    SP, SP, #0x30 偏移前的基地址是0x100006728.  
複製程式碼

(2) 通過LLDB檢視ASLR偏移 0xa8000

iOS逆向工程 iOS工具篇

(3) 設定並觸發斷點:

指令的偏移後基地址 = 0x100006728 + 0xa8000 = 0x1000ae728

在LLDB中設定斷點

br s -a 0x1000ae728
複製程式碼

iOS逆向工程 iOS工具篇

其中Breakpoint後面的1是斷點的序號, 以後會用到.

然後我們點選螢幕上的按鈕觸發斷點.

iOS逆向工程 iOS工具篇

列印的是一些方法的資訊, 當程式停下來後我們可以用c命令繼續執行.

還可以通過br dis 和 br en 和 br del 來禁用 啟用 刪除斷點.

如果是禁用所有斷點則執行

br dis
複製程式碼

禁用某個斷點在後面加上斷點的序號

br dis 1
複製程式碼

同理啟用和刪除斷點也是一樣.

br en  
br del
複製程式碼

另外一個很有用的命令就是在斷點觸發前執行預先設定的指令, 它的用法如下:

br com add 1
複製程式碼

然後出現如圖:

iOS逆向工程 iOS工具篇

其中po i 是要執行的指令, 而DONE是退出設定指令. 數字4是斷點的序號.

這裡設定了一條指令, 然後我們點選按鈕觸發方法如圖:

iOS逆向工程 iOS工具篇

這個時候i的值是1.

這個命令一般用於自動觀察某個斷點觸發時的上下文變化, 後面會用到.

3. print

LLDB主要功能之一是在程式停止的時候檢查程式內部發生的事, 而這個功能是通過print命令完成的, 他可以列印某處的值. 以我本人最近開發的程式 -[HomePageController tableView:didSelectRowAtIndexPath:] 方法為例演示一系列用法.

po   $r0    輸出r0對應的值
p    $r0    輸出r0值的型別以及命令結果
p/x  $r0    輸出r0的十六進位制值
x/10 $r0    輸出指標r0指向的連續10個字的資料


nexti(ni)   執行下一條機器指令  不會進入函式體
stepi(si)   執行下一條機器指令  會進入函式體
** 進不進入函式體的意思就是你再方法中呼叫其他方法, 而當斷點到這個方法的時候, 如果是上面的指令會跳轉的這個呼叫的方法裡面, 而下面的指令不會進入. ** 


register write  r0  1   給暫存器r0賦值為1


複製程式碼

相關文章