[原创]安卓逆向的核心流程里面分享了安卓逆向技能树的“树干”。“树干”上有多个“树枝”,其中有一个就是“混淆还原”,用来还原复杂难懂的代码。然后这个“树枝”上又有多个“树叶”,接下来分享的就是里面的“扁平化还原”。
大多OLLVM扁平化还原的核心思路是基于:块关系。
这篇文章从另外一个角度进行还原:状态机。
样本来自:[原创]OLLVM控制流平坦化混淆还原,目标函数:.init_proc
先说一下对OLLVM扁平化的理解
正常一个函数,会有多个基本块,逻辑清晰 函数通过OLLVM扁平化之后,逻辑变得复杂 所谓的扁平化,本质上是用状态机的方式对所有基本块进行重新调度。
原本直观的层次关系被抹除,所有基本块扁平成一排,从而提高静态分析的成本。
更形象地理解:一本书本来是章节结构清晰的,扁平化后每一段后面写着下一段的编号,要去找到这个编号才能串起来。 这里先梳理一下状态机的调度过程,后续还原要用到:
因为改变状态之后,都会回到分发器:goto dispatcher,这就意味着dispatcher引用有很多个
这个函数只有一个集中返回的点,这里简单粗暴定为引用最多次数就是dispatcher。 对应可以写一个找dispatcher的脚本 0x43120对应有29个引用
状态寄存器存放状态值,分发器根据状态值进行调度,举个例子: 对应可以写一个找状态寄存的脚本: 调度过程都是:改变状态+返回分发器
返回分发器直接找:B dispatcher_ea
改变状态有2种情况: 对应的可以写一个寻找改变状态块的脚本 先比较状态,再执行基本块,具体有2种情况: 对应的可以写一个寻找命中状态块的脚本 OLLVM扁平化的还原,实际上是去掉分发器,从而还原基本块的关系 上面说到基本块的结束有2种情况,所以还原扁平化的脚本要处理2种情况:还原之前:逻辑复杂,总共181行
还原之后:逻辑清晰,总共53行,是原来的29%
基于状态机的角度进行还原,关键的步骤如下:实战过程遇到的情况会复杂很多,比如:
1、同个函数里面存在多个分发器;
2、“存放状态的寄存器”和“比较状态的寄存器”不是同一个;
3、比较状态不是直接判断值是否相等,而是用等价的表达式。
如果代码写得好,一键还原还挺爽的。 PS:块关系的角度,是先对所有基本块进行分类,再找出真实块之间的关联。但真实块之间的关联需要执行才知道(真机trace、模拟运行或者符号执行)。int demo(int x) {
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-288598.htm
[原创]OLLVM扁平化还原—新角度:状态机
144 浏览
14 回复
感谢分享
感谢分享
看看隐藏
感谢分享
感谢分享
感谢分享
感谢分享
学习学习
学习学习
学下,谢谢
说是新思路,看下
跟我的思路一样,果然天才的想法都是一样的!
牛逼
逆天而行
跟我的思路一样,果然天才的想法都是一样的![em_013]
不,你是逆天
跟我的思路一样,果然天才的想法都是一样的![em_013]
不,你是逆天