ios逆向工具--LLDB+debugServer

LLDB(Low Level Debugger),如果说IDA是倚天剑,那么LLDB就是屠龙刀两者在逆向工程中的地位不相上下,难分伯仲。内置于xCode中的调试工具,通吃c,c++,object-c,全盘支持osx、ios,及ios模拟器;

功能可以概括为4点:

1、在指定的条件下启动程序

2、在指定的条件下停止程序

3、在程序停止的时候检查程序内部发生的事;

4、在程序停止的时候对程序进行改动,观察程序的执行过程有什么变化。

LLDB是运行在OSX中运行的,要想调试iOS,还需要另一个工具debugserver的配合。

debugserver运行在iOS上,作为服务端,实际执行LLDB(作为客户端)传过来的命令,再把执行结果反给LLDB,显示给用户,即所谓的“远程调试”。在默认情况下,iOS上并没有安装debugserver,只有在iOS设备连接过一次xCode,并在window-Devices菜单中添加此设备后,debugserver才会被Xcode安装到iOS的“/Developer/usr/bin/”目录下。

ios逆向工具--LLDB+debugServerX

但是,因为缺少task_for_pid权限,通过Xcode安装的debugserver只能调试我们自己的app,要想能够调试其他人的app,还需要进行配置;

先用scp命令或pp助手之类的工具将手机中的debugserver拷到mac上来;然后用lipo命令,结其瘦身:(ps:要确认手机对应的指令集iphone5,5c为armv7s,iphone5s,6..为arm64),比如我的是iphone5s,故只需要保留arm64即可:

ios逆向工具--LLDB+debugServer

可以看到lipo命令瘦身之后的debgugserver由原来的13M多变成4、5M的大小。

ios逆向工具--LLDB+debugServer

用file命令,也可查看到,未瘦身之前的debugserver包含armv7、armv7s和arm64,而lipo之后的只有arm64。

接下来给debugserver添加task_for_pid权限,下载http://iosre.com/ent.xml至与瘦身后的degserver同一目录下;然后ldid -Sent.xml debugserver执行添加权限:(注意:-S与ent.xml中间无空格)

ios逆向工具--LLDB+debugServer

然后将处理后的debugserver拷回到ios的/usr/bin/目录下,然后ssh到ios,给debugserver添加使用权限:

ios逆向工具--LLDB+debugServer

P.S. 为什么不把debugserver拷回原来的/Developer/usr/bin/目录,而是/usr/bin/目录下呢?因为一是原版的debugserver是不可写的,无法替换覆盖;二是放在/usr/bin/目录下的命令,无须输入全路径即可执行,即在ios任意目录下都可以执行debugserver命令。

debugserver最常用的2种场景,就是启动和附加进程,命令分别是:

debugserver -x backboard IP:port /paht/to/excutable

此种方式,debugserver会启动excutable,并开启port端口,等待来自IP的LLDB接入;

debgugserver IP:port -a 'processName'

此种方式,debugserver会附加processName进程,并开启port端口,等待来自IP的LLDB接入。

eg:

在ios上用debugserver打开MobileSMS并启动调试(*:1234表示允许任意IP通过1234端口进行lldb连接调试)

ios逆向工具--LLDB+debugServer

在mac上启动lldb连接,连接成功后即可行远程调试:

ios逆向工具--LLDB+debugServer

ps:连接后,进程将处理暂停状态,输入c即可进入运行调试状态。ctrl+D中止调试。

在ios上用debugserver附加到已经打开的MobileSMS上,进行调试:

ios逆向工具--LLDB+debugServer

mac上lldb连接同上。

至此即可使用lldb进行愉快的动态调试了!

附lldb常用命令:

imagelist -o -f //查看ASLR偏移

b function //函数的起始位置设置断点,如b NSlog

br s -a 0xAddress //在计算出的偏移后的地址上设置断点

br s -a 'Addr1+Addr2' //直接用ASLR+偏移前地址进行断点

br s del //删除所有断点

br s del index //删除指定断点

br dis //禁用所有断点

br dis index //禁用指定断点

br en //启用断点

br en index //启用指定断点

br com add index //在指定断点上,预先设置指令,在触发后得到执行

eg:

(lldb) br com add 1

Enter your debugger command(s). Type 'DONE' to end.

>po [$r0 class]

>p (char *)$r1

>c

>DONE

//br com add命令一般用于自动观察某个断点被触发时其上下文的变化,找到进一步分析的线索

p (char *)$r1

//通过强制转换的方式打印了C语言基本数据类型对象;

//oc里所有的对象都是用指针表示的,p打印出来的是对象的指针,而不是对象的本身,要打印对象本身则可以用po命令(print object)

po $r1

p/x $sp //16进制方式打印sp的值(一个指针)

x/10 $sp //打印这个指针指向的连续10个字(word)的数据

p/x $lr //在方法开始处断点,输入此命令可以查找调用此方法的上一个方法,即该方法的调用者;还可以直接在方法的结束处断开,然后ni执行,会回到上一级调用者的方法里;

c 继续执行至下一个断点

ni 单步执行

si 进入函数体

register write //用于指定的寄存器赋值,从而对程序进行改动,观察程序的执行过程有啥变化;

eg:register write r0 1 //将r0的值改成1,使下面的判断执行到另一分支

1)lldb调试的二进制文件必须从iOS中提取,IDA分析的二进制文件必须与LLDB调试的二进制文件为同一个。二进制文件可以通过dyld_decache工具从iOS上获取。

2)LLDB中,如果要重复执行上一个调试指令,直接回车即可;上下方向键可以查看之前执行过的调试指令。

lldb中下内存读写断点断点:

(lldb) help watchpoint set

The following subcommands are supported:

哈哈试出来了:

(lldb) wa s e -w r -- 0x27d61114

Watchpoint created: Watchpoint 5: addr = 0x27d61114 size = 4 state = enabled type = r

new value: 391767744

(lldb) wa s e -w w -- 0x27d61114

Watchpoint created: Watchpoint 6: addr = 0x27d61114 size = 4 state = enabled type = w

new value: 391767744

现有一int型地址0x12345678,内容初始值为0。我想用LLDB watchpoint捕获这个地址内容变更(条件内存写断点),请问前辈们如何写这个命令。

re:

watchpoint set expressiom(最后一个m改成n,操蛋的博客输入expressio(n)时判断为非法字符) -w write -s 4 -- 0x12345678

watchpoint set expressiom -w write -s 8 -- 0x12345678

你可能感兴趣的:(ios逆向工具--LLDB+debugServer)