逆向之旅--越狱手机动态调试 App Store 应用

在逆向过程中,我们需要通过各种工具和方法分析程序,找到合适的突破点破解程序,其中最重要的分析手段是静态分析和动态调试。
静态分析是指在不运行程序的前提下进行程序分析的一种方法,一般会配合已经得到的线索和分析工具来进行分析。静态分析相关的文章比较多,工具也比较丰富,类似 Hopper Disassembler、IDA、class-dump 等,这里不再赘述。
这篇文章重点来讲下动态调试部分,如何在越狱手机上动态调试 App Store 下载的应用(以微博为例)。先列举下自己的设备情况

  • iPhone 5s, iOS 9.2
  • 已越狱
  • 通过 USB 线 SSH 2222 端口连接到手机

准备调试工具

LLDB 原理

正向开发过程中,相信没有哪个开发者会没用到过 LLDB 进行调试。
通过 Xcode 调试,实际上是把调试指令发送到手机上的 debugserver 服务端,debugserver 是专门用来连接 Mac 上的 LLDB 客户端,并接收 LLDB 所提供的命令,从而达到调试的目的。
当手机设备连接到 Mac 进行真机调试的时候,debugserver 才会被安装到 Developer/usr/bin 目录下。但是,debugserver 默认只能对自己开发的 App 进行调试,要想调试其他 App 的话,需要进行如下的工作:

获取 debugserver

首先将手机里的 debugserver 拷贝到 Mac 中,这里通过 iFunBox 进行拷贝。用 USB 线将手机连接到 Mac,打开 iFunBox,左侧边栏选中文件系统,进入目录 /Developer/usr/bin,将 debugserver 文件拖拽到 Mac 端桌面上,如下图所示

逆向之旅--越狱手机动态调试 App Store 应用_第1张图片
拷贝 debugserver

给 debugserver 赋予权限

在桌面新建 entitlements.plist 文件,写入以下内容:




        com.apple.springboard.debugapplications
        
        get-task-allow
        
        task_for_pid-allow
        
        run-unsigned-code
        


使用 codesign 进行签名,命令如下:

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

将 debugserver 复制回手机

通过 iFunBox 将修改好的 debugserver 拷贝到手机的 /usr/bin/ 目录下,然后就可以对从 App Store 下载的 App 进行调试了

调试实战

准备好上述的 debugserver 之后就可以开始对从 App Store 下载的 App 进行调试了,这里以微博为例。
这里说明一下,动态调试通常是建立在静态调试的基础之上的。比如已经通过 class-dump 生成了头文件并找到了疑似的调用点,然后通过 Hopper Disassembler 反编译基本确认了这个调用点就是我们逆向的入口,那么此时就可以通过动态调试获取寄存器的值证实我们的猜测,还可以修改寄存器的值寻找可能的方法,最终达到破解的目的。
比如我们想要破解微博的登录功能(下图)

逆向之旅--越狱手机动态调试 App Store 应用_第2张图片
微博登录界面

我们已经通过 class-dump 和 Hopper Disassembler 找到了疑似的调用点 - [WBLoginViewController loadloginEngineWithUserName:password:],查看一下这个函数的实现:
函数反编译

先记录下函数对应的偏移地址 0x00000001014affc8(以下简称 D1),待会会用到。

LLDB 连接手机

现在就可以通过 LLDB 动态调试来验证一下我们的猜测,新建一个终端窗口(以下简称终端 A),通过 USB 线 SSH 2222 端口连接到手机,点击微博让进程运行起来,然后输入
ps aux 命令找到微博对应的进程 ID 为 798:

进程 ID

找到目标进程之后就可以通过进程 ID 进行调试了,在终端 A 输入以下命令:

debugserver *:1234 -a 798

此时微博界面会卡住,进入等待连接的状态。然后新建一个终端窗口(以下简称终端 B),输入 iproxy 1234 1234 命令进行端口转发。
新建一个终端窗口(以下简称终端 C),输入 lldb 并回车进入调试状态,然后输入以下命令连接上手机的 debugserver 服务端:

process connect connect://localhost:1234

可以看到终端 C 有下图所示的输出,代表连接成功,可以开始调试了:

逆向之旅--越狱手机动态调试 App Store 应用_第3张图片
LLDB 连接

终端 C 输入命令 c 然后回车让程序继续运行并响应外部事件。

打印寄存器的值

我们现在需要在函数 - [WBLoginViewController loadloginEngineWithUserName:password:] 上打一个断点好让程序执行到这个函数的时候可以断下来,那么就需要将模块的基地址加上之前说到的函数偏移地址 D1 得到函数在内存中的真实地址。在终端 C 中输入以下命令可以获取模块的基地址(以下简称 D0):

image list -o -f "Weibo"

结果如下图:


获取模块的基地址

函数在内存中的真实地址 = D0 + D1,执行以下命令对该函数下断点:

br s -a 0x00000000000b0000+0x00000001014affc8

对函数下断点

下完断点后在终端 C 中输入 c 然后回车让程序可以继续运行。
在微博上输入用户名 10010 和密码 123,点击登录按钮
逆向之旅--越狱手机动态调试 App Store 应用_第4张图片
输入用户名和密码

可以看到微博再次卡住,终端 C 输出了断点对应的信息:
逆向之旅--越狱手机动态调试 App Store 应用_第5张图片
断点

在终端 C 中用 po 命令打印出各个寄存器的值:
逆向之旅--越狱手机动态调试 App Store 应用_第6张图片
打印寄存器的值

参考文章:深入iOS系统底层之函数调用可知,x0、x1 分别为函数隐藏的参数 self 和 cmd,而 x2、x3、x4...分别对应函数的参数,可以看到我们输入的用户名 10010 和密码 123 都被正确打印出来了。至此,我们成功地在越狱手机上对 App Store 下载的应用进行动态调试
接下来,我们可以用 bt 打印当前堆栈信息、通过 expression 命令修改寄存器的值等等,这些命令我们平时正向开发都有用到,可以参考文章与调试器共舞 - LLDB 的华尔兹,这里不再赘述。

结语

这是逆向之旅系列的第一篇文章,实现了用命令行动态调试第三方应用的功能。
但是我们可以发现过程比较繁杂,用到的命令也比较多,而且因为没有符号表,所以断点输出的信息很多都是没被符号化的,不够完美。接下来会撰文总结如何用熟悉的 Xcode 调试第三方应用,以及如何恢复符号表信息,从而可以在调试过程中获取更多的信息,最终达成破解的目的。


逆向之旅--越狱手机动态调试 App Store 应用_第7张图片
To be continued

你可能感兴趣的:(逆向之旅--越狱手机动态调试 App Store 应用)