先運行一下程序,發現flag是一串亂碼,還好知道這個re題,不然又是一頓亂操作(爬。
很快找到主函數,F5反編譯。
xxxxxxxxxx
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);//win32函數創建堆
lpMem = (CHAR *)HeapAlloc(hHeap, 8u, MaxCount + 1);//win32爲堆申請空間
memcpy_s(lpMem, MaxCount, &unk_409B10, MaxCount);//猜測將unk_409b10賦值給堆lpMem
if ( sub_40102A() || IsDebuggerPresent() )//第二個函數是判斷是否被調試如果被調試就返回非零。
{
__debugbreak();//暫停程序執行,打開調試器,進入調試模式。(不知道做什麼用的)
sub_401000(v3 + 4, lpMem);
ExitProcess(0xFFFFFFFF);
}
MessageBoxA(0, lpMem + 1, "Flag", 2u);//win32釋放一個標題爲“Flag”,內容爲lpMem+1的文本框
HeapFree(hHeap, 0, lpMem);//釋放空間
HeapDestroy(hHeap);//銷燬對象
ExitProcess(0);
}
不妨看一下其他的函數。
xxxxxxxxxx
int sub_40102A()
{
char v0; // t1
v0 = *(_BYTE *)(*(_DWORD *)(__readfsdword(0x18u) + 48) + 2);
return 0;
}//一定返回0
那麼正常打開的情況下條件語句中的代碼沒有被執行。那麼我們不妨直接看一下lpMem(即unk_409b10)的內容:
顯然是符合亂碼的。
接下來看一下分支語句中的函數:
xxxxxxxxxx
unsigned int __fastcall sub_401000(int a1, char *a2)
{
int v2; // esi
char *v3; // eax
unsigned int v4; // ecx
unsigned int result; // eax
v2 = dword_409B38;
v3 = &a2[strlen(a2 + 1) + 2];
v4 = 0;
result = ((unsigned int)(v3 - (a2 + 2)) >> 2) + 1;
if ( result )
{
do
*(_DWORD *)&a2[4 * v4++] ^= v2;//劃重點!!!
while ( v4 < result );
}
return result;
}
這裏對lpMem的內容進行了修改,應該就是解密函數。所以我們需要做的就是讓這一步運行。
這裏我們啓用OD(ollydebug)。
先用中文搜索引擎+智能搜索選擇"Flag“來快速定位到我們的函數(直接到達的位置應爲00C810A7,向上翻即可)
接下來我們應該做什麼?修改程序運行流程,做如下圖所示的三處修改:
1.抹除判斷語句的跳轉
2.抹除int3的異常
3.跳入第二個MassageBox()(第一個完全沒有入口是由於編譯器產生的一個無效的函數,鑑定方法:查看流程圖,感謝hsq學長的解答,hsqyyds)
Finally,you get it!
另外附上使用IDA調試的方法。