歡迎閱讀iOS逆向系列(按序閱讀食用效果更加)html
平常開發中常常會用到LLDB調試
,可能用的最多的命令就是po
,而在逆向領域中根本不可能讓你在代碼中下斷點調試,因而乎LLDB
就成了很是重要的手段express
LLDB
(Low Lever Debug)的縮寫,是默認內置於XCode的動態調試工具,它與LLVM編譯器一塊兒,存在於主窗口底部的控制檯中,可以帶給咱們更豐富的流程控制和數據檢測的調試功能sass
標準的LLDB提供了一組普遍的命令,旨在與老版本的GDB命令兼容。除了使用標準配置外,還能夠很容易的自定義LLDB以知足實際須要安全
<command> [<subcommand> [<subcommand>...]] <action> [-options [option-value]] [argument[argument...]]
複製代碼
<command>
(命令)和<subcommand>
(子命令):LLDB調試命令的名稱<action>
:執行命令的操做<options>
:命令選項<arguement>
:命令的參數[]
:表示命令是可選的,能夠有也能夠沒有好比breakpoint set -n test
bash
command
:breakpoint表示斷點命令action
:set表示設置斷點option
:-n表示根據方法name設置斷點arguement
:test表示方法名爲testLLDB命令都是在進入LLDB狀態(運行狀態下點擊「暫停符號」)才能使用生效的 微信
where
是斷點所在處address
是斷點地址option disable
斷點被禁用(lldb) breakpoint list
複製代碼
// 設置c函數的斷點
(lldb) breakpoint set -n cMethod
// 設置oc函數的斷點
(lldb) breakpoint set -n "[ViewController ocMethod1]"
複製代碼
(lldb) breakpoint set -n "[ViewController ocMethod1]" -n "[ViewController ocMethod2]" -n "[ViewController ocMethod3]"
複製代碼
// 禁用
(lldb) breakpoint disable 1
// 啓用
(lldb) breakpoint enable 1
複製代碼
// 禁用
(lldb) breakpoint disable 1.1
// 啓用
(lldb) breakpoint enable 1.1
複製代碼
(lldb) breakpoint delete
複製代碼
(lldb) breakpoint delete 1.1
複製代碼
(lldb) breakpoint set --selector touchesBegan:withEvent:
複製代碼
(lldb) breakpoint set --file ViewController.m --selector touchesBegan:withEvent:
複製代碼
(lldb) breakpoint set -r ocMethod
複製代碼
(lldb) c
複製代碼
// 查看LLDB指令幫助
(lldb) breakpoint help
// 查看LLDB的breakpoint幫助
(lldb) breakpoint help
複製代碼
LLDB
的斷點列表中,但LLDB
的斷點不會出如今Xcode的斷點列表處LLDB
命令來操做,但LLDB
下的斷點只能經過LLDB
來操做命令 | 意義 | 簡寫 |
---|---|---|
breakpoint list | 查看斷點列表 | breakpoint l |
breakpoint set -n cMethod | 設置單個斷點 | b -n cMethod |
breakpoint set -n "[ViewController ocMethod1]" -n "[ViewController ocMethod2]" |
設置一組斷點 | b -n "[ViewController ocMethod1]" -n "[ViewController ocMethod2]" |
breakpoint set --selector touchesBegan:withEvent: | 設置某一個方法的斷點 | b -selector touchesBegan:withEvent: |
breakpoint set --file ViewController.m --selector touchesBegan:withEvent: | 設置某文件下某一個方法的斷點 | b -f ViewController.m --selector touchesBegan:withEvent: |
breakpoint set -r ocMethod | 設置全部匹配方法名的斷點 | b -r ocMethod |
breakpoint enable 1 | 啓用某一組斷點 | breakpoint en 1 |
breakpoint disable 1 | 禁用某一組斷點 | breakpoint dis 1 |
breakpoint enable 1.1 | 啓用某一個斷點 | breakpoint en 1.1 |
breakpoint disable 1.1 | 禁用某一個斷點 | breakpoint dis 1.1 |
breakpoint delete | 刪除全部斷點 | breakpoint d |
continue | 退出LLDB模式 | c |
next | 單步運行,將子函數當作總體一塊兒執行 | n |
stpe | 單步運行,將子函數當作總體一塊兒執行 | s |
關於簡寫:dom
b
:breakpoint set
l
:list
-n
:--name
--f
:--file
dis
:disable
en
:enable
前文中提到關於開發中最經常使用的po
指令,在LLDB
中並非print -out
的意思,實際上是expression --object-
函數
p
:做爲expression
的縮寫,意指表達執行的意思o
:則是object
的縮寫(經過help expression
查看指令)po
:執行對象——輸出該對象的信息
既然知道了p指令有執行代碼的做用,接下來就來玩一下工具
動態修改背景顏色(筆者在machOS 10.15.5+Xcode11上並不能成功)post
p self.view.backgroundColor = [UIColor redColor];
動態建立對象並賦值
FXPerson *p
p self.p = [FXPerson new]; self.p.name = @"Felix";
接下來在如下代碼中進行調試,點擊屏幕依次調用test
、test1
、test2
,在test2
處打下斷點
- (void)testWithStr:(NSString *)str {
NSLog(@"test");
[self test1WithStr:str];
}
- (void)test1WithStr:(NSString *)str {
NSLog(@"test1");
[self test2WithStr:str];
}
- (void)test2WithStr:(NSString *)str {
NSLog(@"test2");
NSLog(@"%@", str);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self testWithStr:@"test"];
}
複製代碼
bt
——查看函數調用棧,可以看到函數調用的順序
up/down
——上下挪動函數調用
frame select 數字
——跳轉函數調用(0表示當前方法,2表示2個方法前)
frame variable
——查看當前函數屬性:內存地址、方法名、參數
thread return
——結束當前函數調用,跳轉回上一個調用棧的下一步(當前是跳轉回第30行代碼,準備執行31行代碼)
由此,能夠嘗試在調用中修改參數的值從而完成新值打印
up修改已經調用過的函數參數
up
指令回到上一步,使用p str = @"F";
進行修改
提早修改函數參數
總結:已經執行過的代碼再怎麼回滾也不能隨意修改值,應當提早打下斷點進行修改
內存斷點,顧名思義就是給內存下的斷點
watchpoint set variable self->_p->_name
就能夠給對應的屬性內存下斷點
watchpoint list
來查看內存斷電列表watchpoint delete
進行刪除相似於給程序添加腳本命令,斷點執行也能夠添加命令
breakpoint command add 1
就能夠給指定斷點添加命令DONE
結束斷點命令添加target stop-hook
是一個給全部斷點添加命令的指令——在每次stop的時候去執行一些命令(只對breakpoint、watchpoint有效)
只要target stop-hook add
操做一番,任何斷點都會觸發添加的命令
單條命令能夠簡寫成target stop-hook add -o "frame variable"
(-o
表示單條命令)
一樣的,也可使用target stop-hook list
查看列表
target stop-hook disable
進行禁用
target stop-hook delete
/undisplay 1
進行禁用
接下來介紹一個高階的操做
LLDB啓動的時候就會去加載一個叫作.lldbinit
的文件,在/Users/用戶名
目錄下
若是沒有的話能夠經過vi .lldbinit
建立,而後在文件中添加命令target stop-hook add -o "frame variable"
從新啓動運行Xcode.lldbinit
文件中的命令就會被加載,是個很方便的調試手段!
ASLR
(Address space layout randomization)全稱叫作地址空間配置隨機加載
,是一種防範內存損壞漏洞被利用的計算機安全技術,在各大平臺都有應用
ASLR
經過隨機放置進程關鍵數據區域的地址空間來防止攻擊者能可靠地跳轉到內存的特定位置來利用函數
說得簡單易懂些就是物理地址 = ASLR + 虛擬地址
接下來經過實例來了解一下這個傢伙吧
- (void)fxTest {
NSLog(@"%s", __func__);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self fxTest];
}
複製代碼
cmd+B
編譯生成MachO文件
,使用Hopper打開,找到fxTest
方法
此時拿到了「內存地址」就能夠打下內存斷點來進行調試了,其實0x1340
只是個虛擬地址——只是相對於MachO文件的偏移地址(前面的1表示空段,對地址沒有任何影響)
剛纔說了物理地址 = ASLR + 虛擬地址
,那麼此時的ASLR又是多少呢?
經過image list
就能夠打印出來——0x000000010301e000
就是這個進程的ASLR
(看過dlyd源碼就知道每次運行這個ASLR值都不相同)
實際地址 = 0x000000010ae85000
+ 0x1340
= 0x10AE86340
LLDB這些指令如同Xcode的快捷鍵通常,不掌握也無妨,掌握了就是錦上添花,多了一種調試的思路,便能讓你拉開與同行之間的差距