【CTF reverse】新160個CrackMe之046-keyme1-x64dbg除錯+GetVersionExA

語言: CN / TW / HK

PETools檢視概況

32位程式,入口點Section: [UPX1], EP: 0x00012760

有upx殼,脫殼:.\upx.exe -d <your path to>\mfykm1.exe

根據參考連結2,也可以用ollydbg手動脫殼,~~以後再學吧~~。

被逆向exe可在參考連結2下載。

作者:hans774882968以及hans774882968

x64dbg動態分析

搜尋字串,點選Good Job那個串,即可定位到以下程式碼段。

0040150B | mov eax,dword ptr ss:[ebp-4] | 0040150E | cmp eax,dword ptr ds:[444410] | 00401514 | jne mfykm1.401524 | 00401516 | mov dword ptr ss:[esp],mfykm1.4400B0 | 4400B0:"\n\nGood Job! Make a keygen and tutorial and send it in to crackmes.de\n" 0040151D | call <JMP.&printf> | 00401522 | jmp mfykm1.401530 | 00401524 | mov dword ptr ss:[esp],mfykm1.4400F6 | 4400F6:"\n\nTry again, sorry!\n" 0040152B | call <JMP.&printf> | 00401530 | mov dword ptr ss:[esp],mfykm1.44010B | 44010B:"PAUSE"

關鍵跳就是00401514 | jne mfykm1.401524,而比較的兩個主體是eaxds:[444410]

本來我想試試記憶體斷點功能的,但是後來發現不同於ollydbg,x64dbg的記憶體斷點是記憶體頁的,沒啥用。

[444410]的程式碼就在若干printf語句的上面,很容易找到:

0040147E | push ebp | 0040147F | mov ebp,esp | 00401481 | sub esp,18 | 00401484 | and esp,FFFFFFF0 | 00401487 | mov eax,0 | 0040148C | add eax,F | 0040148F | add eax,F | 00401492 | shr eax,4 | 00401495 | shl eax,4 | 00401498 | mov dword ptr ss:[ebp-8],eax | 0040149B | mov eax,dword ptr ss:[ebp-8] | 0040149E | call mfykm1.40D1E0 | 004014A3 | call mfykm1.40CE20 | 004014A8 | call mfykm1.401390 | 004014AD | mov eax,dword ptr ds:[444558] | 004014B2 | imul eax,dword ptr ds:[444554] | 004014B9 | add eax,dword ptr ds:[44455C] | 004014BF | mov edx,eax | 004014C1 | sub edx,dword ptr ds:[444558] | 004014C7 | mov eax,dword ptr ds:[44455C] | 004014CC | imul eax,eax,CDD | 004014D2 | lea eax,dword ptr ds:[edx+eax] | 004014D5 | add eax,dword ptr ds:[44455C] | 004014DB | mov dword ptr ds:[444410],eax |

程式碼很短,而且可以看到只有3個函式呼叫。其中004014A8 | call mfykm1.401390是最後一個函式呼叫,因此我們在4014a8處打斷點,然後點“重新執行”。3個函式呼叫都執行後,發現幾個比較重要的記憶體[444554], [444558], [44455c]的值由全0變成了6, 2, 23f0。執行完後[444410]的值是parseInt("01CE8E1A",16) // 30314010,把這個30314010輸進去,果然是正確的。

進一步分析

根據以上程式碼,[444410]的值只依賴於這3個記憶體,因為eax, edx都被這3個記憶體的值覆蓋了。那麼後面幾條指令就根據這3個記憶體的值來模擬一遍即可。

不過我們不能滿足於此,我們可以看看上面3個函式哪些修改了以上3個記憶體。

小技巧:在CPU這個tab的彙編語句(左上角)或記憶體(左下角)的區域,滑鼠右鍵,選擇“轉到”,然後選擇“表示式”,即可輸入地址進行跳轉。

我們在第1個函式呼叫0040149E | call mfykm1.40D1E0處打斷點,並“重新執行”。可以發現第1個函式呼叫之前,到第2個函式之後,以上3個記憶體都是全0。因此只有第3個函式是有用的。

“步進”第3個函式,發現004013FE call <JMP.&GetVersionExA>之後3個關鍵記憶體一起發生了變化,變成了最終值6, 2, 23f0;而在此之前它們都是0。

結論:只有GetVersionExA有用。於是我們可以開始寫程式碼了。但根據參考連結1,GetVersionExA在Windows10下已經廢棄,其行為為:

Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2)

所以python應該是不存在這玩意的替代品的,~~有也懶得查了~~。所以這個註冊機就用cpp寫。

執行下面的cpp程式碼的demo函式,即可得知osvi.dwMajorVersion = 6, osvi.dwMinorVersion = 2, osvi.dwBuildNumber = 0x23f0

```cpp

include

include

void demo() { OSVERSIONINFO osvi; BOOL bIsWindowsXPorLater;

ZeroMemory (&osvi, sizeof (OSVERSIONINFO) );
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);

GetVersionEx (&osvi);

printf ("%d %d %d\n", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber);

bIsWindowsXPorLater =
    ( (osvi.dwMajorVersion > 5) ||
      ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1) ) );
if (bIsWindowsXPorLater)
    printf ("The system meets the requirements.\n");
else printf ("The system does not meet the requirements.\n");

}

int main() { demo(); OSVERSIONINFO osvi; BOOL bIsWindowsXPorLater;

ZeroMemory (&osvi, sizeof (OSVERSIONINFO) );
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);

GetVersionEx (&osvi);

const int x = osvi.dwMajorVersion, y = osvi.dwMinorVersion, z = osvi.dwBuildNumber;
int eax = y * x + z;
int edx = eax - y;
eax = z * 0xcdd + edx + z;
printf("%d\n",eax);
/*
004014AD | mov eax,dword ptr ds:[444558]           |
004014B2 | imul eax,dword ptr ds:[444554]          |
004014B9 | add eax,dword ptr ds:[44455C]           |
004014BF | mov edx,eax                             |
004014C1 | sub edx,dword ptr ds:[444558]           |
004014C7 | mov eax,dword ptr ds:[44455C]           |
004014CC | imul eax,eax,CDD                        |
004014D2 | lea eax,dword ptr ds:[edx+eax]          |
004014D5 | add eax,dword ptr ds:[44455C]           |
004014DB | mov dword ptr ds:[444410],eax           |
*/
return 0;

} ```

參考連結

  1. GetVersionExA文件:https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getversionexa
  2. https://www.bilibili.com/video/BV1Nf4y1F7bK