iOS攻防 - (十二)LLDB和DebugServer配合使用

1.介绍

debugserver是运行在iOS上。从它的名字你就能看出,debugserver扮演着一个服务器的角色,可以执行在MAC OS X客户端执行LLDB命令,并把结果反映到终端界面上,通常也成为”remote debugging”远程调试。debugserver默认在iOS系统里是没有的,但是,只要我们用Xcode在iPhone上调试过程序,它就会自动安装到iOS的目录 /Developer/usr/bin/ 。但是此种情况下,debugserver只能调试自己开发的程序。debug自己的程序多没意思,我们有源码了,什么都是一目了然,只要调试别人开发的程序,才有意思。所以,别担心,以下有一些小技巧教你如此调试别人的程序。

2.配置debugserver

2.1 首选从以下这张表中找出你的iOS设备对应的ARM类型

iOS攻防 - (十二)LLDB和DebugServer配合使用_lldb


iOS攻防 - (十二)LLDB和DebugServer配合使用_lldb_02

我的iOS设备是iPhone 5,所以对应的ARM类型是armv7s。
首先从iOS设备中把debugserver拷贝到OS X中,iOS路径是 /Developer/usr/bin/debugserver ,可以通过iFunBox拷贝,也可以通过scp命令,取决于你自己。这里我举栗子拷贝到OS X的Documents目录,然后执行如下瘦身命令

lipo -thin armv7s debugserver -output debugserver

armv7s,取决于你的iOS设备

2.2 给debugserver添加task_for_pid权限

下载 http://iosre.com/ent.xml 到 “/Users/victor/Documents” 的OSX目录下,然后运行以下命令:

/opt/theos/bin/ldid -Sent.xml debugserver

注意:-S和ent.xml中间没有空格

如果不知道theos和ldid,请

如果一切顺利,几秒钟内,这个命令就能执行完。倘若几分钟了,或者程序卡死在这条命令,那就取消吧,换一个方案。
下载 http://iosre.com/ent.plist 到 “/Users/victor/Documents/” 的OSX目录下,然后运行如下命令:

codesign -s - –entitlements ent.plist -f debugserver

2.3 拷贝修改好debugserver到iOS设备的 /usr/bin 目录下

VictorZhang@VictorZhang:~/Documents$ scp debugserver root@10.18.138.168:/usr/bin/debugserver

然后SSH登录到iOS设备,赋予debugserver执行权限

chmod +x /usr/bin/debugserver

有一件事需要声明,就是我们把debugserver拷贝到了 /usr/bin/ 目录下,而不是覆盖原始的debugserver,主要是因为,一:原始的debugserver是不可写的;二:我们在使用debugserver时,可以直接使用命令 debugserver 不用带一长串路径。到此为止debugserver已经准备好了

2.4 使用debugserver对进程的启动和附加

拿微信举栗子,SSH连接到iOS设备上运行如下命令,表示开启WeChat应用的远程调试,任意IP可以连接,端口指定1234

debugserver *:1234 -a “WeChat”

此时,在MAC OS X端再打开一个终端,进行LLDB操作

lldb
(lldb) process connect connect://10.18.136.168:1234

具体的lldb命令详解,请看这里 http://lldb.llvm.org/lldb-gdb.html

这里的意思是,远程进程连接,连接到IP=10.18.136.168,端口=1234的设备上,也就是我的iPhone 5手机

但是我在连接时发生了错误,如图所示

Process 440 stopped
* thread #1, stop reason = signal SIGSTOP
    frame #0: 0x00000001987c7570
error: memory read failed for 0x1987c7400

iOS攻防 - (十二)LLDB和DebugServer配合使用_ios_03

在官方书籍里说,这是LLDB的一个巨大bug,自从Xcode 6就开始了 把ARM和THUMB指令全部打乱混乱,专门针对armv7和armv7s的设备。我猜,Apple公司对外宣称这是一个bug,但是其实内部决定这是防止各位iOS逆向程序员对任意应用进行debug的一种行为表现

在官方书籍还说,上有政策,下有对策。我们有一个临时解决方案,就是下载Xcode 5.0.x 安装到Mac OS X,在安装时,要注意:因为Mac OS X本身有一个最新的Xcode 8.3.2 ,所以在安装Xcode 5.0.2时,在弹出的提示时要保留两者,keep both.

下载地址: http://adcdownload.apple.com/Developer_Tools/xcode_5.0.2/xcode_5.0.2.dmg

安装完后,在MAC OS X端再打开一个终端,进行LLDB操作

/Applications/Xcode5.app/Contents/Developer/usr/bin/lldb
(lldb) process connect connect://10.18.136.168:1234

发现还是报错,只是换了错误提示,无语。。。

iOS攻防 - (十二)LLDB和DebugServer配合使用_lldb_04

已经在StackOverflow 提交一个问题,正等待回答。。。
https://stackoverflow.com/questions/44342680/failed-to-remote-debugging-on-using-command-line-process-connect-connect-iosi

也在iOSRE上提了,等着回答。。。
http://bbs.iosre.com/t/failed-to-remote-debugging-on-using-command-line-process-connect-connect-iosip-port/8259

终于在iOSRE上找到答案了,是debugserver瘦身时选择的架构的问题,对debugserver重新瘦身用arm64

lipo -thin arm64 debugserver -output debugserver
codesign -s - –entitlements ent.plist -f debugserver

然后,把debugserver在scp到iOS设备里,赋予执行权限chmod

当成功链接后,你会看到如下图所示

iOS攻防 - (十二)LLDB和DebugServer配合使用_ios_05


2.5 当debugserver连接上后,准备调试

2.5.1 image list

image list在lldb里,info shared在GDB里,作用都是列出main executable和所有依赖的库。

(lldb) process connect connect://10.18.136.168:1234
Process 68463 stopped
* thread #1: tid = 0x10b6f, 0x00000001987ace0c libsystem_kernel.dylib`mach_msg_trap + 8, queue = 'com.apple.main-thread, stop reason = signal SIGSTOP
    frame #0: 0x00000001987ace0c libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap + 8:
-> 0x1987ace0c:  ret    lr

libsystem_kernel.dylib`mach_msg_overwrite_trap:
   0x1987ace10:  movn   x16, #31
   0x1987ace14:  svc    #128
   0x1987ace18:  ret    lr
(lldb) image list -o -f
[  0] 0x00000000000a8000 /private/var/mobile/Containers/Bundle/Application/62733E8A-0E12-4F06-9F6B-A5C3ACAB0AF8/weixin.app/Lanxin(0x00000001000a8000)
[  1] 0x0000000101acc000 /Library/MobileSubstrate/MobileSubstrate.dylib(0x0000000101acc000)
[  2] 0x00000000053e4000 /Users/VictorZhang/Library/Developer/Xcode/iOS DeviceSupport/8.2 (12D508)/Symbols/usr/lib/libiconv.2.dylib
[  3] 0x00000000053e4000 /Users/VictorZhang/Library/Developer/Xcode/iOS DeviceSupport/8.2 (12D508)/Symbols/usr/lib/libstdc++.6.dylib
[  4] 0x00000000053e4000 /Users/VictorZhang/Library/Developer/Xcode/iOS DeviceSupport/8.2 (12D508)/Symbols/usr/lib/libxml2.2.dylib
[  5] 0x00000000053e4000 /Users/VictorZhang/Library/Developer/Xcode/iOS DeviceSupport/8.2 (12D508)/Symbols/usr/lib/libz.1.dylib
[  6] 0x00000000053e4000 /Users/VictorZhang/Library/Developer/Xcode/iOS DeviceSupport/8.2 (12D508)/Symbols/System/Library/Frameworks/AVFoundation.framework/AVFoun
......

上面输出的三列解释如下:
第一列,序号
第二列,由ASLR随机生成的image地址
第三列,image的全路径,括号里是(原始起始地址 + ASLR偏移地址)

重点:
1.最终运行的基地址 = 不包含偏移地址的基地址 + ASLR 偏移地址
2.不包含偏移地址的基地址可以在IDA中查看
3.ASLR 偏移地址可以在LLDB上查看

拿微信举例,如何断点

(1).假如我们现在已经连接上了debugserver,并且拿 -[WloginProtocol loginWithPasswd:retData:]: 举例

iOS攻防 - (十二)LLDB和DebugServer配合使用_debugserve_06


(2).那么该方法的基地址是多少?

答:e979e + f0000 = 1d979e

br s -a 0x1d979e

f0000地址如下图显示

iOS攻防 - (十二)LLDB和DebugServer配合使用_iosreverse_07

其他参数和命令 http://lldb.llvm.org/lldb-gdb.html

>br l               //查看所有断点
>br s -a 0xCC730    //设置断点
>br dis             //禁用断点
>br en              //启用断点
>br del             //删除断点
>c                  //继续运行

//设置一组断点,通过以下命令
(lldb) br com add 1
Enter your debugger command(s).  Type 'DONE' to end.
> po [$r0 class] 
> p (char *)$r1 
> c 
> DONE