在iOS開發(fā)中,詳細(xì)大家對Xcode都不陌生,對lldb也不陌生吧,回想大學(xué)剛畢業(yè)時(shí),第一次出來面試時(shí),面試官問我,在平時(shí)的學(xué)習(xí)和寫代碼的過程中,是否會使用lldb進(jìn)行debug,那會還有點(diǎn)懵,貌似沒使用過lldb工具吧,殊不知,其實(shí)lldb就在我們xcode打斷點(diǎn)后,下方彈出的控制臺,那個(gè)就是lldb,最近一段時(shí)間有時(shí)間學(xué)習(xí),對lldb進(jìn)行了一次更深層次的了解與學(xué)習(xí),lldb是在逆向開發(fā)中不可或缺的一樣神器。
在正向開發(fā)中,我們一般都是通過圖形化界面進(jìn)行斷點(diǎn)的置放,在逆向中,通常都是使用lldb來打斷點(diǎn)。
通過使用?breakpoint 在lldb環(huán)境下,可以對對應(yīng)的函數(shù)名進(jìn)行斷點(diǎn)。
1. breakpoint ?
breakpoint set -n? "objectMothed" (對指定函數(shù)設(shè)置斷點(diǎn))
breakpoint disable ?1.1 ? (對斷點(diǎn)列中1.1斷點(diǎn)進(jìn)行 取消斷點(diǎn)操作)
breakpoint enable ??1.1 ? (對斷點(diǎn)列中1.1斷點(diǎn)進(jìn)行 重啟斷點(diǎn)操作)
breakpoint delete ?1 (在刪除斷點(diǎn)時(shí),只能按組刪除,如果一組中有多個(gè)斷點(diǎn),無法通過1.1方式刪除指定斷點(diǎn), 如無指定 目標(biāo)組數(shù) 則刪除所有斷點(diǎn))
breakpoint list (可查詢當(dāng)前存在多少組斷點(diǎn),并且顯示所有斷點(diǎn)詳情)
通過上面列舉的幾個(gè)AIP 我們來進(jìn)行簡單的操作,詳情,請看下面。
現(xiàn)在來解釋一下,上面我標(biāo)注的三處位置。
1 通過使用?breakpoint set -n "viewDidLoad" ?成功為項(xiàng)目中所有viewDidLoad 函數(shù)打上斷點(diǎn)。并且提示?Breakpoint 1: 343 locations. 這里解釋一下:Breakpoint 1 代表一組斷點(diǎn) ?343 locations 代表 有343處
2 通過使用?breakpoint disable 1.1 成功禁止(關(guān)閉)1.1位置的斷點(diǎn)。
3 通過使用?breakpoint list 查看所有斷點(diǎn),并且打印出?1: name = 'viewDidLoad', locations = 343, resolved = 342, hit count = 0
此處不難看出 name = 'viewDidLoad' 就是我們剛才用?breakpoint 下斷點(diǎn)時(shí)的函數(shù)名稱。locations = 343 (共有343處斷點(diǎn))。但是 resolved = 342 (可生效的斷點(diǎn)有 432處)。 ?此時(shí)我們看看圖中三指的位置(1.1),在hit count = 0 ?后面 還跟著 Options: disabled ,其他斷點(diǎn)都是沒有跟?Options: disabled,這個(gè)就是我們上面通過?breakpoint disable 1.1 禁止的斷點(diǎn)(也就是未生效斷點(diǎn),可通過 breakpoint enable 1.1 使該斷點(diǎn)生效)。
在此順便提一下 1.1中?address = 0x00000002340c30a8(這是該函數(shù)的內(nèi)存地址,因?yàn)閤code在編譯時(shí)就將該函數(shù)加載入內(nèi)存了)
我們還可以通過?breakpoint help 來獲取?breakpoint 相關(guān)方法介紹 和 使用。
在下斷點(diǎn)時(shí),我們是使用 breakpoint set -n "viewDidLoad"來設(shè)置的,我們同樣可以使用?help breakpoint set 來查看 set中有多少方法可以使用
一個(gè)set 就包含了這么多東西,我靠( ‵o′)凸,還是全英文的,各位有興趣的就自行了解一下就行了。不過里面的方面是經(jīng)常會使用到的,后續(xù)在使用的時(shí)候在跟大家慢慢列舉和說明。
breakpoint set -r viewDidLoad 該方法是使用正則表達(dá)式,在項(xiàng)目中遍歷所有包含有viewDidLoad字段的函數(shù)名稱,為其打上斷點(diǎn)。
Tisp:所有 breakpoint set 都能簡寫為 b 。例如?breakpoint set -r viewDidLoad 可以簡化成 b -r?viewDidLoad.
2 bt
? ??使用LLDB能在堆棧中查看信息,在斷點(diǎn)后,可以使用bt 來打印堆棧的調(diào)用信息。?
在查看堆棧時(shí),還能使用 up down ?等命令 去到上一個(gè)堆棧信息中。
如果 我們要查看當(dāng)前堆棧中,某個(gè)詳細(xì)堆棧中的信息,我們可以使用 frame select '堆棧編號'
在這個(gè)實(shí)例中,我定位到當(dāng)前堆棧的第39行,使用?frame select 39 后,我們能從當(dāng)中獲取到一些信息,在逆向中時(shí)候用時(shí),顯示的都是匯編語言,在自己項(xiàng)目中時(shí),這里出現(xiàn)的是源碼。
Tisp 在我們定位到某個(gè) 函數(shù)時(shí),可以使用?frame variable 來獲取當(dāng)前函數(shù)調(diào)用參數(shù)信息。
當(dāng) 我們想給對象的某個(gè)屬性添加斷點(diǎn)時(shí),我們可以使用?watchpoint set expression + 對象屬性的內(nèi)存地址,當(dāng)該屬性發(fā)生改變時(shí),就會觸發(fā)該斷點(diǎn),讓我們來詳細(xì)看看下圖。
watchpoint set expression +對象屬性的內(nèi)存地址后,顯示已經(jīng)成功添加一個(gè)內(nèi)存斷點(diǎn)。這時(shí)我們使用c跳過當(dāng)前斷點(diǎn)后,我們進(jìn)行對象屬性值的改變,這時(shí)就會觸發(fā)已經(jīng)設(shè)置好的內(nèi)存斷點(diǎn),并且在斷點(diǎn)時(shí),還是打印出了 old value 和 new value 并在后面附帶出內(nèi)存地址 ,我們通過常用的lldb命令 PO 打印內(nèi)存地址中的參數(shù),在此,我們是否想到了跟開發(fā)中KVO有點(diǎn)類似??KVO同樣有?old value 和 new value?
同樣的,我們可以為斷點(diǎn)添加運(yùn)行代碼,讓我們來看看下文。
breakpoint command add + 斷點(diǎn)組數(shù) 為該斷點(diǎn)添加,并提示?Enter your debugger command(s).? Type 'DONE' to end.
當(dāng)你在最后寫入DONE時(shí),結(jié)束該允許代碼添加。
同樣的,我們也可以刪除我們編寫的內(nèi)存代碼,查看斷點(diǎn)中內(nèi)存組數(shù)。
使用?breakpoint command list 5 查看 內(nèi)存斷點(diǎn)中相關(guān)的代碼。
使用?breakpoint command delete 5 刪除 內(nèi)存斷點(diǎn)中相關(guān)的代碼。
3?target stop-hook?
在執(zhí)行斷點(diǎn)時(shí),有時(shí),我們需要在觸發(fā)斷點(diǎn)時(shí),順帶打印一些信息,例如函數(shù)的參數(shù)。這時(shí),我們就可以使用?target stop-hook ?,接下來讓我們使用help 來了解一下?target stop-hook 有哪些功能呢。
這個(gè)?target stop-hook 里面的內(nèi)容結(jié)構(gòu)跟breakpoint 結(jié)構(gòu)類似, 增刪查禁啟,細(xì)心的小伙伴不難發(fā)現(xiàn),這其中的用法基本都是一樣的,在我看來 這里面除了需要仔細(xì)研究 add 中是否有其他構(gòu)造形式,其他幾個(gè)用法 都比較單一。
這時(shí),我們來試試?target stop-hook add help 看看 add里面有沒有更深層次的東西。
當(dāng)我們在lldb中輸入?target stop-hook add help 時(shí) 會發(fā)現(xiàn) :Enter your stop hook command(s).? Type 'DONE' to end.再次出現(xiàn)內(nèi)存代碼塊命令模式。(我在里面一頓操作猛如虎,暫時(shí)還不知道如何觸發(fā),后期研究到了再回來改寫一下。)
從上面得知?target stop-hook add help 不行,那我們就換種寫法,help?target stop-hook add 此時(shí)lldb終于迎來我們熟悉的界面了。
在此就不一一翻譯了,有興趣研究的小伙伴,私下去研究一下。后續(xù),我有用到的也會更新上來。
Tisp:如果有些常用的lldb語句,在每次一次啟動后,都要手動敲進(jìn)去是不是很麻煩。??在此,我們可以使用預(yù)加載文件,當(dāng)我們項(xiàng)目跑起來的時(shí)候,就會自動把lldb語句加載入當(dāng)期項(xiàng)目中,接下來,讓我們一起來了解一下。
首先,在我們的系統(tǒng)的根目錄下 查找一下 看看是否存在 ".lldbinit" 文件(由于.開頭的文件都是隱藏文件,還需打開文件夾隱藏文件顯示才能看到),如果沒有我們可以使用 終端命令在跟目錄下創(chuàng)建一個(gè).?
1.?touch .lldbinit
2. open .lldbinit ? 打開.lldbinit文件,然后把 示例代碼? target stop-hook add -o "frame variable" ?放入文件中 command + S 保存,這是重新運(yùn)行項(xiàng)目就會發(fā)現(xiàn)控制臺會自己動把??target stop-hook?add -o "frame variable" 添加進(jìn)入。(注:然后是剛創(chuàng)建 .lldbinit 的 則需要完全關(guān)閉Xcode,重新打開才能生效。)