首先下载文件在detect it easy中进行查壳,
从 DIE 结果可以知道:
-
PE32,32 位 GUI 程序(Windows GUI)
-
编译器:Microsoft Visual C/C++ (12.00.9782)
-
调试信息:包含 PDB 路径(说明可能有符号信息)
-
Overlay 在偏移
0x2B000处有 0x64 字节数据(可能是附加数据或 flag) -
语言:C++
然后把它放入IDA中进行查看,
找到了关键函数 DialogFunc_0
int __stdcall DialogFunc_0(HWND hWnd, int a2, int a3, int a4)
{
int v4; // eax
char Source[260]; // [esp+50h] [ebp-310h] BYREF
_BYTE Text[257]; // [esp+154h] [ebp-20Ch] BYREF
__int16 v8; // [esp+255h] [ebp-10Bh]
char v9; // [esp+257h] [ebp-109h]
int Value; // [esp+258h] [ebp-108h]
CHAR String[260]; // [esp+25Ch] [ebp-104h] BYREF
memset(String, 0, sizeof(String));
Value = 0;
if ( a2 == 16 )
{
DestroyWindow(hWnd);
PostQuitMessage(0);
}
else if ( a2 == 273 )
{
if ( a3 == 1000 )
{
GetDlgItemTextA(hWnd, 1002, String, 260);
strlen(String);
if ( strlen(String) > 6 )
ExitProcess(0);
v4 = atoi(String);
Value = v4 + 1;
if ( v4 == 122 && String[3] == 120 && String[5] == 122 && String[4] == 121 )
{
strcpy(Text, "flag");
memset(&Text[5], 0, 0xFCu);
v8 = 0;
v9 = 0;
_itoa(Value, Source, 10);
strcat(Text, "{");
strcat(Text, Source);
strcat(Text, "_");
strcat(Text, "Buff3r_0v3rf|0w");
strcat(Text, "}");
MessageBoxA(0, Text, "well done", 0);
}
SetTimer(hWnd, 1u, 0x3E8u, TimerFunc);
}
if ( a3 == 1001 )
KillTimer(hWnd, 1u);
}
return 0;
}
这段代码是对话框处理函数,当点击 ID 为 1000 的按钮(应该是 "Crack" 按钮)时会执行验证逻辑:
1. 密码检查条件
if ( v4 == 122 && String[3] == 120 && String[5] == 122 && String[4] == 121 )
v4 = atoi(String),String 是用户输入的密码。
条件为:
-
atoi(String) == 122→ 输入字符串转换为整数后必须等于 122 -
String[3] == 'x'(ASCII 120) -
String[4] == 'y'(ASCII 121) -
String[5] == 'z'(ASCII 122)
注意:字符串索引从 0 开始,所以:
-
String[3]是第 4 个字符 -
String[4]是第 5 个字符 -
String[5]是第 6 个字符
2. 长度限制
if ( strlen(String) > 6 )
ExitProcess(0);
输入长度 ≤ 6 个字符
推导正确密码
我们设密码为 s[0]s[1]s[2]s[3]s[4]s[5](最多 6 字符):
-
atoi(String) == 122-
atoi会从字符串开始解析数字,直到遇到非数字字符 -
最简单的满足方式:
"122"(但这样长度不够 6 且后面的字符条件不满足)
-
-
考虑到后面有特定字符要求,且
atoi在遇到非数字字符时会停止解析,所以我们可以这样构造:-
让前三个字符是
"122"(这样atoi("122...") == 122) -
然后
s[3] = 'x',s[4] = 'y',s[5] = 'z'
-
所以密码是 :122xyz
验证:
-
atoi("122xyz")= 122 ✓ -
s[3] = 'x'✓ -
s[4] = 'y'✓ -
s[5] = 'z'✓ -
长度 = 6 ✓
生成 Flag
当密码正确时,代码生成 flag:
strcpy(Text, "flag");
_itoa(Value, Source, 10); // Value = v4 + 1 = 122 + 1 = 123
strcat(Text, "{");
strcat(Text, Source); // "123"
strcat(Text, "_");
strcat(Text, "Buff3r_0v3rf|0w");
strcat(Text, "}");
所以 flag 是:
flag{123_Buff3r_0v3rf|0w}
验证方法
-
运行程序 ,在输入框输入
122xyz -
点击 "Crack" 按钮
-
应该会弹出 "well done" 消息框,显示 flag