[NPUCTF2020]Baby Obfuscation

64位无壳,主函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // ebx
int v5; // esi
int v6; // ebx
int v7; // ebx
int v8; // esi
int v9; // ebx
int v10; // ebx
int v11; // ebx
int v12; // esi
int v13; // eax
int v14; // ebx
int v15; // esi
int v16; // ebx
int v17; // eax
bool v18; // bl
int v19; // eax
int v20; // esi
int v21; // ebx
int v22; // ebx
int v23; // eax
int v24; // eax
int v25; // eax
int v26; // ebx
int A0X3[65]; // [rsp+20h] [rbp-60h] BYREF
char A0X2[1001]; // [rsp+130h] [rbp+B0h] BYREF
int A0X1[1001]; // [rsp+520h] [rbp+4A0h] BYREF
int A0X5[4]; // [rsp+14D0h] [rbp+1450h]
int A0X4[4]; // [rsp+14E0h] [rbp+1460h]
int V0X1; // [rsp+14F0h] [rbp+1470h]
int i_1; // [rsp+14F4h] [rbp+1474h]
int i_0; // [rsp+14F8h] [rbp+1478h]
int i; // [rsp+14FCh] [rbp+147Ch]

_main();
memset(A0X1, 0, 0xFA0ui64);
A0X1[1000] = 0;
memset(A0X3, 0, 0x100ui64);
A0X3[64] = 0;
for ( i = 0; i <= 64; ++i )
A0X3[i] = i + 1;
A0X4[0] = 2;
A0X4[1] = 3;
A0X4[2] = 4;
A0X4[3] = 5;
A0X5[0] = 2;
A0X5[1] = 3;
A0X5[2] = 4;
A0X5[3] = 5;
puts("WHERE IS MY KEY!?");
scanf("%32s", A0X2);
V0X1 = strlen(A0X2);
v3 = F0X1(A0X3[i_0], A0X3[i_0]);
for ( i_0 = v3 / A0X3[i_0]; i_0 <= V0X1; ++i_0 )
{
v4 = (A0X3[i_0] + A0X3[i_0 + 1]) * (A0X3[i_0] + A0X3[i_0 + 1]);
if ( v4 >= F0X5(2, 2) * A0X3[i_0] * A0X3[i_0 + 1] )
{
v5 = ~A0X2[F0X4(i_0, 1)];
v6 = F0X4(i_0, 1);
A0X1[i_0] = ~(v5 + A0X4[v6 % F0X5(2, 2)]);
}
v7 = F0X1(A0X3[i_0], A0X3[i_0 + 1]);
if ( v7 > F0X1(A0X3[i_0 + 1], ~(~A0X3[i_0 + 1] + A0X3[i_0])) )
{
v8 = A0X1[i_0];
v9 = F0X4(i_0, 1);
A0X1[i_0] = ~(~v8 + A0X3[v9 % F0X5(2, 2)]) * v8;
}
v10 = A0X3[i_0 + 1];
v11 = F0X5(2, 1) * v10;
v12 = A0X3[i_0];
v13 = F0X5(2, 1);
v14 = F0X1(v12 * v13, v11);
v15 = F0X5(2, 1);
if ( v14 == v15 * F0X1(A0X3[i_0], A0X3[i_0 + 1]) )
{
v16 = F0X4(i_0, 1);
A0X1[i_0] ^= A0X4[v16 % F0X5(2, 2)];
}
v17 = F0X5(V0X3, A0X3[i_0]);
v18 = v17 < A0X3[i_0] + 1;
v19 = F0X5(2, 4);
if ( F0X3(v19 >= i_0, v18) )
{
v20 = ~A0X2[F0X4(i_0, 1)];
v21 = F0X4(i_0, 1);
A0X1[i_0] ^= ~(v20 + A0X4[v21 % F0X5(2, 2)]);
}
v22 = F0X5(2, 3);
v23 = F0X1(A0X3[i_0], A0X3[i_0]);
A0X1[i_0] *= v22 + F0X5(2, v23 / A0X3[i_0]);
}
v24 = F0X5(2, 4);
if ( F0X4(v24, 1) != V0X1 )
goto LABEL_23;
v25 = F0X1(A0X3[i_1], A0X3[i_1]);
for ( i_1 = v25 / A0X3[i_1]; i_1 <= V0X1; ++i_1 )
{
v26 = A0X1[i_1];
if ( v26 == F0X4(A0X6[i_1], 1) / 10 )
++V0X2;
}
if ( V0X2 == V0X1 )
puts("\nPASS");
else
LABEL_23:
puts("\nDENIED");
return 0;
}

按顺序分析,逐个函数分析吧

各个函数

F0X1

int __cdecl F0X1(int a, int b)
{
int result; // eax

if ( b )
result = F0X1(b, a % b);
else
result = a;
return result;
}

欧几里得算法,辗转相除法,求出最大公倍数

F0X3&F0X2

bool __cdecl F0X3(bool a, bool b)
{
bool v2; // bl
bool v3; // al

v2 = F0X2(b, b);
v3 = F0X2(a, a);
return F0X2(v3, v2);
}
bool __cdecl F0X2(bool a, bool b)
{
return a == b && !a;
}

F0X4

int __cdecl F0X4(int a, int b)
{
return ~(~a + b);
}

F0X5

int __cdecl F0X5(int a, int b)
{
int ans; // [rsp+Ch] [rbp-4h]

ans = 1;
while ( b )
{
if ( (b & 1) != 0 )
ans *= a;
a *= a;
b >>= 1;
}
return ans;
}

最后再程序整体中推断

for ( i_0 = v3 / A0X3[i_0]; i_0 <= V0X1; ++i_0 )// i从1开始
{
v4 = (A0X3[i_0] + A0X3[i_0 + 1]) * (A0X3[i_0] + A0X3[i_0 + 1]);
if ( v4 >= F0X5(2, 2) * A0X3[i_0] * A0X3[i_0 + 1] )// if执行
{
v5 = ~key[F0X4(i_0, 1)];
v6 = F0X4(i_0, 1);
A0X1[i_0] = ~(v5 + A0X4[v6 % F0X5(2, 2)]);
}
v7 = F0X1(A0X3[i_0], A0X3[i_0 + 1]);
if ( v7 > F0X1(A0X3[i_0 + 1], ~(~A0X3[i_0 + 1] + A0X3[i_0])) )// 不执行
{
v8 = A0X1[i_0];
v9 = F0X4(i_0, 1);
A0X1[i_0] = ~(~v8 + A0X3[v9 % F0X5(2, 2)]) * v8;
}
v10 = A0X3[i_0 + 1];
v11 = F0X5(2, 1) * v10;
v12 = A0X3[i_0];
v13 = F0X5(2, 1);
v14 = F0X1(v12 * v13, v11);
v15 = F0X5(2, 1);
if ( v14 == v15 * F0X1(A0X3[i_0], A0X3[i_0 + 1]) )// if执行
{
v16 = F0X4(i_0, 1);
A0X1[i_0] ^= A0X4[v16 % F0X5(2, 2)];
}
v17 = F0X5(V0X3, A0X3[i_0]);
v18 = v17 < A0X3[i_0] + 1;
v19 = F0X5(2, 4);
if ( F0X3(v19 >= i_0, v18) ) // 不执行
{
v20 = ~key[F0X4(i_0, 1)];
v21 = F0X4(i_0, 1);
A0X1[i_0] ^= ~(v20 + A0X4[v21 % F0X5(2, 2)]);
}
v22 = F0X5(2, 3);
v23 = F0X1(A0X3[i_0], A0X3[i_0]);
A0X1[i_0] *= v22 + F0X5(2, v23 / A0X3[i_0]);
}

最后会执行的就如下所示,

A0X1[i_0] *= v22 + F0X5(2, v23 / A0X3[i_0]);

A0X1[i_0] ^= A0X4[v16 % F0X5(2, 2)];

A0X1[i_0] = ~(v5 + A0X4[v6 % F0X5(2, 2)]);

等效与

A0X1[i_0] *=10

A0X1[i_0] ^= A0X4[i_0-1 % 4]

然后这个替换
v5 = ~key[F0X4(i_0, 1)];
v6 = F0X4(i_0, 1);
A0X1[i_0] = ~(v5 + A0X4[v6 % F0X5(2, 2)]);
A0X1[i_0] = key[(i_0-1)%4]-A0X4[i_0-1 % 4]

脚本

A0X4=[2,3,4,5]
aox6=[0,0x1E79,0x1E79,0x2135,0x170D,0x1F41,0x1901,0x2CED,0x11F9,0x2649,0x2581,0x2DB5,0x14B5,0x25E5,0x2A31,0x30D5]
for i in range(1,16):
aox6[i]//=100
aox6[i]^=A0X4[(i-1)%4]
aox6[i]+=A0X4[(i-1)%4]
print(chr(aox6[i]),end="")
# NPUCTF{0bfu5er}