1.分析文件:
把文件拖入DIE里面查看:
发现文件被保护器OLLVM执行过,
使用控制流平坦化和指令替换混淆代码,加密算法采用xxtea进行加密,
控制流平坦化的解决办的是使用defla.py和am_graph.py脚本来解决这个问题,
2.拖入IDA,查找main函数的地址
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // eax
int v5; // eax
int v7; // [rsp+80h] [rbp-C0h]
__int64 v8; // [rsp+84h] [rbp-BCh] BYREF
int v9; // [rsp+8Ch] [rbp-B4h]
void *ptr; // [rsp+90h] [rbp-B0h]
int v11; // [rsp+9Ch] [rbp-A4h]
int dest[20]; // [rsp+A0h] [rbp-A0h] BYREF
__int64 v13[2]; // [rsp+F0h] [rbp-50h] BYREF
char s[4]; // [rsp+100h] [rbp-40h] BYREF
int v15; // [rsp+134h] [rbp-Ch]
v15 = 0;
printf("Plz input your flag:");
v13[0] = 0x87654321DEADBEEFLL;
v13[1] = 0xCAFEBABEFACEB00CLL;
fgets(s, 50, _bss_start);
memcpy(dest, &unk_400E90, 0x48uLL);
v11 = (strlen(s) + 3) >> 2;
ptr = malloc(8LL * v11);
v9 = 0;
v7 = 1382681843;
while ( v7 != -1648711900 )
{
switch ( v7 )
{
case -1318238338:
v4 = -410445276;
if ( v9 < 2 * v11 )
v4 = 431781552;
v7 = v4;
break;
case -1182181165:
memset(&v8, 0, sizeof(v8));
LODWORD(v8) = *(_DWORD *)&s[4 * v9];
encode(32LL, &v8, v13);
*((_QWORD *)ptr + v9) = v8;
v7 = 1714824249;
break;
case -750079413:
++v9;
v7 = -1318238338;
break;
case -410445276:
printf("Congratulations\n");
free(ptr);
v15 = 0;
v7 = -1648711900;
break;
case 107817298:
v7 = -750079413;
break;
case 431781552:
v5 = 107817298;
if ( *((_DWORD *)ptr + v9) != dest[v9] )
v5 = 1679507848;
v7 = v5;
break;
case 1382681843:
v3 = 1550668173;
if ( v9 < v11 )
v3 = -1182181165;
v7 = v3;
break;
case 1550668173:
v9 = 0;
v7 = -1318238338;
break;
case 1679507848:
printf("Error\n");
v15 = 0;
v7 = -1648711900;
break;
default:
++v9;
v7 = 1382681843;
break;
}
}
return v15;
}
我们可以看见main函数的可读性很差,查找main函数的地址:0x400950,所以就需要使用指令:python deflat.py babyre 0x400950python deflat.py + 名字 + main函数的地址
(注意,这里需要被操作的题与脚本在同一的路径下面cmd,不然我会出现查找不到的错误:
然后就会生成一个文件babyre_recovered,打开来就会发现文件的main函数可读性明显提升了:
3.查看加密的函数encode
点开encode函数,可以看见函数里面十分复杂,基本看不懂里面在干什么:
那么就可以猜测的里面会有指令替换,所以我们就需要一个IDA的插件来帮助我们来把这一个混淆去掉:
我们把这两个文件放入IDA里面的plugins文件夹里面,
然后打开IDA,进入到encode函数里面,在Edit,Plugins里面找到插件D-810:
然后点击start,待结束过后按F5重新加载一下,就可以看见函数变小了很多:
__int64 __fastcall encode(unsigned int a1, unsigned int *a2, __int64 a3)
{
int v3; // eax
__int64 result; // rax
int v5; // [rsp+14h] [rbp-30h]
unsigned int v6; // [rsp+1Ch] [rbp-28h]
unsigned int v7; // [rsp+20h] [rbp-24h]
unsigned int v8; // [rsp+24h] [rbp-20h]
unsigned int v9; // [rsp+28h] [rbp-1Ch]
v8 = *a2;
v7 = a2[1];
v6 = 0;
v9 = 0;
v5 = -541349338;
while ( 1 )
{
while ( v5 == -541349338 )
{
v3 = -420430140;
if ( v9 < a1 )
v3 = 821547026;
v5 = v3;
}
if ( v5 == -420430140 )
break;
if ( v5 == 401959373 )
{
++v9;
v5 = -541349338;
}
else
{
v8 += (v7 + ((16 * v7) ^ (v7 >> 5))) ^ (*(_DWORD *)(a3 + 4LL * (v6 & 3)) + v6);
v6 -= 1640531527;
v7 += (v8 + ((16 * v8) ^ (v8 >> 5))) ^ (*(_DWORD *)(a3 + 4LL * ((v6 >> 11) & 3)) + v6);
v5 = 401959373;
}
}
*a2 = v8;
result = v7;
a2[1] = v7;
return result;
}
可以使用IDA的插件或者经验得出这一段加密是tea加密,然后根据unk_400E90里面的数据和key来解题,下面是找的解tea的脚本:
#include <iostream>
#include <stdio.h>
#include <stdint.h>
void jm(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4])
{
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x61C88647;
for (i = 0; i < num_rounds; i++)
{
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum -= delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = v0;
v[1] = v1;
}
void dm(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4])
{
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x61C88647, sum = 0xc6ef3720;
for (i = 0; i < num_rounds; i++)
{
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum += delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0;
v[1] = v1;
}
int main()
{
uint32_t enc[] = { 0x168f8672, 0x2dbd824, 0xcf647fca, 0xe6efa7ef, 0x4ae016f0, 0xc5832e1d, 0x455c0a05, 0xffeb8140, 0xbe9561ef, 0x7f819e23, 0x3bc04269, 0xc68b825b, 0xe6a5b1f0, 0xbd03cbbd, 0xa9b3ce0e, 0x6c85e6e7, 0x9f5c71ef, 0x3be4bd57 };
uint32_t key[4] = { 0xDEADBEEF, 0x87654321, 0xFACEB00C, 0xCAFEBABE };
unsigned int r = 32;
int n = sizeof(enc) / sizeof(uint32_t);
for (int i = 0; i < n / 2; i++)
{
dm(r, &enc[i * 2], key);
printf("%s", &enc[i * 2]);
}
return 0;
}
解出的flag是DASCTF{Don't_forget_to_drink_tea}
Comments | NOTHING