环境配置系统 : Windows 7 程序 : 初世纪 要求 : 输入口令 使用工具 :IDA
开始分析首先我们用ida载入程序,观察其输出。ida提示这是一个64位的程序,所以,我们再次用idax64打开,并且根据左边函数窗口,定位到start位置:
int start()
{
sub_140002250();
return sub_1400017F8();
}
单击进入看看:
__int64 sub_140002250()
{
signed __int64 v0; // rax@1
__int64 result; // rax@5
unsigned __int64 v2; // [sp+30h] [bp+10h]@2
struct _FILETIME SystemTimeAsFileTime; // [sp+38h] [bp+18h]@1
LARGE_INTEGER PerformanceCount; // [sp+40h] [bp+20h]@2
SystemTimeAsFileTime = 0i64;
v0 = _security_cookie;
if ( _security_cookie == 47936899621426i64 )
{
GetSystemTimeAsFileTime(&SystemTimeAsFileTime);
v2 = 0i64;
v2 = GetCurrentThreadId();
v2 ^= GetCurrentProcessId();
QueryPerformanceCounter(&PerformanceCount);
v0 = ((unsigned __int64)&v2 ^ v2 ^ PerformanceCount.QuadPart ^ ((unsigned __int64)PerformanceCount.LowPart << 32)) & 0xFFFFFFFFFFFFi64;
if ( v0 == 47936899621426i64 )
v0 = 47936899621427i64;
_security_cookie = v0;
}
result = ~v0;
qword_140055008 = result;
return result;
}
函数没有什么特殊信息,我们直接运行该程序,发现这是一个窗口程序。也就是说,程序内自有消息循环的代码来处理事件,而输入flag并检测的代码自然就在其中。
查看左侧函数消息列表,发现函数DialogFunc:
INT_PTR __fastcall DialogFunc(HWND a1, int a2, unsigned __int16 a3)
{
INT_PTR result; // rax@3
if ( a2 != 273 || (unsigned int)a3 - 1 > 1 )
{
result = 0i64;
}
else
{
EndDialog(a1, 0i64);
result = 1i64;
}
return result;
}
我们右击函数名称,选择Jump to xref
查看调用函数的交叉引用列表:
Direction Type Address Text
--------- ---- ------- ----
Down o dialog_140001340+F6 lea r9, DialogFunc ; lpDialogFunc
Down o .pdata:000000014005803C RUNTIME_FUNCTION <rva DialogFunc, rva sub_1400012E0, \
双击第一个引用该函数的位置:
int __fastcall dialog_140001340(HWND a1, int a2, unsigned __int16 a3)
{
//delete some init code.
if ( !v6 )
{
DestroyWindow(v5);
return sub_1400016E0((unsigned __int64)&v14 ^ v30);
}
v7 = v6 - 256;
if ( !v7 )
{
v11 = LoadIconA(hInstance, (LPCSTR)0x70);
SendMessageA(v5, 0x80u, 1ui64, (LPARAM)v11);
SendDlgItemMessageA(v5, 1000, 0xC5u, 0x50ui64, 0i64);
v12 = GetDlgItem(v5, 1000);
SetFocus(v12);
return sub_1400016E0((unsigned __int64)&v14 ^ v30);
}
if ( v7 == 1 )
{
if ( v4 == 1002 )
{
SendMessageA(v5, 0x10u, 0i64, 0i64);
return sub_1400016E0((unsigned __int64)&v14 ^ v30);
}
if ( v4 != 1013 )
{
if ( v4 == 1014 || v4 == 40002 )
DialogBoxParamA(hInstance, (LPCSTR)0x67, v5, (DLGPROC)DialogFunc, 0i64);// DialogBoxParam函数根据对话框模板资源创建一个模态的对话框
return sub_1400016E0((unsigned __int64)&v14 ^ v30);
}
v8 = GetDlgItemTextA(v5, 1000, &String, 81);
GetDlgItemTextA(v5, 1000, &v23, 101);
if ( v8 != '\x06' || v23 != '6' || v24 != 'E' || v25 != 'w' || v26 != 'i' || v27 != '9' )
{
v9 = (CHAR *)&String1;
}
else
{
v9 = (CHAR *)&String1;
if ( v28 == 'H' )
{
v10 = (CHAR *)&v19;
LABEL_19:
lstrcpyA(v9, v10);
DialogBoxParamA(hInstance, (LPCSTR)0x79, v5, sub_1400012E0, 0i64);
return sub_1400016E0((unsigned __int64)&v14 ^ v30);
}
}
v10 = String2;
goto LABEL_19;
}
return sub_1400016E0((unsigned __int64)&v14 ^ v30);
}
可以看到if ( v7 == 1 )
就是在处理消息循环,程序中出现了GetDlgItemTextA函数,这就是在获取我们输入的字符串。
搜集证据GetDlgItemTextA函数的返回值就是用户字符串的实际长度,至于其他变量,我们双击v23查看栈变量视图:
-00000000000000D0 var_D0 db ?
-00000000000000CF var_CF db ?
-00000000000000CE var_CE db ?
-00000000000000CD var_CD db ?
-00000000000000CC var_CC db ?
-00000000000000CB var_CB db ?
就是连在一起的,程序中对输入有六次判断,将他们连接起来就是flag了。
夺旗成功运行程序输入6Ewi9H,单击check:
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课