首先用PEiD查一下编译器和壳,发现有UPX壳,直接用吾爱的upx脱壳机脱壳
用IDA反编译,得到如下:
[C] 纯文本查看 复制代码 int __cdecl main(int argc, const char **argv, const char **envp)
{
const char *v3; // eax
int v5; // [esp+14h] [ebp-2Ch]
char result; // [esp+1Ah] [ebp-26h]
char input; // [esp+29h] [ebp-17h]
int tree; // [esp+38h] [ebp-8h]
int *start; // [esp+3Ch] [ebp-4h]
sub_402400();
v5 = 0;
start = &v5;
welcome();
gets(&input);
if ( strlen(&input) != 15 )
{
printf("Nah... ur a fake reverser!");
exit(0);
}
tree = init(&input, 15);
pre(tree, start, (int)&result);
v3 = base64(&result); // base64加密
if ( !strncmp(v3, "aWNuZXJyc2VhZXRydmVl", 0x14u) )
{
puts("well done bro!");
printf("ur really know something about tree!");
}
else
{
printf("Nah.. ur an idiot!");
}
return 0;
}
题目给出提示是tree
进入init函数发现是用用户的输入初始化二叉树
[C] 纯文本查看 复制代码 v13 = 1;
i_1 = 0;
v11 = 0;
p = (int *)malloc(4 * len);
while ( i_1 < len ) //初始化用户的输入数据
{
sub_402B70(2.0, (long double)(v13 - 1));
v6 = (signed int)(double)2.0;
v10 = 0;
for ( i = 0; i < v6; ++i )
{
v5 = i_1 + i;
if ( i_1 + i >= len )
break;
v8 = 0;
if ( input[v5] != '#' )
{
v8 = malloc(12u);
*(_BYTE *)v8 = input[v5];
v8[1] = 0;
v8[2] = 0;
p[v5] = (int)v8;
}
if ( i_1 > 0 )
{
v4 = p[v11 + v10];
if ( i & 1 )
{
*(_DWORD *)(v4 + 8) = v8;//右子树
++v10;
}
else
{
*(_DWORD *)(v4 + 4) = v8; //左子树
}
}
}
v11 = i_1;
i_1 += v6;
++v13;
}
然后pre函数进行前序遍历,将遍历的结果保存在result_1这个数组里面
[C] 纯文本查看 复制代码 int __cdecl pre(int a, _DWORD *cnt, int *result_1)
{
int i; // eax
int result; // eax
if ( a )
{
i = (*cnt)++;
*((_BYTE *)result_1 + i) = *(_BYTE *)a;
pre(*(_DWORD *)(a + 4), cnt, result_1);
result = pre(*(_DWORD *)(a + 8), cnt, result_1);
}
return result;
}
//------------------------
对应的C前序遍历的源码
void print_preorder(node * tree) {
if(tree) {
printf("%d\n",tree->data);
print_preorder(tree->left);
print_preorder(tree->right);
}
}
最后用base64加密前序遍历的结果:
[C] 纯文本查看 复制代码 _BYTE *__cdecl sub_401794(char *a1)
{
_BYTE *v2; // [esp+18h] [ebp-20h]
signed int v3; // [esp+1Ch] [ebp-1Ch]
int v4; // [esp+24h] [ebp-14h]
int v5; // [esp+28h] [ebp-10h]
int v6; // [esp+2Ch] [ebp-Ch]
v3 = strlen(a1);
if ( v3 % 3 )
v6 = 4 * (v3 / 3 + 1);
else
v6 = 4 * (v3 / 3);
v2 = malloc(v6 + 1);
v2[v6] = 0;
v5 = 0;
v4 = 0;
while ( v6 - 2 > v5 )
{
v2[v5] = aAbcdefghijklmn[(unsigned __int8)a1[v4] >> 2];
v2[v5 + 1] = aAbcdefghijklmn[16 * (a1[v4] & 3) | ((unsigned __int8)a1[v4 + 1] >> 4)];
v2[v5 + 2] = aAbcdefghijklmn[4 * (a1[v4 + 1] & 0xF) | ((unsigned __int8)a1[v4 + 2] >> 6)];
v2[v5 + 3] = aAbcdefghijklmn[a1[v4 + 2] & 0x3F];
v4 += 3;
v5 += 4;
}
if ( v3 % 3 == 1 )
{
v2[v5 - 2] = '=';
v2[v5 - 1] = '=';
}
else if ( v3 % 3 == 2 )
{
v2[v5 - 1] = '=';
}
return v2;
}
与网上的base64源码比较:
[color=#0000ff]const[/color] [color=#0000ff]char[/color] * base64char = [color=#800000]"[/color][color=#800000]ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/[/color][color=#800000]"[/color][color=#000000];[/color][color=#0000ff]char[/color] * base64_encode( [color=#0000ff]const[/color] unsigned [color=#0000ff]char[/color] * bindata, [color=#0000ff]char[/color] * base64, [color=#0000ff]int[/color][color=#000000] binlength ){ [/color][color=#0000ff]int[/color][color=#000000] i, j; unsigned [/color][color=#0000ff]char[/color][color=#000000] current; [/color][color=#0000ff]for[/color] ( i = [color=#800080]0[/color], j = [color=#800080]0[/color] ; i < binlength ; i += [color=#800080]3[/color][color=#000000] ) { current [/color]= (bindata[i] >> [color=#800080]2[/color][color=#000000]) ; current [/color]&= (unsigned [color=#0000ff]char[/color])[color=#800080]0x3F[/color][color=#000000]; base64[j[/color]++] = base64char[([color=#0000ff]int[/color][color=#000000])current]; current [/color]= ( (unsigned [color=#0000ff]char[/color])(bindata[i] << [color=#800080]4[/color] ) ) & ( (unsigned [color=#0000ff]char[/color])[color=#800080]0x30[/color][color=#000000] ) ; [/color][color=#0000ff]if[/color] ( i + [color=#800080]1[/color] >=[color=#000000] binlength ) { base64[j[/color]++] = base64char[([color=#0000ff]int[/color][color=#000000])current]; base64[j[/color]++] = [color=#800000]'[/color][color=#800000]=[/color][color=#800000]'[/color][color=#000000]; base64[j[/color]++] = [color=#800000]'[/color][color=#800000]=[/color][color=#800000]'[/color][color=#000000]; [/color][color=#0000ff]break[/color][color=#000000]; }[/color]
[color=#000000] current [/color]|= ( (unsigned [color=#0000ff]char[/color])(bindata[i+[color=#800080]1[/color]] >> [color=#800080]4[/color]) ) & ( (unsigned [color=#0000ff]char[/color]) [color=#800080]0x0F[/color][color=#000000] ); base64[j[/color]++] = base64char[([color=#0000ff]int[/color][color=#000000])current]; current [/color]= ( (unsigned [color=#0000ff]char[/color])(bindata[i+[color=#800080]1[/color]] << [color=#800080]2[/color]) ) & ( (unsigned [color=#0000ff]char[/color])[color=#800080]0x3C[/color][color=#000000] ) ; [/color][color=#0000ff]if[/color] ( i + [color=#800080]2[/color] >=[color=#000000] binlength ) { base64[j[/color]++] = base64char[([color=#0000ff]int[/color][color=#000000])current]; base64[j[/color]++] = [color=#800000]'[/color][color=#800000]=[/color][color=#800000]'[/color][color=#000000]; [/color][color=#0000ff]break[/color][color=#000000]; } current [/color]|= ( (unsigned [color=#0000ff]char[/color])(bindata[i+[color=#800080]2[/color]] >> [color=#800080]6[/color]) ) & ( (unsigned [color=#0000ff]char[/color]) [color=#800080]0x03[/color][color=#000000] ); base64[j[/color]++] = base64char[([color=#0000ff]int[/color][color=#000000])current]; current [/color]= ( (unsigned [color=#0000ff]char[/color])bindata[i+[color=#800080]2[/color]] ) & ( (unsigned [color=#0000ff]char[/color])[color=#800080]0x3F[/color][color=#000000] ) ; base64[j[/color]++] = base64char[([color=#0000ff]int[/color][color=#000000])current]; } base64[j] [/color]= [color=#800000]'[/color][color=#800000]\0[/color][color=#800000]'[/color][color=#000000]; [/color][color=#0000ff]return[/color][color=#000000] base64;}[/color]
这里识别是base64可以用PEiD的密码学插件Krypto ANALyzer,也可以通过代码里的0x3f,>>2,>>4等特征来识别
if ( !strncmp(v3, "aWNuZXJyc2VhZXRydmVl", 0x14u) )
{
puts("well done bro!");
printf("ur really know something about tree!");
}
else
{
printf("Nah.. ur an idiot!");
}
最后比较base64之后的结果
那flag就是base64解码,然后模仿一下前序遍历就行了
In [2]: base64.b64decode("aWNuZXJyc2VhZXRydmVl")
Out[2]: b'icnerrseaetrvee'
|