iOS逆向 lldb动态调试

前言

使用 lldb 调试需要准备 debugserver。使用 OSX 中的 lldb 远程连接 iOS 上的 debugserver,由 debugserver 作为 lldb 和 iOS 的中转,执行命令和返回结果。在默认情况下,iOS 上并没有安装 debugserver,只有在设备连接过一次 Xcode,安装了开发者插件后,debugserver 才会被 Xcode 安装到iOS的/Developer/usr/bin/目录下。

重签名debugserver

在iOS11越狱之前,需要对debugserver进行重签名,在iOS11上可以直接使用/Developer/usr/bin/debugserver,或者直接用 Xcode 对iOS上的app进行调试。iOS11之前用Xcode调试需要对app进行重签名,而iOS11之后不需要重签名app也能调试了。

iOS11之前重签名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文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!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文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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了。

  1. SSH到iOS,使用debugserver来attach一个进程,要查看当前正在运行的进程,使用ps -e命令。比如我们要attach的进程号为 693,我们可以输入如下命令:debugserver *:1234 -a 693

  2. iOS11上debugserver *:1234中的*:1234要替换成localhost:1234。如果用的是Electra越狱,命令变成/Developer/usr/bin/debugserver localhost:1234 -a 693,如果用的是unc0ver越狱,则是debugserver localhost:1234 -a 693。同理,下文中的对应命令也要相应的替换

  3. 如果要用debugserver启动app,而不是附加到已经启动的app,则使用debugserver *:1234 <app二进制文件路径>,例如debugserver *:1234 /var/containers/Bundle/Application/107F3307-2900-4720-B9BA-0C7792D89DF2/APP_TO_DEBUG.app/APP_TO_DEBUG

  4. 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分析获取
截屏2020-03-04下午2.32.14.png

下图是使用hopper分析喜马拉雅播放方法的地址,然后使用lldb下断点
image.png

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

参考

iOS 逆向指南:动态分析