0%

攻防世界testre

Testre

用ida打开文件找到main函数可看到两个关键函数

查看函数sub_400D00(成功加载)

再查看函数sub_400700,可以看到,函数十分复杂

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
__int64 __fastcall sub_400700(void *a1, _QWORD *a2, __int64 a3, size_t a4)
{
unsigned __int8 *v4; // rcx
_DWORD v6[2]; // [rsp+0h] [rbp-C0h] BYREF
int c; // [rsp+8h] [rbp-B8h]
char v8; // [rsp+Fh] [rbp-B1h]
int v9; // [rsp+10h] [rbp-B0h]
bool v10; // [rsp+17h] [rbp-A9h]
unsigned __int8 *v11; // [rsp+18h] [rbp-A8h]
char v12; // [rsp+27h] [rbp-99h]
int v13; // [rsp+28h] [rbp-98h]
int v14; // [rsp+2Ch] [rbp-94h]
unsigned __int64 i; // [rsp+30h] [rbp-90h]
size_t n; // [rsp+38h] [rbp-88h]
size_t v17; // [rsp+40h] [rbp-80h]
size_t v18; // [rsp+48h] [rbp-78h]
size_t j; // [rsp+50h] [rbp-70h]
size_t v20; // [rsp+58h] [rbp-68h]
int v21; // [rsp+64h] [rbp-5Ch]
unsigned __int64 v22; // [rsp+68h] [rbp-58h]
int v23; // [rsp+74h] [rbp-4Ch]
_DWORD *v24; // [rsp+78h] [rbp-48h]
__int64 v25; // [rsp+80h] [rbp-40h]
void *v26; // [rsp+88h] [rbp-38h]
int v27; // [rsp+94h] [rbp-2Ch]
size_t v28; // [rsp+98h] [rbp-28h]
__int64 v29; // [rsp+A0h] [rbp-20h]
_QWORD *v30; // [rsp+A8h] [rbp-18h]
void *s; // [rsp+B0h] [rbp-10h]
char v32; // [rsp+BFh] [rbp-1h]

s = a1;
v30 = a2;
v29 = a3;
v28 = a4;
v27 = -559038737;
v26 = malloc(0x100uLL);
v25 = v29;
v24 = v6;
v22 = 0LL;
v17 = 0LL;
for ( i = 0LL; i < v28; ++i )
{
v13 = *(unsigned __int8 *)(v25 + i);
*((_BYTE *)v26 + i) = byte_400E90[i % 0x1D] ^ v13;
*((_BYTE *)v26 + i) += *(_BYTE *)(v25 + i);
}
while ( 1 )
{
v12 = 0;
if ( v17 < v28 )
v12 = ~(*(_BYTE *)(v25 + v17) != 0);
if ( (v12 & 1) == 0 )
break;
++v17;
}
n = 138 * (v28 - v17) / 0x64 + 1;
v23 = ((v17 + v28) << 6) / 0x30 - 1;
v11 = (unsigned __int8 *)v6 - ((138 * (v28 - v17) / 0x64 + 16) & 0xFFFFFFFFFFFFFFF0LL);
memset(v11, 0, n);
v20 = v17;
v18 = n - 1;
while ( v20 < v28 )
{
v21 = *(unsigned __int8 *)(v25 + v20);
for ( j = n - 1; ; --j )
{
v10 = 1;
if ( j <= v18 )
v10 = v21 != 0;
if ( !v10 )
break;
v22 = v11[j] << 6;
v21 += v11[j] << 8;
v9 = 64;
v11[j] = v21 % 58;
*((_BYTE *)v26 + j) = v22 & 0x3F;
v22 >>= 6;
v21 /= 58;
v27 /= v9;
if ( !j )
break;
}
++v20;
v18 = j;
}
for ( j = 0LL; ; ++j )
{
v8 = 0;
if ( j < n )
v8 = ~(v11[j] != 0);
if ( (v8 & 1) == 0 )
break;
}
if ( *v30 > n + v17 - j )
{
if ( v17 )
{
c = 61;
memset(s, 49, v17);
memset(v26, c, v17);
}
v20 = v17;
while ( j < n )
{
v4 = v11;
*((_BYTE *)s + v20) = byte_400EB0[v11[j]];
*((_BYTE *)v26 + v20++) = byte_400EF0[v4[j++]];
}
*((_BYTE *)s + v20) = 0;
*v30 = v20 + 1;
if ( !strncmp((const char *)s, "D9", 2uLL)
&& !strncmp((const char *)s + 20, "Mp", 2uLL)
&& !strncmp((const char *)s + 18, "MR", 2uLL)
&& !strncmp((const char *)s + 2, "cS9N", 4uLL)
&& !strncmp((const char *)s + 6, "9iHjM", 5uLL)
&& !strncmp((const char *)s + 11, "LTdA8YS", 7uLL) )
{
v6[1] = puts("correct!");
}
v32 = 1;
v14 = 1;
}
else
{
*v30 = n + v17 - j + 1;
v32 = 0;
v14 = 1;
}
return v32 & 1;
}

最后将s与一串字符进行比较

参考别人的wp,发现程序中大多数都是无用的混淆代码,关键部分如下

这里出现了v11

base64加密原理

base系列浅析

官方wp是这么说的

所以最后比较的就是输入后的baee58加密是否相等,那拿D9cS9N9iHjMLTdA8YSMRMp在线解密即可得到flag: