0x00 前言

讲道理,从接触Re到现在快一年了,看了不少比赛的逆向题目,还是只接触到了一点皮毛,没有找到逆向工程真正的方向,学的很杂又很迷茫。

一开始想学re单纯是因为招新赛的时候没人写这个方向,然后接触到了第一个Re师傅X06,感觉人很有意思,所以开始走这个方向,emmm,我做事情的理由确实都奇奇怪怪。

空闲时间也问过X06师傅走逆向工程的方向,提到了混淆代码这个东西,于是来浅学一下,做一个学习笔记。

代码混淆及其作用

代码混淆,是指将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为。不仅仅是保护代码,它也有精简编译后程序大小的作用。

代码混淆不能阻止逆向工程但是会加大其难度,因为被混淆的代码反编译后难于理解,调试以及除错都变得困难。

常用方式有将代码中的各种元素,如变量,函数,类的名字改写成无意义的名字。比如改写成单个字母,或是简短的无意义字母组合,甚至改写成”__”这样的符号,使得阅读的人无法根据名字猜测其用途。重写代码中的部分逻辑,将其变成功能上等价,但是更难理解的形式。比如将for循环改写成while循环,将循环改写成递归,精简中间变量,等等。打乱代码的格式。比如删除空格,将多行代码挤到一行中,或者将一行代码断成多行等等。

0x01 去控制流平坦化

去控制流平坦化学习_JustTK_的博客-CSDN博客_控制流平坦化

控制流平坦化

控制流平坦化的主要思想就是以基本块为单位,通过一个主分发器来控制程序的执行流程。

例如一个常见的 if-else 分支结构程序如下:

20200714210900139.png

经过控制流平坦化后,得到的流程图如下:

20200714211007217.png

这个特点在IDA 中也能很容易地识别出来

20200714213230356png

经过平坦化后的代码块大部分整齐地堆积在程序流程图的下方,这部分代码才是真正有意义的代码,称为”相关块“。

示例

借鉴一下大佬的示例

79d8a773a7fedf211e3fca3140642878.png

编译

1
gcc check_passed.c -o check_password

IDA 查看未经过控制流平坦化的流程图如下

e9cb5ee4874e307b39b9498755ca7b3e.png

进行控制流平坦化

1
build/bin/clang check_passwd.c -o check_password_flat -mllvm -fla

IDA查看控制流平坦化后的 流程图如下

b6d9662e5a216ac6e7a976dd8d814a79.png

去平坦化

接前言,去平坦化就是要识别出相关块,并且理清楚相关块之间的关系。

目前去控制流平坦化最有效的办法是利用符号执行

符号执行

符号执行是一种重要的形式化方法和软件分析技术,通过使用符号执行技术,将程序中变量的值表示为符号值和常量组成的计算表达式,符号是取值集合的记号,程序计算的输出被表示为输入符号值的函数,其在软件测试和程序验证中发挥着重要作用,并可以应用与程序漏洞的检测。

使用deflat脚本去控制流平坦化

下载安装deflat 脚本

1
git clone https://github.com/SnowGirls/deflat

去除控制流平坦化

1
2
cd deflat/
sudo python3 deflat.py check_passwd_flat 0x400530