0%

OLLVM对抗

题目:[RoarCTF2019]polyre

去除控制流平坦化

一眼看出是控制流平坦化后的程序,可以使用deflat.py去除常规的混淆。

在配置了angr的环境运行

1
python deflat.py attachment

可以得到attachment_recovered文件。

去除虚假控制流

这是去除平坦化之后的程序

看流程图更明显一些

可以确定这是进行了虚假控制流的混淆,因为它的调转逻辑不受输入的影响,是既定的跳转,所以我们可以将那些根本没执行过的指令nop掉。借助ida trace可以清晰明了的知道哪些执行过,哪些是假的。

执行过的代码块都进行了高亮处理,只需将为执行的部分nop掉然后重新解析即可。

反编译后逻辑很简单

验证输入,首先判断大于零还是小于零,也就是检测最高位是否为1,如果小于零,也就是最高位为1,那么乘2也就是左移一位,再异或上一个数。如果最高位为0,那么仅左移一位。

逆向过程就是判断最低位,直接左移的最低位为0。由于异或的数据最低位为1,所以经异或处理,最低位为1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
int main()
{
unsigned long long int cpdata[7] = {0xBC8FF26D43536296, 0x520100780530EE16, 0x4DC0B5EA935F08EC, 0x342B90AFD853F450, 0x8B250EBCAA2C3681, 0x55759F81A2C68AE4, 0xB0004B7679FA26B3};
for(int i=0;i<7;i++)
{
unsigned long long int tmp=cpdata[i];
for(int j=0;j<64;j++)
{
if(tmp&0x1==1) //末位为1
{
tmp=((tmp^0xB0004B7679FA26B3)>>1)|0x8000000000000000;
}
else
{
tmp=tmp>>1;
}
}
cpdata[i]=tmp;
}

for(int i=0;i<7;i++)
{
printf("0x%llx,",cpdata[i]);
}
}
//0x6666367b67616c66,0x63362d3039333932,0x2d363563342d3032,0x3539612d30376162,0x6631643365383537,0x7d38,0x1,

最后大小端反转一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdint.h>

int main() {
unsigned long long int v[7] = {0x6666367b67616c66,0x63362d3039333932,0x2d363563342d3032,0x3539612d30376162,0x6631643365383537,0x7d38,0x1};

for (int i = 0; i < 7; i++) {
printf("0x");
for (int j = 0; j < sizeof(unsigned long long); j++) {
printf("%x", (v[i] >> (j * 8)) & 0xFF);
}
printf(",");
}
printf("\n");

return 0;
}
//0x666c61677b366666,0x32393339302d3663,0x32302d346335362d,0x626137302d613935,0x3735386533643166,0x387d000000,0x10000000,
//flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}