前言
使用 lldb 调试需要准备 debugserver。使用 OSX 中的 lldb 远程连接 iOS 上的 debugserver,由 debugserver 作为 lldb 和 iOS 的中转,执行命令和返回结果。在默认情况下,iOS 上并没有安装 debugserver,只有在设备连接过一次 Xcode,安装了开发者插件后,debugserver 才会被 Xcode 安装到iOS的/Developer/usr/bin/目录下。
重签名debugserver
在 iOS 11 越狱之前,需要对 debugserver 进行重签名,在 iOS 11 上可以直接使用/Developer/usr/bin/debugserver,或者直接用 Xcode 对 iOS 上的 app 进行调试。iOS 11 之前用 Xcode 调试需要对 app 进行重签名,而 iOS 11 之后不需要重签名 app 也能调试了。
iOS 11 之前重签名 debugserver 步骤:
1.拷贝 debugserver 到本地计算机中:scp root@iOSDeviceIP:/Developer/usr/bin/debugserver ~/debugserver
。
2.然后用 ldid 添加权限。由于 ldid 不支持 fat 二进制文件,所以要给 debugserver 瘦身,通过 lipo 指定要支持的指令类型,例如:lipo -thin arm64 ~/debugserver -output ~/debugserver
。
3.给 debugserver 添加 task_for_pid 权限,保存以下内容为 ent.xml 文件:
<!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.springboard.debugapplications</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
<key>run-unsigned-code</key>
<true/>
</dict>
</plist>
复制代码
然后执行以下命令添加权限:ldid -Sent.xml debugserver
4.给 debugserver 重新签名,保存以下内容为 entitlements.plist 文件:
<?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.springboard.debugapplications</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
</dict>
</plist>
复制代码
然后运行以下命令给的 debugserver 签名:codesign -s - --entitlements entitlements.plist -f debugserver
5.重新拷贝 debugserver 回手机中:scp ~/debugserver root@iOSDeviceIP:/usr/bin/debugserver
6.第一次使用 debugserver 时需要为其添加可执行权限:chmod +x /usr/bin/debugserver
lldb调试
准备好 debugserver 后,就可以调试任意第三方 app 了。
SSH 到 iOS,使用 debugserver 来 attach 一个进程,要查看当前正在运行的进程,使用
ps -e
命令。比如我们要 attach 的进程号为 693,我们可以输入如下命令:debugserver *:1234 -a 693
iOS 11 上
debugserver *:1234
中的*:1234
要替换成localhost:1234
。如果用的是 Electra 越狱,命令变成/Developer/usr/bin/debugserver localhost:1234 -a 693
,如果用的是unc0ver越狱,则是debugserver localhost:1234 -a 693
。同理,下文中的对应命令也要相应的替换如果要用 debugserver 启动 app,而不是附加到已经启动的 app,则使用
debugserver *:1234 <app二进制文件路径>
,例如debugserver *:1234 /var/containers/Bundle/Application/107F3307-2900-4720-B9BA-0C7792D89DF2/APP_TO_DEBUG.app/APP_TO_DEBUG
Mac 端打开终端,输入 lldb,回车,进入 lldb 界面,使用
process connect
命令连接客户端。 用 WiFi 连接到 iOS 设备时:process connect connect://iOSDeviceIP:1234
。
如果要用 usbmux 连接,则先使用iproxy 1234 1234
进行一次端口转发,再使用process connect connect://localhost:1234
,即可用 USB 连接到 iOS 设备。
回车后需要等待几分钟,时间有点久。
连接成功后,即可用 lldb 命令进行调试。
SSH链接
iproxy 2222 22
端口转发
ssh -p 2222 root@127.0.0.1 连接设备
找到要调试的进程进行调试
ps -e
查看进程
debugserver 127.0.0.1:1234 -a 693
attach进程
iproxy 1234 1234
进行一次端口转发
process connect connect://127.0.0.1:1234
在lldb里执行
下图是调试微信的例子,lldb附加成功之后就可以根据地址使用b
(地址加到b指令之后)指令下断点,地址可以根据hopper分析获取
下图是使用hopper分析喜马拉雅播放方法的地址,然后使用lldb下断点
lldb常用命令
列出所有断点:breakpoint list, br li
打开、关闭某个断点:breakpoint enable, breakpoint disable, br dis, br del
打印参数:frame variable, fr v
打印方法名和行数:frame info
打印寄存器的值:register read
修改寄存器的值:register write rax 123
列出文件加载基地址:image list
执行地址的加减运算:p/x