刮开有奖

捕获

查壳发现是一个32位无壳

进入WINMain主函数1

关键点在于DialogFunc函数里面,进去查看

2

看一遍下来通过代码GetDlgItemTextA(hDlg, 1000, &String, 0xFFFF);
知道了String是我们输入的flag。通过代码**if ( strlen(&String) == 8 )**,我们知道flag的长度应该是8。再从上往下慢慢分析,先给V7-V17赋值,进入函数sub_4010F0

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
int __cdecl sub_4010F0(int a1, int a2, int a3)
{
int result; // eax
int i; // esi
int v5; // ecx
int v6; // edx

result = a3;
for ( i = a2; i <= a3; a2 = i )
{
v5 = 4 * i;
v6 = *(_DWORD *)(4 * i + a1);
if ( a2 < result && i < result )
{
do
{
if ( v6 > *(_DWORD *)(a1 + 4 * result) )
{
if ( i >= result )
break;
++i;
*(_DWORD *)(v5 + a1) = *(_DWORD *)(a1 + 4 * result);
if ( i >= result )
break;
while ( *(_DWORD *)(a1 + 4 * i) <= v6 )
{
if ( ++i >= result )
goto LABEL_13;
}
if ( i >= result )
break;
v5 = 4 * i;
*(_DWORD *)(a1 + 4 * result) = *(_DWORD *)(4 * i + a1);
}
--result;
}
while ( i < result );
}
LABEL_13:
*(_DWORD *)(a1 + 4 * result) = v6;
sub_4010F0(a1, a2, i - 1);
result = a3;
++i;
}
return result;
}

发现是一个排序的函数,将前面赋值的十个数从小到大排序

4

点击查看V23

5

V23等于string[5],依次可以看出V24等等

*v4 = (const char )sub_401000(&v26, strlen(&v26));,接下来继续看sub_401000

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
_BYTE *__cdecl sub_401000(int a1, int a2)
{
int v2; // eax
int v3; // esi
size_t v4; // ebx
_BYTE *v5; // eax
_BYTE *v6; // edi
int v7; // eax
_BYTE *v8; // ebx
int v9; // edi
signed int v10; // edx
int v11; // edi
signed int v12; // eax
signed int v13; // esi
_BYTE *result; // eax
_BYTE *v15; // [esp+Ch] [ebp-10h]
_BYTE *v16; // [esp+10h] [ebp-Ch]
int v17; // [esp+14h] [ebp-8h]
int v18; // [esp+18h] [ebp-4h]

v2 = a2 / 3;
v3 = 0;
if ( a2 % 3 > 0 )
++v2;
v4 = 4 * v2 + 1;
v5 = malloc(v4);
v6 = v5;
v15 = v5;
if ( !v5 )
exit(0);
memset(v5, 0, v4);
v7 = a2;
v8 = v6;
v16 = v6;
if ( a2 > 0 )
{
while ( 1 )
{
v9 = 0;
v10 = 0;
v18 = 0;
do
{
if ( v3 >= v7 )
break;
++v10;
v9 = *(unsigned __int8 *)(v3++ + a1) | (v9 << 8);
}
while ( v10 < 3 );
v11 = v9 << 8 * (3 - v10);
v12 = 0;
v17 = v3;
v13 = 18;
do
{
if ( v10 >= v12 )
{
*((_BYTE *)&v18 + v12) = (v11 >> v13) & 0x3F;
v8 = v16;
}
else
{
*((_BYTE *)&v18 + v12) = 64;
}
*v8++ = byte_407830[*((char *)&v18 + v12)];
v13 -= 6;
++v12;
v16 = v8;
}
while ( v13 > -6 );
v3 = v17;
if ( v17 >= a2 )
break;
v7 = a2;
}
v6 = v15;
}
result = v6;
*v8 = 0;
return result;
}

7

看到这个就知道是熟悉的base64加密

1
2
3
4
5
6
if ( String == v7 + 34                       // sub_4010F0函数后的第一位等于51+34=85-->'U'
&& string[1] == v11 // 第2位,等于v13,即sub_4010F0函数返回值的第5位值-->'J'
&& 4 * string[2] - 141 == 3 * v9
&& string[3] / 4 == 2 * (v14 / 9)
&& !strcmp(v4, "ak1w")
&& !strcmp(v5, "V1Ax") )

看最后的一段代码

然后通过python脚本解密ak1w和V1Ax

1
2
3
4
5
6
7
8
import base64
str1 = 'ak1w'
str2 = 'V1Ax'
flag1 = base64.b64decode(str1)
flag2 = base64.b64decode(str2)
print(flag1)
print(flag2)

得到 jMp和WP1

上面第三行和第四行代码是比较 4*’x-141==3 *69 算出来x=87,是W

所以WP1在前面,flag就可以组合起来了