iOS 逆向11 -- 動(dòng)態(tài)調(diào)試

動(dòng)態(tài)調(diào)試

  • 將程序運(yùn)行起來,通過下斷點(diǎn),打印等方式,查看參數(shù),返回值,函數(shù)調(diào)用流程等。

Xcode調(diào)試App的原理

  • Xcode編譯器的發(fā)展歷程:GCC -> LLVM
  • Xcode調(diào)試器的發(fā)展歷程:GDB -> LLDB
  • debugServer剛開始時(shí)存放在Mac的Xcode里面,其路徑為:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/13.3/DeveloperDiskImage.dmg/usr/bin/debugServer
  • 當(dāng)Xcode識(shí)別到真機(jī)設(shè)備時(shí),Xcode會(huì)自動(dòng)將debugServer安裝到真機(jī)上,安裝路徑為:/Developer/usr/bin/debugServer
  • Xcode調(diào)試的局限性:一般情況下,只能調(diào)試 通過Xcode安裝的App

動(dòng)態(tài)調(diào)試任意App

debugServer的權(quán)限問題
  • 默認(rèn)情況下,真機(jī)設(shè)備路徑下:/Developer/usr/bin/debugServer的debugServer缺少一定的權(quán)限,只能調(diào)試通過Xcode安裝的App,無法調(diào)試其他App;
  • 若希望調(diào)試其他App,需要對(duì)debugServer重新簽名,簽上兩個(gè)調(diào)試相關(guān)的權(quán)限,如下所示:
    • get-task-allow
    • task_for_pid_allow
如何給debugServer簽上權(quán)限
  • 手機(jī)必須越獄;
  • 通過IFunBox,定位到/Developer/usr/bin/debugServer文件路徑下,將debugServer文件拷貝到Mac桌面;
  • Mac需要安裝ldid簽名工具,利用ldid指令導(dǎo)出debugServer文件以前的簽名權(quán)限文件debugServer.entitlements,終端指令為:ldid -e debugServer > debugServer.entitlements
  • 然后在導(dǎo)出的權(quán)限文件debugServer.entitlements中,手動(dòng)添加get-task-allowtask_for_pid_allow這兩個(gè)權(quán)限選項(xiàng);
  • 然后終端執(zhí)行ldid SdebugServer.entitlements debugServer,即將權(quán)限文件debugServer.entitlements簽到debugServer文件中;
  • 由于/Developer/usr/bin/debugServer文件路徑是只讀的,不能操作此文件路徑下的文件,所以將剛重新簽名權(quán)限的debugServer文件,拷貝到/usr/bin文件路徑下;
  • 最后終端輸入:chmod +x /usr/bin/debugServer 賦予操作權(quán)限;
讓debugServer附加到某個(gè)App進(jìn)程
  • 終端在iPhone環(huán)境下,執(zhí)行命令:debugserver *: 端口號(hào) -a 進(jìn)程名稱
  • *: 端口號(hào):使用iPhone的某個(gè)端口號(hào)啟動(dòng)debugserver服務(wù)(只要不是保留端口號(hào)就可以)
  • -a 進(jìn)程名稱:輸入App的進(jìn)程名稱或者進(jìn)程ID
在Mac上啟動(dòng)LLDB,遠(yuǎn)程連接iPhone上的debugserver服務(wù)
  • 啟動(dòng)LLDB:在Mac環(huán)境下,輸入lldb
  • 連接debugserver服務(wù):在Mac環(huán)境下,輸入process connect connect ://手機(jī)的ip地址:debugserver服務(wù)端口號(hào)
  • 使用LLDB指令讓目標(biāo)程序繼續(xù)執(zhí)行:在Mac環(huán)境下,輸入c
  • 接下來就可以使用LLDB指令調(diào)試目標(biāo)App了。
LLDB指令
  • help:幫助提示,直接輸入help,會(huì)打印出所有LLDB指令;
  • help LLDB指令:例如help breakpoint,會(huì)打印出breakpoint的所有子命令,例如上面的set子命令;
  • expression 命令選項(xiàng) -- 執(zhí)行表達(dá)式,例如 expression -O -- self.view
    • --命令選項(xiàng)結(jié)束符,表示命令選項(xiàng)已經(jīng)設(shè)置完畢,如沒有命令選項(xiàng)可以直接省略;
    • expression -- 對(duì)象,expression 對(duì)象,e 對(duì)象print 對(duì)象,p 對(duì)象,call 對(duì)象這些指令的效果一樣,打印目標(biāo)對(duì)象;
    • expression -O -- 對(duì)象po 對(duì)象的效果一樣;
    • 總結(jié):expression不僅僅是打印,后面還能跟表達(dá)式,執(zhí)行表達(dá)式;
    • expression self.view.layer.backgroundColor = [UIColor redColor].CGColor設(shè)置控制器的顏色為紅色,可以在運(yùn)行中動(dòng)態(tài)調(diào)試;
  • thread backtrace:打印當(dāng)前函數(shù)的調(diào)用堆棧,可簡(jiǎn)寫為bt;
  • thread return:讓當(dāng)前函數(shù)直接返回某個(gè)值,不會(huì)執(zhí)行斷點(diǎn)后面的代碼;
  • frame variable:打印出當(dāng)前棧楨函數(shù)內(nèi)部的所有變量;
流程控制
  • thread continue:跳過當(dāng)前斷點(diǎn),繼續(xù)執(zhí)行,如果有下一個(gè)斷點(diǎn)會(huì)卡住在下一個(gè)斷點(diǎn),可簡(jiǎn)寫為continuec
  • thread step-over:?jiǎn)尾綀?zhí)行;如果遇到函數(shù)調(diào)用,會(huì)直接過掉即將函數(shù)調(diào)用看成單行代碼執(zhí)行,可簡(jiǎn)寫為nextn
  • thread step-in:?jiǎn)尾綀?zhí)行,如果遇到函數(shù)調(diào)用,會(huì)進(jìn)入到函數(shù)內(nèi)部執(zhí)行,可簡(jiǎn)寫為steps
  • thread step-out:直接執(zhí)行完當(dāng)前函數(shù)的所有代碼,返回到上一個(gè)函數(shù),可簡(jiǎn)寫為finish
  • 上面的四個(gè)指令與Xcode中的按鈕對(duì)應(yīng)關(guān)系如下:
Snip20210707_13.png
  • thread step-inst-over:匯編指令級(jí)別的單步執(zhí)行,可簡(jiǎn)寫為nextini
  • thread step-inst:匯編指令級(jí)別的單步執(zhí)行,如果遇到函數(shù)調(diào)用,會(huì)進(jìn)入到函數(shù)內(nèi)部執(zhí)行,可簡(jiǎn)寫為stepisi
普通斷點(diǎn)操作
  • breakpoint set -r 正則表達(dá)式:例如breakpoint set -r test,給函數(shù)名包含test字符串的所有函數(shù)添加斷點(diǎn);
  • breakpoint set -s 動(dòng)態(tài)庫(kù) -n 函數(shù)名:給指定動(dòng)態(tài)庫(kù)的執(zhí)行函數(shù)添加斷點(diǎn);
  • breakpoint set -a 函數(shù)內(nèi)存地址:給對(duì)應(yīng)的內(nèi)存地址的函數(shù)添加斷點(diǎn);
  • breakpoint list:打印出工程中的所有斷點(diǎn);
  • breakpoint disable 斷點(diǎn)編號(hào):禁用指定斷點(diǎn);
  • breakpoint enable 斷點(diǎn)編號(hào):?jiǎn)⒂弥付〝帱c(diǎn);
  • breakpoint delete 斷點(diǎn)編號(hào):刪除指定斷點(diǎn);
  • breakpoint command add 斷點(diǎn)編號(hào):給指定的斷點(diǎn)添加額外的執(zhí)行指令;如下所示:
Snip20210707_15.png
  • 當(dāng)執(zhí)行到第18行時(shí),斷點(diǎn)斷住,然后控制臺(tái)執(zhí)行下面的指令,
Snip20210707_16.png
  • breakpoint set -n "-[ViewController touchesBegan:withEvent:]"

  • breakpoint command add 2

  • expression self.view.layer.backgroundColor = [UIColor redColor].CGColor

  • 過掉當(dāng)前斷點(diǎn),點(diǎn)擊屏幕,就會(huì)執(zhí)行在touchesBegan函數(shù)停住,并執(zhí)行上面添加的三條指令;

  • breakpoint command list 斷點(diǎn)編號(hào):打印指定斷點(diǎn)添加的所有執(zhí)行指令;

  • breakpoint command delete 斷點(diǎn)編號(hào):刪除指定斷點(diǎn)添加的所有執(zhí)行指令;

內(nèi)存斷點(diǎn)
  • watchpoint set variable self->_age:監(jiān)聽成員變量_age的內(nèi)存,只要_age發(fā)生變化就會(huì)斷住;
  • watchpoint set expression 對(duì)象的內(nèi)存地址:功能同上;
  • watchpoint list:打印工程中所有的內(nèi)存斷點(diǎn)
  • watchpoint delete 內(nèi)存斷點(diǎn)編號(hào):刪除指定內(nèi)存斷點(diǎn);
  • watchpoint disable 內(nèi)存斷點(diǎn)編號(hào):禁用指定內(nèi)存斷點(diǎn);
  • watchpoint enable 內(nèi)存斷點(diǎn)編號(hào):?jiǎn)⒂弥付▋?nèi)存斷點(diǎn);
  • watchpoint command add 內(nèi)存斷點(diǎn)編號(hào):給指定的內(nèi)存斷點(diǎn)添加額外的執(zhí)行指令;
  • watchpoint command list 內(nèi)存斷點(diǎn)編號(hào):打印指定內(nèi)存斷點(diǎn)添加的所有執(zhí)行指令;
  • watchpoint command delete 內(nèi)存斷點(diǎn)編號(hào):刪除指定內(nèi)存斷點(diǎn)添加的所有執(zhí)行指令;
與模塊鏡像相關(guān)
  • image list:打印工程中引用的所有的模塊,也就是動(dòng)態(tài)庫(kù)文件,也可稱之為鏡像;
  • image lookup -t 類型:查看某個(gè)類型的信息,例如:image lookup -t int
  • image lookup -a 內(nèi)存地址:根據(jù)內(nèi)存地址查找在模塊中的位置,例如崩潰的代碼行定位;
  • image lookup -n 符號(hào)或函數(shù)名:查找某個(gè)符號(hào)或者函數(shù)的位置;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容