脚本工具:基于lldb的trace脚本(新增<算法还原检测脚本>,辅助算法分析,过混淆等)

由于工作的需要,在逆向分析中,遇到了强混淆,vm虚拟机等加固方案。在分析的过程中,痛不欲生。为了能在逆向的过程中,能安心的喝口咖啡,同时能还原出 高度混淆/vm虚拟机 中的代码。参考函数追踪的原理,弄个 指令级 的 lldb-trace脚本。

[前瞻]:

平时分析的过程中,难免遇到c函数,c++函数,objc函数。而objc函数又包括很多realease函数…顾儿,在trace过程中,objc的 形如 release,引用计数类的函数,都忽略掉。对于 c/c++ 函数而言,类构造函数啊 … 系统函数啊…等等,都需要过滤。而 objc_msgsend 函数,可以做重点分析:在于你是否要分析这个函数。而我不需要,所以我只要objc_msgsend中的函数名,而函数的实现,我就不trace了。

框架分析:
对不同平台,做不同的配置。忽略掉的函数,都放到忽略函数列表中。objc_msgsend函数需要特殊处理,顾放到受保护列表中。由于trace过程中,需要读取那些寄存器的值,顾用正则解析汇编指令,获得此汇编需要的寄存器。

更新 :

1,trace 参数优化,绝大部分参数都为默认参数。
2,结束地址可以有多个(在某些混淆情况下,不确定结束地址到哪里,可以多设置几个结束地址)
3,增加了 暂停其他线程 的 可选参数
4,增加了 只 trace 本模块的 可选参数
5,增加了 进度 信息(防止以为脚本卡死…等的不耐心…从而关闭了 lldb)
6,对msg_send 函数的参数解开发中…
7,增加了对还原的算法检测脚本

怎么使用该脚本:

1,在你准备追踪的地方下断点:(我的断点,从breakpoint函数 si 进入到 a函数的 第一行)

2,导入lldbTrace.py脚本。(你可以设置,默认的 log 文件路径。如果不设置,默认和脚本同位置)
2222

3,设置一个停止追踪的地址:(当前a函数,我把结束地址设为 最后地址,和 ret 地址。为了查看debug信息,我把log类型设置成了debug)

4,设置好,直接回车,结果如下:

脚本在 git 上 :https://github.com/yangyss/lldb-trace

脚本还有很多不完善的地方,需要慢慢优化。
不过利用trace 结果,能还原 手写的算法,以及强混淆 或者 某些 vm虚拟机。

某手撸 aes 算法的还原:

11 Likes

大神厉害,体验了一下很好用.

顾儿

哈哈哈,牛逼,y总

道爷,别奶我…
就瞎搞瞎搞,为分析混淆/虚拟机 提供一个方案

1 Like

大佬,加载出现这个错是怎么解决啊
error: module importing failed: Traceback (most recent call last):
File “”, line 1, in
File “/opt/lldb_scripts/lldbTrace.py”, line 117
def handle_command(command,debugger:lldb.SBDebugger):

感觉,可能是你的 python环境,我这个是python3环境

而且我只实现了 arm64 架构的trace x86 系列的 没有弄
def handle_command(command,debugger:lldb.SBDebugger): 这个是 python3的语法

谢谢,我试试切换一下

感觉很牛逼,体验下来反馈

感觉会有效率问题。以前使用ida trace过vm,太慢了。

感觉还行。
一般10分钟左右,trace 2-3w行

如果trace 10几万行,那就脱离了 trace 的价值。
trace的主要目的 是 分析算法,抠出关键逻辑。

ida trace 没用过。还是比较相信lldb 自带api接口。

而trace vm 是需要技巧的,直接全局trace 。。。妈妈呀,只能紫薯布丁了

摸摸摸摸摸摸摸 :star_struck:

脚本优化如下:
1,增加了多个 结束地址,用 “;” 分割
2,增加了 调试 500 行,显示 相关信息
3,增加了 trace 本模块的 可选参数
4,增加了 暂停其他线程的 可选参数

4 Likes

算法还原检测脚本 简介:

***具体操作如下 ***

1,找到ida中对应方法,翻译成对应的python代码
ida_fun

2,利用lldbTrace.py脚本,把需要翻译的函数trace一哈。结果如下:

3,在ida伪代码中,切换到对应的汇编,对照trace结果,确定具体检测的地址。因为trace,当前打印的是上一句代码执行后的寄存器值。所以,我们把check的地址,定义为 0x10000393c,寄存器为 w8

4,定义检测的 变量 Check_0x10000393c_w8 = ‘Check_0x10000393c_w8’ 。在翻译的代码中,添加检测函数 check_value(ret,Check_0x10000393c_w8) 。在解析tracelog文件之前,设置check的相关信息 set_trace_data(Check_0x10000393c_w8)

5,用python 调用此脚本,并传入 tracelog文件的路径。结果如下:
check_pintout

2 Likes

在终端切换成了python3 xcode 里的lldb也会跟着切换吗 但是还是报错
Traceback (most recent call last):
File “/Users/aimo/Desktop//lldb-trace-script/lldbTrace.py”, line 959, in trace
log_d(“Target: {}”.format(str(target)))
File “/Users/aimo/Desktop//lldb-trace-script/lldbTrace.py”, line 30, in log_d
d_log_file.write(msg)
UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 14-15: ordinal not in range(128)

UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 14-15: ordinal not in range(128)

你这一段代码,具体的看看

也就ida 自带了一个python运行环境,别的没注意过。
xcode按理没自带python运行环境,应该和你当前的python运行环境,是一样的样子。。。个人猜测,不足为凭

在tk上试验了下,失败了,一直在死循环,
0x103efb4c8 stlxrbw10, w8, [x20] // w9 : 0x00000000 x20 : 0x00000001085b36c4
0x103efb4cc cbnz w10, 0x103efb4c4 // w10 : 0x00000001 w8 : 0x00000001 x20 : 0x00000001085b36c4
0x103efb4c4 ldaxrbw9, [x20] // w10 : 0x00000001
0x103efb4c8 stlxrbw10, w8, [x20] // w9 : 0x00000000 x20 : 0x00000001085b36c4
0x103efb4cc cbnz w10, 0x103efb4c4 // w10 : 0x00000001 w8 : 0x00000001 x20 : 0x00000001085b36c4
一直在这里死循环,不知道为啥

想到一种东西么?同步锁?原子锁?
因为其他线程,都暂停了,所以 w10 的值一直是1,所以对应的指向这个地址 一直被占用…具体的是啥个代码?可以写个demo看看

建议两种做法:
1,直接在 0x103efb4d0 下断点,重新trace
2,–supend-threads-except-current-thread 设置为 false

这个应该是用python2 运行的问题,如果跟你python环境保持一致(用python3)应该就没问题了.

但是我终端已经切换了python3 难道xcode 的lldb不是自动切换成对应的吗

应该不是,你可以试下在代码中最靠前的地方打印一下python的版本,import sys print(sys.version_info)