我爱编程技术分享

LLDB && debugServer的简单使用

2018-04-08  本文已影响663人  77168ddcf2c6

1.1 LLDB

<h4>LLDB全称为low level debugger,是xcode自带的动态调试工具,可用于c,c++,objective-c,全盘支持iOS,OSX以及iOS模拟器。
LLDB有以下四个功能:

1.在特定的情况下暂停程序

2.在特定的情况下启动程序

3.在程序停止的情况下检查程序内部

4.在程序停止的情况下改动程序,观察执行过程。

LLDB是运行在OSX程序中的,可以通过特定的语句配合debugServer对iOS中的程序进行监视。

1.2 debugServer

<h4>debugserver是运行在iOS程序中的,顾名思义,作为server端,它接受与来自服务端,也就是LLDB传送过来的命令,继而执行的操作。再把执行结果返回给LLDB,默认情况下, iOS并没有安装debugserver,只有在设备连接了一次xcode之后,并在window->device中添加此设备之后,debugservercai才会别安装到iOS中,默认位于Developer/usr/bin目录下。

但是默认的debugserver只用用户调试我们自己的app,如果想要调试iOS里面所有的app,还需要通过给debugserver赋予task_for_pid的权限。以下是配置task_for_pid的教程

1.debugserver瘦身,首先根据你的iOS设备确定你的手机对应的ARM,4s是armv7,5,5c是armv7s,5s以上的机型都是arm64,我的手机是5s,所以对应的arm是arm64,所以只从debugserver保留arm64的架构即可。具体步骤:
首先将未经处理的debugserver从iOS拷贝到OSX中,可以用scp命令,也可以用iFunBox。
然后利用命令

lipo -thin arm64(这里对应你的iOS设备的结构) (未经处理的debugServer的路径) -output (新的debugserver的保存路径)

2.给debugServer添加task_for_pid权限,将以下xml保存为ent.xml。

<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 -S(ent.xml的全路径) (debugServer的全路径)

以上命令实质上是通过ldid这个签名工具,为debugserver添加task_for_pid权限,上面的命令也可以用xcode自带的codesign实现。

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

3.将添加权限后的debugserver放回去iOS复制到/usr/bin/debugserver,这样的好处是可以全局执行debugserver命令。另一个原因是因为在developer里面的是不可以写的,无法覆盖。
4.给新的debugserver添加可执行的权限

chmod +x /usr/bin/debugserver

1.3 debugserver使用

<h4>debugserver有两个命令。

1.启动进程,debugserver会启动进程,并且开启port端口,等待来自ip的LLDB接入。ip如果为*则代表任意ip

debugserver backend ip:port /path/to/excutable

2.附加进程,附加进程是在进程已打开的情况下,可以执行以下命令。

debugserver ip:port -a "processname"

1.4 LLDB && debugserver配合使用

<h5>
假设我们要调试在iOS中要按下home键的处理。通过IDA我们知道按下home键的时候调用了 -[SpringBoard _menuButtonDown:] 这个方法,现在我们的需求是在menuButtonDown的方法下面打一个断点。

(1)首先利用debugserver启动进程或者附加进程。系统的SpringBoard默认是启动的,所以不需要启动进程,使用附加进程命令即可。SSH到iOS中,然后附加到SpringBoard进程(以下命令开启了1234接口并且等待来自任意ip的LLDB接入)

Last login: Sun Apr  8 11:04:23 on ttys016
MacBookPro:~ lemon$ ssh root@192.168.2.154
lemons-iPhone5S:~ root# debugserver *:1234 -a "SpringBoard"
debugserver-@(#)PROGRAM:debugserver  PROJECT:debugserver-340.3.124
 for arm64.
Attaching to process SpringBoard...
Listening to port 1234 for a connection from *...

(2)在OSX的terminal中启动LLDB,然后连接远程1234端口

MacBookPro:~ lemon$ lldb
(lldb) process connect connect://192.168.2.154:1234
Process 2148 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x000000018208cfd8 libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
->  0x18208cfd8 <+8>: ret    

libsystem_kernel.dylib`mach_msg_overwrite_trap:
    0x18208cfdc <+0>: mov    x16, #-0x20
    0x18208cfe0 <+4>: svc    #0x80
    0x18208cfe4 <+8>: ret    
Target 0: (SpringBoard) stopped.
(lldb)  

(3)通过以上两步我们已经可以在电脑的终端利用LLDB调试APP了。现在在终端输入 image list -o -f 可以看到当前所有iOS中启动的所有的进程模块。

[(lldb) image list -o -f
[  0] 0x0000000000040000 /Users/lemon/Library/Developer/Xcode/iOS DeviceSupport/9.3.1 (13E238)/Symbols/usr/lib/dyld
[  1] 0x00000000000dc000 /System/Library/CoreServices/SpringBoard.app/SpringBoard(0x00000001000dc000)
[  2] 0x0000000100988000 /Library/MobileSubstrate/MobileSubstrate.dylib(0x0000000100988000)
[  3] 0x0000000001acc000 /Users/lemon/Library/Developer/Xcode/iOS DeviceSupport/9.3.1 (13E238)/Symbols/System/Library/PrivateFrameworks/StoreServices.framework/StoreServices

(4)通过3中的信息我们发现了Spring的偏移是0x00000000000dc000,接下来我们需要用ida查看menuButtonDown这个函数在模块中的地址是多少。

                     -[SpringBoard _menuButtonDown:]:
0000000100016fe8         stp        x28, x27, [sp, #0xffffffa0]!                ; Objective C Implementation defined at 0x1006a4550 (instance)
0000000100016fec         stp        x26, x25, [sp, #0x10]
0000000100016ff0         stp        x24, x23, [sp, #0x20]
0000000100016ff4         stp        x22, x21, [sp, #0x30]
0000000100016ff8         stp        x20, x19, [sp, #0x40]
0000000100016ffc         stp        x29, x30, [sp, #0x50]
0000000100017000         add        x29, sp, #0x50
0000000100017004         sub        sp, sp, #0x60

通过上面的信息可以看到,该函数的第一条指令的地址是0000000100016fe8,所以该函数偏移后的地址是:原地址+偏移 =》0x00000000000dc000 + 0000000100016fe8 = 0x1000F2FE8

(5)在偏移后的地址出打断点

(lldb) br s -a 0x1000F2FE8
Breakpoint 1: where = SpringBoard`_mh_execute_header + 71804, address = 0x00000001000f2fe8
(lldb) 

(6)在打完断点之后,可以按下home键,这个时候程序就会停在断点处,可以用1.5里面的命令进行调试等等

1.5 LLDB命令解析

<h5>
(1) b NSog // 在函数的起始位置设置断点

(2) br s -a address //在地址处设置断点

(3) br s -a 'address + offsetAddress' //在地址处设置断点

(4) br dis //禁用所有的断点

(5) br dis 6 //禁用序号为6的断点

(6) br del //删除所有断点

(7) br del 6 //删除序号为6的断点

(8) br en //启用所有断点

(9) br en 6 //启用序号为6的断点

(10)br com add 1 //当序号为1的断点执行的时候,可以执行预先设置的指令。当执行了这条指令之后,llDB会要求你输入一些指令,并且以DONE结束,当程序停在序号为1的断点时,就会执行这些预先设定的指令。

(11)p $R1 //打印R1的值

(12)p/x $sp //打印SP的地址,以16进制输出

(13)x/10 $sp //打印sp的地址,以10进制输出

(14)nexti 和 stepi //nexti不进入函数体,stepi进入函数体,nexti可以简写成ni,setpi可以简写成si。

(15)register write r0 1 //用于给指定的寄存器r0赋值为1从而达到对程序进行改动的目的。

上一篇下一篇

猜你喜欢

热点阅读