动态调试

138 阅读6分钟

iOS逆向工程(八):动态调试

[TOC]

一、什么是动态调试

  • 动态调试就是将程序运行起来,通过打断点、打印等方式,查看参数、返回值、函数调用流程等信息
  • 之前我们说的静态分析,就是程序不运行的时候,对程序的可执行文件进行分析,分析头文件、伪代码之类的信息
  • 学会动态调试之后,我们就可以分析某个程序的整体调用流程了,例如:分析微信抢红包的时候,就可以知道微信调用了哪些方法去抢红包,以便我们hook

二、Xcode动态调试的原理

  • 1、其实Xcode自带的LLDB工具,就是动态调试的工具,我们平常开发的时候也一直在用,在Xcode打断点,程序就会暂停,输入lldb指令,就会出现结果,那么Xcode动态调试的原理是怎样的呢?
  • 2、Xcode动态调试的原理是这样的:我们用Xcode启动程序的时候,就会在自动在手机上安装一个debugserver程序,Xcode的LLDB工具会跟debugserver程序进行交互,将lldb指令传输给debugserver程序,debugserver程序又会将lldb指令传输给App,App执行完之后,会将返回值传输给debugserver程序,debugserver程序又发给LLDB,在控制台显示出结果,如下图所示:

  • 3、debugserver程序一开始是存放在Mac中的Xcode里面的,手机里是没有的,只有当Xcode识别到手机设备时,才会自动把debugserver程序安装到手机上。debugserver的具体路径,如下所示

    debugserver在Mac上的路径是:
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/13.2/DeveloperDiskImage.dmg/usr/bin/debugserver
    
    debugserver安装到手机的路径是:
    /Developer/usr/bin/debugserver
    
  • 4、需要注意的是,Xcode动态调试,只能调试通过Xcode安装的App,也就是说我们逆向别人App的时候,是无法用Xcode动态调试来调试的,那么如何才能调试任意App呢?

三、动态调试任意App的原理

  • 1、想要调试任意App,我们就需要用终端取代Xcode,终端里的LLDB工具与手机的debugserver程序交互,来传输lldb命令,如下所示:

  • 2、 我们知道Xcode安装的debugserver只能与Xcode安装的App进行交互,因为沙盒机制的原因,导致debugserver没有权限与其他App产生交互,所以我们还需要给debugserver赋予相应的权限,才能与任意App进行交互

  • 3、 动态调试任意App只需要三步:将有权限的debugser安装到手机、让debugserver与App建立交互、让debugserver与LLDB产生交互

四、动态调试任意App的第一步:将有权限的debugserver安装到手机

这一步是一劳永逸的,安装完后,以后只需要第二步和第三步,就可以启动动态调试了

  • 1、在Mac的中找到与手机系统版本对应的debugserver程序,Mac中的路径如下:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/13.2/DeveloperDiskImage.dmg/usr/bin/debugserver
  • 2、使用ldid签名工具给debugserver新增两个权限:get-task-allowtask_for_pid-allow,这两个都是Bool值,设置为YES,新增权限流程如下:

    • (1). 通过ldid命令,导出debugserver现有的权限,命令是:

      ldid -e debugserver > debugserver.entitlements
      
    • (2). 编辑debugserver.entitlements文件,新增get-task-allowtask_for_pid-allow,值设置为YES,如下图所示:

    • (3). 通过ldid命令,对debugserver进行重新签名,命令是:

      ldid -Sdebugserver.entitlements debugserver,注意S是大写,并且与debugserver紧挨着。
      
  • 3、将已经签好权限的debugserver放到手机的/usr/bin里面,便于手机找到debugserver命令

五、动态调试任意App的第二步:让debugserver与App建立交互

  • 1、远程登录到手机后 ,让debugserver附加到某个App进程,命令如下:
打开命令行:sh usb.sh

新建命令行:sh login.sh,登录到手机后

让debugserver附加到某个App进程:$ debugserver 127.0.0.1:端口号 -a 进程名

例如让debugserver附加到微信的进程:$ debugserver 127.0.0.1:10011 -a WeChat
  • 2、重点命令就这一句话:$ debugserver 127.0.0.1:端口号 -a 进程名,其中127.0.0.1:端口号代表使用iPhone的某个端口启动debugserver服务,只要不是保留端口号就行

六、动态调试任意App的第三步:让debugserver与LLDB建立交互

  • 1、在Mac上启动LLDB服务,并且远程连接到iPhone的debugserver服务,命令如下:

    启动LLDB
    ` $ lldb    `
    
    连接到iPhone的debugserver服务
    ` (lldb) process connect connect://手机IP地址:debugserver服务的端口号  `
    
    以微信为例,连接到iPhone的debugserver服务:
    ` (lldb) process connect connect://10.88.211.170:10011 
    
  • 2、重点命令就这一句话process connect connect://手机IP地址:debugserver服务的端口号,如果输入完这句命令后,出现以下提示,就说明已经动态调试已经就绪,可以执行LLDB指令来调试了(注意此时会处在线程卡死状态,需要执行(lldb) c命令,让程序先运行起来)

(lldb) process connect connect://localhost:10011
Process 1194 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x000000018da64634 libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
->  0x18da64634 <+8>: ret

libsystem_kernel.dylib`mach_msg_overwrite_trap:
    0x18da64638 <+0>: mov    x16, #-0x20
    0x18da6463c <+4>: svc    #0x80
    0x18da64640 <+8>: ret
Target 0: (WeChat) stopped.

七、使用USB方式动态调试任意App

  • 上面说的流程是通过用Wifi的方式传输LLDB命令的,传输速度较慢,所以推荐使用USB的方式建立交互,也就是:将Mac的10011端口与iPhone的10011端口建立映射,然后debugserver服务使用iPhone的10011端口,此时Mac的LLDB工具与Mac的10011端口传输数据就相当于与iPhone的10011端口传输数据,如下所示:
在Mac上输入命令,让10011端口与10011端口映射、1001022端口映射
`python /Users/songpeng/Documents/python-client/tcprelay.py -t 22:10010 10011:10011`

在iPhone上执行下面的命令,启动debugserver服务,端口号为10011
`$ debugserver 127.0.0.1:10011 -a WeChat`

在Mac上执行以下命令,让LLDB与本地的10011传输数据,由于映射已经建立,就相当于给iPhone的debugserver服务发送数据
`$ lldb  `
`(lldb) process connect connect://localhost:10011 `
  • 2、可以将以前写的usb.sh文件的内容改成python /Users/songpeng/Documents/python-client/tcprelay.py -t 22:10010 10011:10011,这样即可以用USB的方式SSH登录到手机,也可以以USB的方式让LLDB与debugserver建立交互。以后使用起来就很方便了

  • 3、我们总结一下,使用USB方式动态调试任意App的全部流程,如下所示,以后忘记原理没关系,只需要按顺序输入以下命令,就可以顺利开启动态调试

在Mac上打开命令行窗口,让10011端口与10011端口映射、1001022端口映射
`$ sh usb.sh`

在Mac上新建命令行窗口,然后SSH登陆到手机
`$ sh login.sh`

登录到手机后,启动手机的debugserver服务,让其与App建立交互
`iPhone7ceshiji:~ root# debugserver 127.0.0.1:10011 -a WeChat`

在Mac上新建命令行窗口,进入lldb工具,并且让LLDB与debugserver建立交互
`$ lldb`
`(lldb) process connect connect://localhost:10011`

使用LLDB命令c,先让程序继续运行
`(lldb) c`
  • 4、动态调试建立好之后,我们就可以使用LLDB指令,来正式开始调试了

八、LLDB指令

    1. LLDB指令的格式是: <command> [<subcommand> [<subcommand>...]] <action> [-options [option- value]] [argument [argument...]],其中,command代表命令,subcommand代表子命令,action代表命令的动作,- options 代表命令的选项,argument代表命令的参数,[]中的可以省略。
    1. help命令,用于查看指令的用法,例如:help breakpointhelp breakpoint set
    1. expression命令,执行一个表达式,例如:expression self.view.backgroundColor = [UIColor redColor],expression与print、p、call的效果一样

www.jianshu.com/p/fa2f080fb…