main函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // eax
char v5; // al
int v6; // eax
int v7; // eax
int v8; // eax
char v10[52]; // [esp+4h] [ebp-38h] BYREF
v3 = sub_401890();
std::ostream::operator<<(v3, sub_401AD0);
sub_401BD0((int)v10);
if ( IsDebuggerPresent() || strlen(v10) != 24 )
{
v4 = sub_401890();
std::ostream::operator<<(v4, sub_401AD0);
Sleep(0x7D0u);
goto LABEL_3;
}
sub_401460();
v5 = sub_4012F0(v10);
*(_DWORD *)v10 = sub_401AD0;
if ( v5 )
{
v6 = sub_401890();
std::ostream::operator<<(v6, sub_401AD0);
v7 = sub_401890();
std::ostream::operator<<(v7, *(_DWORD *)v10);
system("pause");
LABEL_3:
exit(0);
}
v8 = sub_401890();
std::ostream::operator<<(v8, *(_DWORD *)v10);
Sleep(0x7D0u);
return 0;
}
首先读入字符串到v10中,然后要求v10的长度为24
之后关键函数sub_401460和sub_4012F0存在花指令,IDA无法分析。
去除如下图所示花指令
得到函数sub_401460
int sub_401460()
{
unsigned int v0; // eax
int result; // eax
int v2; // [esp+Ch] [ebp-30h]
int v3; // [esp+18h] [ebp-24h]
int v4; // [esp+1Ch] [ebp-20h]
int v5; // [esp+28h] [ebp-14h]
int v6; // [esp+2Ch] [ebp-10h]
int k; // [esp+30h] [ebp-Ch]
int j; // [esp+34h] [ebp-8h]
int i; // [esp+38h] [ebp-4h]
v6 = 0;
v0 = time(0);
srand(v0);
for ( i = 1; i <= 20; ++i )
{
dword_405460[i] = dword_40545C[i] + rand() % 5;
if ( v6 <= dword_405460[i] )
v5 = dword_405460[i];
else
v5 = v6;
v6 = v5;
}
v3 = time(0);
for ( j = 0; ; ++j )
{
result = j;
if ( j >= 6 )
break;
v4 = 0;
v2 = time(0);
result = v3;
if ( v2 - v3 > v6 )
break;
for ( k = 0; k <= 20; ++k )
{
if ( v2 - v3 <= dword_405460[k] )
{
v4 = dword_405460[k];
break;
}
}
*((_DWORD *)&xmmword_405034 + j) = (3 * j + v4 + dword_405030 * *((_DWORD *)&xmmword_405034 + j)) % 32;
v3 = v2;
}
return result;
}
函数sub_4012F0
char __cdecl sub_4012F0(const char *a1)
{
int v1; // esi
int v3; // [esp+14h] [ebp-14h]
int i; // [esp+1Ch] [ebp-Ch]
int v5; // [esp+20h] [ebp-8h]
v3 = 0;
for ( i = 0; i < strlen(a1); i += 4 )
{
v1 = __ROR4__(
a1[i + 3] | (a1[i + 2] << 8) | (a1[i + 1] << 16) | (a1[i] << 24),
*((_DWORD *)&xmmword_405034 + i / 4));
v5 = ((v1 << 16) | (unsigned __int16)~HIWORD(v1)) ^ (1 << *((_DWORD *)&xmmword_405034 + i / 4));
if ( i > 0 )
v5 ^= v3;
v3 = v5;
if ( v5 != dword_405018[i / 4] )
return 0;
}
return 1;
}
通过搜索提示字符串可知,sub_4012F0返回值为1表示输入正确。
要想根据sub_4012F0推知正确字符串需要获取sub_401460得到的xmmword_405034。
利用ollydbg动调发现结果受到每次循环的时间差v2 - v3的影响,而程序正常运行是时间差可以看做为0,因此对程序做一下修改使得时间差为0。
然后动调求xmmword_405034的值
得到结果为
0x03, 0x10, 0x0d, 0x04, 0x13, 0x0b
根据sub_4012F0写出对应的解密程序
#include<bits/stdc++.h>
using namespace std;
unsigned int dword_405018[6] = {2351698746u, 4148999158u, 4276070130u, 2871606843u, 651135530u, 2292314745u};
const unsigned int xmmword_405034[6] = {0x03, 0x10, 0x0d, 0x04, 0x13, 0x0b};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
vector<char> ans(24);
for (int i = 5; i >= 1; i--)dword_405018[i] ^= dword_405018[i - 1];
for (int i = 0; i < 24; i += 4) {
unsigned int tmp = dword_405018[i >> 2] ^ (1 << xmmword_405034[i >> 2]);
tmp = (~tmp << 16) | (tmp >> 16);
tmp = (tmp << xmmword_405034[i >> 2]) | (tmp >> (32 - xmmword_405034[i >> 2]));
ans[i] = char(tmp >> 24 & 0xFF);
ans[i + 1] = char(tmp >> 16 & 0xFF);
ans[i + 2] = char(tmp >> 8 & 0xFF);
ans[i + 3] = char(tmp & 0xFF);
}
for (char c: ans)cout << c;
return 0;
}
运行得到flag
flag{a_3a2y_re_for_test}