接下来几篇文章将介绍iOS逆向分析中动态调试分析。主要是使用lldb配合(ida或者Hopper Disassembler)对iOS app的关键算法进行动态调试外加静态分析,从而还原出算法流程及参数。
该篇文章主要是对UnCrackable1进行动态调试分析。首先主要是介绍debugserver、lldb配置,其次则开始调试分析练习的app。
一、debugserver、lldb配置
-
配置debugserver(debugserver是在iOS设备中用来接收mac端lldb提供的指令,并进行相应的执行,即server端。iOS设备中带有的debugserver只能调试自己开发的相关应用,因此要对其他iOS app进行调试时,则需要配置debugserver)
拷贝debugserver到电脑上,在mac电脑安装有Xcode,并连接上iOS设备后。打开Xcode,即可在iOS设备的/Developer/usr/bin目录中找到debugserver(如下图所示),使用scp命令复制到电脑上
对debugserver进行瘦身,使用如下命令(其中-thin后面填写的是iOS设备的arm架构,iPhone 5s之前的都是 armv7s,iPhone 5s之后(含iPhone 5s)都是arm64,因为我的设备是iPhone 6s因此写arm64)
lipo -thin arm64 debugserver -output debugserver
给debugserver添加task_for_pid权限,新建文档ent.xml,拷贝以下配置到文档中,并保存到debugserver所在的目录中
保存后,在终端切换到debugserver所在目录后,执行如下命令
ldid -Sent.xml debugserver #赋予debugserver task_for_pid的权限
(如果执行命令时,提示ldid不存在,则使用brew install ldid安装ldid)
配置完debugserver后,将debugserver拷贝到iOS设备的/usr/bin目录(因为/Developer/usr/bin目录只读)中,并赋予可执行的权限,命令如下所示
chmod +x debugserver
赋予完权限后,则可以启动试试是否正常运行,命令如下
debugserver
配置lldb(mac安装Xcode后则自带lldb,不用配置)
二、调试分析UnCrackable1
-
在iOS设备中安装需要分析的iOS app,安装后启动该app。连接iOS设备,使用如下命令查看进程名,如下图所示
ps aux | grep "/var/containers" #找到我们要调试的进程名
-
在iOS设备中启动debugserver进行监听,使用如下命令,如下图所示
debugserver *:12345 -a "UnCrackable Level 1" #即我们要调试的iOS app的进程名
如果后面lldb连接debugserver提示如下错误时,则debugserver执行的命令修改为如下命令
debugserver 127.0.0.1:12345 -a "UnCrackable Level 1" #修改后的debugserver命令
-
使用lldb连接debugserver
这里也使用usb连接的方式连接debugserver则需要先设置端口转发,命令如下所示
./tcprelay.py -t 12345:12345(其中前面的12345端口是上面debugserver设置的监听端口号)
设置完后,在终端输入lldb命令,进入lldb的命令符后,执行如下命令将lldb和debugserver进行连接
lldb
(lldb)process connect connect://localhost:12345
连接完以后,则可以开始调试我们的目标app UnCrackable1了。
-
调试UnCrackable1
首先查看UnCrackable1进程的所有模块,在模块显示的信息中,我们可以看到它在虚拟内存中相对于模块基地址的偏移量。使用如下命令查看进程所有模块信息
image list -o -f
显示的结果如下图所示
左边的地址为ASLR偏移量(地址随机偏移量0x0000000000208000,右边的地址为偏移后的地址 0x0000000100208000)
因为我们要分析的函数在UnCrackable Level 1模块中,因此我们这里只需要记录UnCrackable Level 1的随机偏移量0x0000000000208000即可
查看完进程中模块的随机偏移量后,我们接下来即要在Hopper Disassember或者ida中打开我们的iOS app,找到需要分析的函数 buttonClick(即按下按键后执行的函数,比较两个字符串是否相等的函数) ,查看它的地址(这里我以ida为例)如下图所示
我们即可看到函数地址为 0x00000001000044A8(64位机器地址)
现在我们可以算出函数在内存中地址
0x00000000002080000(随机偏移量) + 0x00000001000044A8(ida中地址)= 0x1020844A8(内存中函数地址)
算出函数地址后,开始在lldb下断点,使用如下命令
(lldb) br s -a 0x1020844A8 #这样程序开始执行时,会运行到我们下断点的地方停下来,方便我们逐步跟踪
下完断点后,执行如下命令继续运行app
c #continue继续执行程序
则可看到如下图程序断在输入字符串的界面,等着我们输入字符串,在文本框中输入字符串"test",并按下 Verify 按键
如下所示,按下verify键后,lldb中程序断在buttonClick函数处,可以与ida中的buttonClick做对比,函数流程相同
接着即开始单步nexti(简写ni,ni指令遇到子函数不进入执行,步过)、stepi(简写si,si指令遇到子函数会进入执行,即每条指令都执行,步入)调试buttonClick函数
调试UnCrackable Level 1的buttonClick函数,我们主要是查看如下图所示的关键代码,并输出相应的寄存器值来辅助分析,具体如下所示
lldb执行流程如下所示(寄存器的值)
在lldb中继续执行 c 指令,可看到iOS设备中弹出错误信息
尝试修改isEqualToString函数返回值,查看程序的流程是否发生改变,使用如下命令,具体如下所示
register write x24(对应的寄存器) 0x1
修改寄存器后,iOS设备中程序弹出注册成功信息
当然还有一种方法就是我们已经跟踪到隐藏的标签的字符串值"i am groot!"。因此只需在文本框中输入对应的字符串值后,即可验证成功。如下图所示
最后,还有lldb调试指令没有补充,后面整理再增加上。
如果需要该练习的app进行lldb调试练习,可以在公众号回复 "UnCrackable1",获取下载链接
公众号二维码