iOS逆向工程(八):動態調試 動態調試

動態調試

一、什麼是動態調試

  • 1.動態調試就是將程序運行起來,通過打斷點、打印等方式,查看參數、返回值、函數調用流程等信息
  • 2.之前我們說的靜態分析,就是程序不運行的時候,對程序的可執行文件進行分析,分析頭文件、僞代碼之類的信息
  • 3.學會動態調試之後,我們就可以分析某個程序的整體調用流程了,例如:分析微信搶紅包的時候,就可以知道微信調用了哪些方法去搶紅包,以便我們hook

二、動態調試任意App

第一步:將有權限的debugserver安裝到手機

1/進入目錄
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport

找到手機對應版本,點開dmg;拷貝debugserver備用
/usr/bin/debugserver

2/修改權限
導出權限

$ ldid -e debugserver > debugserver.entitlements

修改內容

溫馨提示->
最好整體copy

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.backboardd.debugapplications</key>
    <true/>
    <key>com.apple.backboardd.launchapplications</key>
    <true/>
    <key>com.apple.frontboard.debugapplications</key>
    <true/>
    <key>com.apple.frontboard.launchapplications</key>
    <true/>
    <key>com.apple.springboard.debugapplications</key>
    <true/>
    <key>com.apple.system-task-ports</key>
    <true/>
    <key>get-task-allow</key>
    <true/>
    <key>platform-application</key>
    <true/>
    <key>run-unsigned-code</key>
    <true/>
    <key>task_for_pid-allow</key>
    <true/>
</dict>
</plist>

編輯後將其合入debugserver【注意-S後面不要空格】

$ ldid -Sdebugserver.entitlements debugserver

3/將編輯完成的文件放入手機的/usr/bin目錄

電腦端操作->

$ scp -r /Users/gn/Desktop/333/debugserver [email protected]:/usr/bin

手機端操作->如果有過操作,需要刪除debugserver

iPhone-7:~ root# rm /usr/bin/debugserver

第二步:讓debugserver與App建立交互

在Mac上打開命令行窗口,讓10011端口與10011端口映射、10010與22端口映射

新建命令行窗口
$ iproxy 10011 10011
新建命令行窗口
$ iproxy 10010 22

在Mac上新建命令行窗口,然後SSH登陸到手機

gndeMacBook-Pro:~ gn$ ssh -p 10010 [email protected]

提示
server端密碼或是其他發生改變的時候。
解決方法一般就需要刪除~/.ssh/known_hosts的東西,然後再登錄即可。

登錄到手機後,啓動手機的debugserver服務,讓其與App建立交互

iPhone-7:~ root# debugserver 127.0.0.1:10011 -a WeChat
debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.106
 for arm64.
Attaching to process WeChat...
Listening to port 10011 for a connection from localhost...
Waiting for debugger instructions for process 0.

第三步:讓debugserver與LLDB建立交互

在Mac上新建命令行窗口

$ lldb  
(lldb) process connect connect://127.0.0.1:10011
Process 1079 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x0000000189d2d198 libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
->  0x189d2d198 <+8>: ret    

libsystem_kernel.dylib`mach_msg_overwrite_trap:
    0x189d2d19c <+0>: mov    x16, #-0x20
    0x189d2d1a0 <+4>: svc    #0x80
    0x189d2d1a4 <+8>: ret    
Target 0: (WeChat) stopped.
(lldb)  

使用LLDB命令c,先讓程序繼續運行

(lldb) c
Process 1079 resuming
(lldb) 

測試

(lldb) image list
[  0] 12AE6955-466B-365D-B4AD-4414062D4AA0 0x0000000100e20000 /private/var/containers/Bundle/Application/155D1862-E927-4904-B513-B48BDA84DE08/WeChat.app/WeChat (0x0000000100e20000)
[  1] D3BB8E91-0746-3426-8707-5B717D156B4E 0x000000010d2a0000 /Library/Caches/cy-B6mYK0.dylib (0x000000010d2a0000)
[  2] BF3B96C2-BD3B-390E-BFCF-33656588C86E 0x000000010cf90000 /usr/lib/substrate/SubstrateBootstrap.dylib (0x000000010cf90000)
[  3] 46F72B20-370B-352E-ABCA-3896633F251D 0x00000001b4191000 /Users/gn/Library/Developer/Xcode/iOS DeviceSupport/13.7 (17H35)/Symbols/System/Library/Frameworks/AuthenticationServices.framework/AuthenticationServices 
[  4] 7602EB30-DE1D-3996-8D0E-024450B58325 0x000000019885d000 /Users/gn/Library/Developer/Xcode/iOS DeviceSupport/13.7 (17H35)/Symbols/System/Library/Frameworks/AVKit.framework/AVKit 
[  5] E545F1E8-28B7-3580-9770-97D87896929B 0x00000001c08be000 /Users/gn/Library/Developer/Xcode/iOS DeviceSupport/13.7 (17H35)/Symbols/usr/lib/libresolv.9.dylib 

第四步:動態調試建立好之後,我們就可以使用LLDB指令,來正式開始調試了

LLDB指令
LLDB指令的格式是:
<command> [<subcommand> [<subcommand>...]] <action> [-options [option- value]] [argument [argument...]],其中,command代表命令,subcommand代表子命令,action代表命令的動作,- options 代表命令的選項,argument代表命令的參數,[]中的可以省略。
help命令,用於查看指令的用法,例如:help breakpoint、help breakpoint set
expression命令,執行一個表達式,例如:expression self.view.backgroundColor = [UIColor redColor],expression與print、p、call的效果一樣
thread backtrace命令,打印線程的堆棧信息,與bt命令效果一樣
thread return []命令,讓函數直接返回某個值,不會執行斷點後面的代碼了,例如:thread return 3,返回了3
frame variable []命令,打印當前棧幀的變量
thread continue、continue、c命令,讓程序繼續運行
thread step-over、next、n命令,單步執行,把子函數當做一個整體,不會進入子函數
thread step-in、step、s命令,單步執行,遇到子函數會進入子函數內部
breakpoint set命令,設置斷點,參數主要有以下幾種:
breakpoint set -a 函數地址
breakpoint set -n 函數名
breakpoint set -r 正則表達式
breakpoint set -s 動態庫 -n 函數名
breakpoint list命令,列出所有的斷點,每個斷點都有自己的編號
breakpoint delete 斷點編號命令,刪除某個斷點
breakpoint command add 斷點編號命令,給斷點預先設置需要執行的命令,到觸發斷點時,就會按順序執行
breakpoint command list 斷點編號命令,查看某個斷點的預設命令
watchpoint內存斷點,就是當內存數據改變時,觸發此斷點,以便確認是誰修改了內存,子命令主要有以下幾種:
watchpoint set variable 變量,例如:watchpoint set variable self->_age,當age變量改變時,斷點就會觸發,以便找到修改age內存的代碼

watchpoint set expression 地址,例如:watchpoint set expression &self->_age

watchpoint list,列出所有的內存斷點

watchpoint delete 斷點編號,刪除此內存斷點

watchpoint command add 斷點編號,給此內存斷點,增加預設命令

image lookup,尋找模塊信息,如果你想找某個類型、某個方法、某個地址在模塊中的什麼位置,就可以用這個命令,主要參數如下:
image lookup -t 類型,查找某個類型的信息,例如image lookup -t NSInterger
image lookup -a 地址,看看某個內存地址在模塊中的位置
image lookup -n 符號或者函數名,查找某個符號或者函數的位置
image list,列出所加載的模塊信息
一些小技巧:敲Enter會自動執行上次的命令、絕大部分命令可以使用縮寫

lldb常用命令

breakpoint使用

1、下斷點

breakpoint set --name test1 

breakpoint set -n test1 

打印:

Breakpoint 2: where = LLDB`-[ViewController test1] + 23 at ViewController.m:25:5, address = 0x0000000109de9f97

斷點位置信息,執行便能在該處斷住。

連續下多個斷點:

breakpoint set -n "-[ViewController save:]" -n "-[ViewController pause:]" -n "-[ViewController continues:]"

運行c繼續運行,n單步執行,s進入函數內部執行,finish執行到函數尾部。

2、查看斷點列表

breakpoint list

打印:

1: file = '/Users/hibo/Documents/test/LLDB/LLDB/ViewController.m', line = 21, exact_match = 0, locations = 1 Options: disabled 

 1.1: where = LLDB`-[ViewController touchesBegan:withEvent:] + 70 at ViewController.m:22:6, address = 0x0000000109de9f46, unresolved, hit count = 2 Options: disabled 

2: name = 'test1', locations = 1, resolved = 1, hit count = 7

 2.1: where = LLDB`-[ViewController test1] + 23 at ViewController.m:25:5, address = 0x0000000109de9f97, resolved, hit count = 7 

3、禁用斷點

breakpoint disable  //禁用所有斷點
breakpoint disable 1.1 //禁用第一個斷點

4、啓用斷點

breakpoint enable   //啓用所有斷點
breakpoint enable 1.1  //啓用1處斷點  

5、刪除所有斷點

breakpoint delete
breakpoint delete 1

刪除只能刪除一組,不能單個刪除

6、設置selector

breakpoint set --selector touchesBegan:withEvent:

將爲所有該方法設置斷點

7、設置文件中的selector斷點

breakpoint set --file ViewController.m --selector touchesBegan:withEvent:

8、設置帶有相同字符串的方法斷點

breakpoint set -r Game:

打印:

Current breakpoints:

1: regex = 'Game:', locations = 3, resolved = 3, hit count = 0

 1.1: where = LLDB`-[ViewController pauseGame:] + 43 at ViewController.m:31:5, address = 0x00000001010dff0b, resolved, hit count = 0 

 1.2: where = LLDB`-[ViewController continueGame:] + 43 at ViewController.m:34:5, address = 0x00000001010dff5b, resolved, hit count = 0 

 1.3: where = LinkPresentation`-[LPGameCenterInvitationMetadata setGame:], address = 0x00007fff2733e5e9, resolved, hit count = 0 

如上也給其他帶有Game字符的類下了斷點。

給某一個文件下的帶有相同字符串的方法下斷點:

breakpoint set --file ViewController.m -r Game

簡寫:breakpoint->b
打印列表需要寫全:breakpoint list或者break list

bt、frame命令

1、查看函數相關信息,使用p、down追蹤函數的調用和被調用關係

frame select

使用bt命令查看函數調用堆棧

2、查找方法的調用者及方法名稱

frame variable

methods、pviews

1、methods打印當前對象的屬性和方法

methods self 

2、pviews打印當前視圖的層級結構

以上兩個命令是lldb插件名中的命令。chisel安裝

……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章