iOS 安全攻防 -- 動態(tài)調(diào)試

本文基于重簽名后的IPA包安裝在越獄手機上運行的包實現(xiàn)動態(tài)調(diào)試。動態(tài)調(diào)試借助于ldid、debugserver、lldb 來實現(xiàn)。

  • ldid: 調(diào)試工具需要自行安裝至Mac端;
  • debugserver: 存于手機系統(tǒng)中,但是原本手機上的 debugserver 不具備get-task-allowtask_for_pid-allow 權限,需要賦予權限后重新簽名將其通過SSH傳輸至手機上;
  • LLDB(Low level Debuger): 輕量級調(diào)試 位于Mac。

一、準備工作

1.ldid

如果Mac上未安裝 ldid,則直接執(zhí)行指令:

$ brew install ldid

2. debugserver

a. 獲取

通過一下路徑可獲取到 debugserver,將其復制出至空文件夾中:

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/13.4/DeveloperDiskImage.dmg/usr/bin/debugserver

PS:真機調(diào)試包的版本號需與手機系統(tǒng)的版本號對應。

b. 賦予權限 & 重簽名

導出 entitlements 文件

$ ldid -e debugserver > debugserver.entitlements

通過文本編輯打開 debugserver.entitlements(debugserver.entitlements 無法直接打開,因為文件內(nèi)包含兩份配置 arm64、arm64v),將其內(nèi)文本替換為一下內(nèi)容(entitlements 中添加 get-task-allowtask_for_pid-allow 權限):

<?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>

重簽名

# 查看權限信息
$ codesign -d --entitlements - debugserver
# 簽名權限
$ codesign -f -s - --entitlements debugserver.entitlements debugserver
# 或著簡寫為
$ codesign -fs- --entitlements debugserver.entitlements debugserver
c. 將 debugserver 傳輸至手機上

將 debugserver 傳輸至 iPhone 上并放置于 /usr/bin/, 并對其附加權限

# iphone-ip 為手機IP地址
$ scp -r /xxx/debugserver root@iphone-ip:/usr/bin
# 例如 scp -r /Desktop/xxx/debugserver root@10.22.48.5:/usr/bin

# 輸入 SSH 秘鑰
$ alpine

# 開啟SSH, iphone-ip 為手機IP地址
$ ssh root@iphone-ip
# 輸入 SSH 秘鑰
$ alpine

# 增加權限
$ chmod +x /usr/bin/debugserver

二、debugserver 與 App 建立交互

新建終端窗口,將debugserver 與 App 建立交互

# 開啟 SSH
$ ssh root@ip
# 輸入SSH 密碼,下面為默認密碼
$ alpine

# 啟動應用后 可通過Mac端的控制臺獲取到進程ID/進程名
# ProcessID 為進程名/進程ID
$ debugserver 127.0.0.1:10011 -a <ProcessName/ProcessID>

三、debugserver 與 LLDB 建立交互

新建終端窗體,啟用端口 10011

# 新建終端窗口
$ iproxy 10011 10011


# 如果需要關閉端口
# 查看端口信息
$ lsof -i:10011
# kill 對應的PID
$ kill -9 <PID>

新建終端窗口,將 debugserver 與 LLDB 建立交互

$ lldb
$ process connect connect://127.0.0.1:10011
# 或 process connect connect:localhost:10011
# 關聯(lián)成功后,進程默認暫停,需要執(zhí)行一下命令讓程序繼續(xù)運行
$ c

四、指令響應歸納

App增加了 ptrace,動態(tài)調(diào)試建立關聯(lián)報錯,打印信息如下:

debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.106
 for arm64.
Attaching to process 6044...
Segmentation fault: 11

未做防護建立關聯(lián)正確信息,打印信息如下:

debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.98
 for arm64.
Attaching to process FYPrototypeDemo...
Listening to port 10011 for a connection from localhost...
Waiting for debugger instructions for process 0.

debugserver 與 LLDB 建立交互,打印信息如下:

Process 12370 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x00000001bf85b5f4 libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
->  0x1bf85b5f4 <+8>: ret

libsystem_kernel.dylib`mach_msg_overwrite_trap:
    0x1bf85b5f8 <+0>: mov    x16, #-0x20
    0x1bf85b5fc <+4>: svc    #0x80
    0x1bf85b600 <+8>: ret
Target 0: (FYPrototypeDemo) stopped.

五、lldb 指令

1. breakpoint

查看斷點列表

$ breakpoint list

禁用斷點

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

啟用斷點

# 啟用所有斷點
$ breakpoint enable
# 啟用第一個斷點
$ breakpoint enable 1.1

刪除斷點

# 刪除所有斷點
$ breakpoint delete
# 刪除第1組斷點, 刪除只能刪除一組,不能單個刪除
$ breakpoint delete 1

下斷點

# 通過函數(shù)名下斷點
$ breakpoint set --name <methodName>
# 或者
$ breakpoint set -n <methodName>
# 連續(xù)下多個斷點
$ breakpoint set -n <methodName> -n <methodName>
# 例如 breakpoint set -n "-[ViewController save:]" -n "-[ViewController pause:]" -n "-[ViewController continues:]"

設置 selector 斷點

$ breakpoint set --selector <selector>
# 例如 breakpoint set --selector touchesBegan:withEvent:

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

$ breakpoint set -r Game:

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

$ breakpoint set --file <filename> -r <method>
# 例如 breakpoint set --file ViewController.m -r Game

注意:

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

2. bt、frame 命令

查看函數(shù)相關信息,使用p、down追蹤函數(shù)的調(diào)用和被調(diào)用關系

# 使用bt命令查看函數(shù)調(diào)用堆棧
$ frame select

查找方法的調(diào)用者及方法名稱

$ frame variable

3. methods、pviews 命令

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

$ methods self

4. 命令大全

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

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

watchpoint list,列出所有的內(nèi)存斷點

watchpoint delete 斷點編號,刪除此內(nèi)存斷點

watchpoint command add 斷點編號,給此內(nèi)存斷點,增加預設命令

image lookup,尋找模塊信息,如果你想找某個類型、某個方法、某個地址在模塊中的什么位置,就可以用這個命令,主要參數(shù)如下:
image lookup -t 類型,查找某個類型的信息,例如image lookup -t NSInterger
image lookup -a 地址,看看某個內(nèi)存地址在模塊中的位置
image lookup -n 符號或者函數(shù)名,查找某個符號或者函數(shù)的位置
image list,列出所加載的模塊信息
一些小技巧:敲Enter會自動執(zhí)行上次的命令、絕大部分命令可以使用縮寫
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

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