一、概述
在越狱环境中我们可以很方便的使用cycript和reveal来调试应用,但是有个问题是他们都不影响进程,没有办法下断点调试。reveal主要的是界面调试,有时候我们需要lldb进行逻辑调试。
二、xcode附加进程
在xcode的debug中有个Attach to Process附加进程:
image.png
变成Running后就附加上了,可以直接断点调试了:
image.png
(lldb) pvc
<MainTabBarViewController 0x1168fd800>, state: appeared, view: <UILayoutContainerView 0x115c91f40>
| <MMUINavigationController 0x11692f000>, state: appeared, view: <UILayoutContainerView 0x115c98070>
| | <NewMainFrameViewController 0x116920c00>, state: appeared, view: <MMUIHookView 0x115f81700>
| <MMUINavigationController 0x116c13000>, state: disappeared, view: <UILayoutContainerView 0x115f86a70> not in the window
| | <ContactsViewController 0x11648c600>, state: disappeared, view: (view not loaded)
| <MMUINavigationController 0x11621b200>, state: disappeared, view: <UILayoutContainerView 0x11c27dbd0> not in the window
| | <FindFriendEntryViewController 0x116490800>, state: disappeared, view: (view not loaded)
| <MMUINavigationController 0x116252600>, state: disappeared, view: <UILayoutContainerView 0x11c2d4000> not in the window
| | <MoreViewController 0x1164d0a00>, state: disappeared, view: (view not loaded)
(lldb)
并且可以view debug:
image.png
- 对于越狱设备来说可以附加所有
App的进程,对了非越狱设备而言只能附加自己的App。
三、debugserver
Xcode中的lldb可以调试手机中的应用,是因为手机中的debugserver开启的相关服务。所以在越狱环境中我们只需要开启debugserver服务就可以利用LLDB远程调试三方应用了。
lldb通信原理
-
Xcode中有lldb给手机中的debugserver发送指令。 - 手机中的
debugserver会附加App,读App中的内容做一系列操作。 -
debugserver读取到的结果给到lldb显示。
3.1 Mac中的debugserver
mac在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport目录中能够看到不同iOS系统版本对应的的镜像文件:
mac中iOS镜像文件
打开dmg文件,进入usr/bin目录可以看到debugserver。这就是xcode安装到手机中的文件:
mac中对应iOS版本debugserver
3.2 验证
当xcode第一次连接手机的时候就会将debugserver安装到手机。
具体安装在手机的/Developer/usr/bin/目录中:
zaizai:~ root# cd /Developer/usr/bin/
zaizai:/Developer/usr/bin root# ls
DTDeviceArbitration* ScreenShotr* axauditd* debugserver*
zaizai:/Developer/usr/bin root#
将手机中的debugserver拷贝出来与mac上的进行md5验证
➜ md5 debugserver
MD5 (debugserver) = 8ce8fc76bebaa1a3aca530cdbce531a6
➜ scp -P 12345 root@localhost:/Developer/usr/bin/debugserver ./idebugserver
debugserver 100% 9779KB 35.6MB/s 00:00
➜ md5 idebugserver
MD5 (idebugserver) = 8ce8fc76bebaa1a3aca530cdbce531a6
md5一致验证确认。
⚠️如果手机端是重签过的
debugserver肯定就不一样了。当然重签也不能放在/Developer/usr/bin/目录,这个目录的肯定和电脑端对应版本的md5是一致的。
四、debugserver重签名
4.1 debugserver为什么需要重签
由于debugserver权限问题debugserver默认只能附加Xcode安装的程序。需要对其进行重签名来附加其它程序。当出现Failed to get connection from a remote gdb process的时候一般都是权限的问题。
对debugserver重签使用的是ldid工具 (需要安装),ldid具体功能可以直接在电脑终端输入ldid查看:
➜ ~ ldid
usage: ldid -S[entitlements.xml] <binary>
ldid -e MobileSafari
ldid -S cat
ldid -Stfp.xml gdb
-
-e:查看权限文件,后面可以跟>导出。 -
-S文件:重新签名(⚠️-S后面没有空格)。
4.2 导出权限文件
拷贝Xcode中和手机版本对应的debugserver导出权限文件(我这里是iOS14):
//ldid -e debugserver 可以直接在终端查看权限
ldid -e debugserver > debugserver.entitlements
在
iOS 12之后debugserver包含两个架构arm64和arm64e:lipo -info debugserver Architectures in the fat file: debugserver are: arm64 arm64e我们可以拆分架构生成重签对应架构的
debugserver(当然不拆也没有问题,不拆plist中两份配置都要改):lipo -thin arm64 debugserver -output debugserver_arm64然后将自己需要的架构重命名为
debugserver进行权限文件导出和重签。
4.3 修改导出的权限文件
4.3.1 增加权限
<key>platform-application</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>com.apple.system-task-ports</key>
<true/>
4.3.2 删除权限
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>seatbelt-profiles</key>
<array>
<string>debugserver</string>
</array>
4.3.3 完整权限内容
完整内容与自己的统版本有关,这里是iOS14.0,⚠️是arm64和arm64e两个架构的:
<?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>com.apple.backboardd.launchapplications</key>
<true/>
<key>com.apple.backboardd.debugapplications</key>
<true/>
<key>com.apple.frontboard.launchapplications</key>
<true/>
<key>com.apple.frontboard.debugapplications</key>
<true/>
<key>com.apple.private.logging.diagnostic</key>
<true/>
<key>com.apple.private.memorystatus</key>
<true/>
<key>com.apple.private.cs.debugger</key>
<true/>
<key>platform-application</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>com.apple.system-task-ports</key>
<true/>
</dict>
</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>com.apple.backboardd.launchapplications</key>
<true/>
<key>com.apple.backboardd.debugapplications</key>
<true/>
<key>com.apple.frontboard.launchapplications</key>
<true/>
<key>com.apple.frontboard.debugapplications</key>
<true/>
<key>com.apple.private.logging.diagnostic</key>
<true/>
<key>com.apple.private.memorystatus</key>
<true/>
<key>com.apple.private.cs.debugger</key>
<true/>
<key>platform-application</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>com.apple.system-task-ports</key>
<true/>
</dict>
</plist>
4.4 重签名debugserver
修改好后好后进行重签名(-S后面没有空格):
ldid -S权限文件 debugserver文件
ldid -Sdebugserver.entitlements debugserver
4.5 签名和debugserver配置
如果你想用重签名后的debugserver替换/Developer/usr/bin目录下的debugserver那么你想多了。这个目录我们没有修改权限(只读目录)。
zaizai:/Developer/usr/bin root# rm debugserver
rm: cannot remove 'debugserver': Read-only file system
那么我们直接将重新签名后的debugserver放入/usr/bin/目录中:
scp -P 12345 debugserver root@localhost:/usr/bin/
至此手机端的debugserver就已经配置好了。
⚠️
/usr/bin/目录下有个好处是这个默认配置了环境变量,在任何目录下我们都能使用debugserver。
五、手动启动debugserver
5.1 开启usb映射
在开启手机端debugserver前,我们先在端口映射处加一个映射:
//iproxy
iproxy 12345:22 12346:12346
//python /Users/zaizai/HPShell/python-client/tcprelay.py -t 22:12345 12346:12346
同时映射两个端口,iproxy和python脚本都可以。
5.2 手机端开启debugserver服务
5.2.1 debugserver功能
进入/usr/bin/目录输入./debugserver就可以看都有哪些功能了:
zaizai:/usr/bin root# ./debugserver
debugserver-@(#)PROGRAM:LLDB PROJECT:lldb-1200.2.12
for arm64.
Usage:
debugserver host:port [program-name program-arg1 program-arg2 ...]
debugserver /path/file [program-name program-arg1 program-arg2 ...]
debugserver host:port --attach=<pid>
debugserver /path/file --attach=<pid>
debugserver host:port --attach=<process_name>
debugserver /path/file --attach=<process_name>
可以看到我们可以通过进程id和名字开启:
debugserver 主机地址:端口号 –a 应用进程
- 主机地址:由于主机地址是当前手机,可以使用
localhost代替。 - 端口号:启动
server服务,开放端口,让远程的LLDB通过sever调试进程。
5.2.2 debugserver开启
手机端先开启debug server:
zaizai:/usr/bin root# ./debugserver localhost:12346 -a WeChat
debugserver-@(#)PROGRAM:LLDB PROJECT:lldb-1200.2.12
for arm64.
Attaching to process WeChat...
Listening to port 12346 for a connection from localhost...
进入监听状态。
5.3 mac进入lldb环境
在mac终端直接输入lldb回车进入lldb环境,然后连接:
process connect connect://IP:端口
➜ ~ lldb
➜ ~ lldb
(lldb) process connect connect://localhost:12346
Process 24284 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x00000001b494e8c4 libsystem_kernel.dylib` mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
-> 0x1b494e8c4 <+8>: ret
libsystem_kernel.dylib'mach_msg_overwrite_trap: 0x1b494e8c8 <+0>: mov x16, #-0x20
0x1b494e8cc <+4>: svc #0x80
0x1b494e8d0 <+8>: ret
libsystem_kernel.dylib'semaphore_signal_trap: 0x1b494e8d4 <+0>: mov x16, #-0x21
0x1b494e8d8 <+4>: svc #0x80
0x1b494e8dc <+8>: ret
libsystem_kernel.dylib'semaphore_signal_all_trap: 0x1b494e8e0 <+0>: mov x16, #-0x22
Target 0: (WeChat) stopped.
(lldb)
连接需要等几秒钟。出现Target stopped就连接成功了,可以直接输入命令调试了。
5.4 终端lldb调试
image.png
lldb命令调试:
(lldb) process interrupt
Process 24268 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x00000001b494e8c4 libsystem_kernel.dylib` mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
-> 0x1b494e8c4 <+8>: ret
libsystem_kernel.dylib'mach_msg_overwrite_trap: 0x1b494e8c8 <+0>: mov x16, #-0x20
0x1b494e8cc <+4>: svc #0x80
0x1b494e8d0 <+8>: ret
libsystem_kernel.dylib'semaphore_signal_trap: 0x1b494e8d4 <+0>: mov x16, #-0x21
0x1b494e8d8 <+4>: svc #0x80
0x1b494e8dc <+8>: ret
libsystem_kernel.dylib'semaphore_signal_all_trap: 0x1b494e8e0 <+0>: mov x16, #-0x22
Target 0: (WeChat) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
* frame #0: 0x00000001b494e8c4 libsystem_kernel.dylib` mach_msg_trap + 8
frame #1: 0x00000001b494dcc8 libsystem_kernel.dylib` mach_msg + 72
frame #2: 0x0000000189f7874c CoreFoundation` __CFRunLoopServiceMachPort + 376
frame #3: 0x0000000189f72bd0 CoreFoundation` __CFRunLoopRun + 1176
frame #4: 0x0000000189f72200 CoreFoundation` CFRunLoopRunSpecific + 572
frame #5: 0x00000001a006d598 GraphicsServices` GSEventRunModal + 160
frame #6: 0x000000018c838004 UIKitCore` -[UIApplication _run] + 1052
frame #7: 0x000000018c83d5d8 UIKitCore` UIApplicationMain + 164
frame #8: 0x0000000105270328 WeChat` ___lldb_unnamed_symbol30639$$WeChat + 860
frame #9: 0x0000000189c51598 libdyld.dylib` start + 4
(lldb) sbt
frame #0 : 0x1b494e8c4 libsystem_kernel.dylib`mach_msg_trap + 8
frame #1 : 0x1b494dcc8 libsystem_kernel.dylib`mach_msg + 72
frame #2 : 0x189f7874c CoreFoundation`__CFRunLoopServiceMachPort + 376
frame #3 : 0x189f72bd0 CoreFoundation`__CFRunLoopRun + 1176
frame #4 : 0x189f72200 CoreFoundation`CFRunLoopRunSpecific + 572
frame #5 : 0x1a006d598 GraphicsServices`GSEventRunModal + 160
frame #6 : 0x18c838004 UIKitCore`-[UIApplication _run] + 1052
frame #7 : 0x18c83d5d8 UIKitCore`UIApplicationMain + 164
frame #8 : 0x105270328 WeChat`-[ + 860
frame #9 : 0x189c51598 libdyld.dylib`start + 4
(lldb) c
Process 24268 resuming
(lldb)
-
process interrupt:可以中断进程。 - 退出
lldb的时候进程会被杀掉。
总结
- 使用附加
- 1.终端附加:
- 手机端:
debugserver 主机名称:端口 -a App名称 -
Mac端:- 启动
lldb process connect connect://主机名称:端口
- 启动
- 手机端:
- 2.
Xcode附加:Debug->Attach to Process(需要选中设备)
- 1.终端附加:
- 权限:
- 导出权限文件:
ldid -e debugserver > debugserver.entitlements - 设置权限:
- 增加权限:
platform-application
get-task-allow
task_for_pid-allow
run-unsigned-code
com.apple.system-task-ports - 删除权限:
com.apple.security.network.server
com.apple.security.network.client
seatbelt-profiles - 设置权限:
ldid -Sdebugserver.entitlements debugserver
- 增加权限:
- 导出权限文件:












网友评论