1.查壳
无壳,32位文件
打开文件
如题目所说,弹出的是乱码
2.拖入IDA
老规矩,拖入IDA,找main函数,反编译查看伪代码
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // ecx
CHAR *lpMem; // [esp+8h] [ebp-Ch]
HANDLE hHeap; // [esp+10h] [ebp-4h]
hHeap = HeapCreate(0x40000u, 0, 0);
lpMem = (CHAR *)HeapAlloc(hHeap, 8u, MaxCount + 1);
memcpy_s(lpMem, MaxCount, &unk_409B10, MaxCount);
if ( sub_40102A() || IsDebuggerPresent() )
{
__debugbreak();
sub_401000(v3 + 4, lpMem);
ExitProcess(0xFFFFFFFF);
}
MessageBoxA(0, lpMem + 1, "Flag", 2u);
HeapFree(hHeap, 0, lpMem);
HeapDestroy(hHeap);
ExitProcess(0);
}
分析代码
MessageBoxA(0, lpMem + 1, "Flag", 2u);
这一行应该就是弹框显示flag值得代码,但程序运行显示的是上图所示的乱码
继续分析代码
if ( sub_40102A() || IsDebuggerPresent() )
这个if语句中,暂且不管sub_40102A()这个函数是干什么的,IsDebuggerPresent()这个函数看起来就是判断是否处于调试器中,满足条件后,进入执行语句。
__debugbreak();
Microsoft 专用,将在代码中引起断点,并在其中提示用户运行调试程序。
接着看到sub_401000函数,双击进入
unsigned int __fastcall sub_401000(int a1, int a2)
{
int v2; // esi
unsigned int v3; // eax
unsigned int v4; // ecx
unsigned int result; // eax
v2 = dword_409B38;
v3 = a2 + 1 + strlen((const char *)(a2 + 1)) + 1;
v4 = 0;
result = ((v3 - (a2 + 2)) >> 2) + 1;
if ( result )
{
do
*(_DWORD *)(a2 + 4 * v4++) ^= v2;
while ( v4 < result );
}
return result;
}
看起来是个加密函数,应该和flag有关,将v2进行一系列操作后返回,然后退出,弹出flag。然而事实上并未显示flag,所以我们猜测这个函数并没有被执行,
于是我们再用OllyDbg打开文件
搜索字符串,根据Flag找到IsDebuggerPresent()函数的地址
可以看出,进行if判断后,程序直接跳过了sub_401000函数,然后跳出弹框,显示乱码,所以我们需要对程序进行修改使其执行sub_401000函数。
双击短跳转汇编代码,使其跳转到sub_401000函数地址的前一处,这样一来程序运行后就会执行生成flag的函数。接下来我们还需要使弹框显示flag,所以需要修改sub_401000函数之后的跳转语句,使其跳转到弹框位置
这里要注意,跳转到第二个flag位置处,因为flag是在lpMem + 1位置处弹出来的
修改完成后,就可以F9运行程序了
flag如预期一样弹了出来,可以在栈中找到flag值
这样flag就出来了