iOS逆向工程 iOS工具篇

CydiaSubstrate

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

MobileHooker

替換系統函數. 也就是所謂的hook, 它主要包含如下兩個函數:安全

(1) 其中MSHookMessageEx做用於OC函數, 經過調用method_setImplementation函數將[class selector] 的實現改成replacement, 達到hook的目的. 如 向一個NSString對象發送hasSuffix消息, 而作出hasPrefix的操做, 至關於把函數實現換了.bash

(2) MSHookFunction : 做用於C和C++函數, 經過編寫彙編指令, 在進程執行到function時轉而執行replacement, 同時保持function的指令及其返回地址, 使得用戶能夠選擇性地執行function, 並保證進程可以在執行完replacement後繼續正常運行. 並且MSHookFunction對function的指令總長度是有要求的, function全部指令加起來長度不能過短.(8字節)架構

MSHookFunction三個參數做用分別是: 替換的原函數 替換函數 被MobileHooker保存的原函數.這個體系寫法以下:app

MobileLoader

做用是加載第三方dylib. iOS 啓動時, 會由launchd將MobileLoader載入內存, 而後MobileLoader會根據dylib的同名plist文件指定的做用範圍, 有選擇地在不一樣進程裏經過dlopen函數打開目錄/Library/MobileSubstrate/DynamicLibraries/ 下的全部dylib.ssh

Safe mode

因爲tweak本質是dylib, 寄生在別的進程裏, 一旦出錯可能會致使進程崩潰, 而若是是SpringBoard等系統進程, 則會形成iOS 系統癱瘓, 因此CydiaSubstrate引入Safe mode, 他會捕獲SIGTRAP SIGABRT SIGILL SIGBUS SIGSEGV SIGSYS這六種信號, 而後進入安全模式. 安全模式裏全部基於CydiaSubstrate的第三方均會被禁用. 並且這個插件要本身去安裝, 越獄以後是不會自動安裝的, 因此本人以前的手機就白蘋果了, 若是有這個插件能夠避免一些問題的出現, 不過白蘋果也是能夠解決的, 經過iTunes刷機就行了, 仍是能夠恢復正常的, 但系統就是最新的了.iphone

Cycript

是由saurik推出的一款腳本語言, 能夠看做是Objective-JavaScript .

首先ssh到手機的進程, 而後 cycript, 出現cy# 的提示符就說明已成功啓動cycript.函數

按下control + D , 先退出 Cycript. 若是要測試NSStrign類的 length函數功能, 則可注入任意鏈接了Foundation庫的進程.工具

經過進程注入方式調用Cycript測試函數的步驟很簡單, 以SpringBoard爲例, 首先找到進程名或PID以下:測試

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

若是知道對象的內存地址, 還能夠經過# 操做符來獲取這個對象.

若是知道對象的內存地址, 還能夠經過# 操做符來獲取這個對象.

經過choose命令, 能夠獲取類對象的地址.

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助手.

而後幫助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在同一個文件夾內, 並且執行當前命令時要在當前文件的文件夾中.

如圖:

出現這樣的提示就是成功了.


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接入.

    若是中途出現錯誤, 那麼就有多是task_for_pid權限沒加上.

  • 附加進程

    debugserver *:1234 -a "MobileSMS"
    複製代碼

    其實附加進程和啓動進程區別就是須要手動打開指定的App.

  • 錯誤

    若是出現如圖:

    說明iOS上的/Developer/目錄下缺乏必要的調試數據.由於沒有在Xcode的Window->Devices菜單中添加此設備, 從新添加便可.


LLDB使用說明

在終端中輸入lldb便可啓動lldb. 如圖:

而後執行:

process connect connect://iOSIP:1234
複製代碼

記得把iOSIP換成本身手機的IP.

成功後如圖:

在這以前debugserver啓動過進程或者附加了進程才能夠.

因此電腦終端最好開倆個窗口好操做些, 用手機終端則麻煩不少.

這個時候咱們就能夠開始調試了, 下面看一下經常使用的LLDB命令.

1. image list

用於列舉當前進程中的全部模塊, 由於ASLR的關係, 每次進程啓動時(就是當你打開一個應用時), 同一進程的全部模塊在虛擬內存中的起始地址都會產生隨機偏移. 我的理解其實就是App啓動時在手機內存中是有一個起始的內存地址的, 而ASLR其實就是讓App每次打開時的起始地址隨機.

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

image list -o -f
複製代碼

  • 模塊基地址

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

偏移後模塊基地址 = 偏移前模塊基地址 + ASLR偏移
複製代碼

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

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

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

  • 符號基地址

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

    若是是偏移前只要減去ASLR偏移便可.

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

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

2. breakpoint

和Xcode中的斷點同樣, 只不過這裏不是圖形工具而已. 通常逆向工程中用到的:

b function 

在函數的起始位置設置斷點

br s –a address

br s –a 'ASLROffset+address'

在地址處設置斷點
複製代碼

以我本身新建Xocde工程項目設置函數[ViewController buttonAction:]斷點爲例:

(1) 用IDA查看這個項目偏移前的基地址, 把項目二進制文件放入IDA中, 定位到buttonAction:方法能夠看到:

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

(2) 經過LLDB查看ASLR偏移 0xa8000

(3) 設置並觸發斷點:

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

在LLDB中設置斷點

br s -a 0x1000ae728
複製代碼

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

而後咱們點擊屏幕上的按鈕觸發斷點.

打印的是一些方法的信息, 當進程停下來後咱們能夠用c命令繼續運行.

還能夠經過br dis 和 br en 和 br del 來禁用 啓用 刪除斷點.

若是是禁用全部斷點則執行

br dis
複製代碼

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

br dis 1
複製代碼

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

br en  
br del
複製代碼

另一個頗有用的命令就是在斷點觸發前執行預先設置的指令, 它的用法以下:

br com add 1
複製代碼

而後出現如圖:

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

這裏設置了一條指令, 而後咱們點擊按鈕觸發方法如圖:

這個時候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


複製代碼
相關文章
相關標籤/搜索