欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

CTF 逆转] 新 160 CrackMe 046-keyme1-x64dbg 调试新 160 CrackMe 046-keyme1-x64dbg 调试+GetVersionExA

最编程 2024-04-16 16:54:48
...

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

#include <windows.h>
#include <stdio.h>

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文档:docs.microsoft.com/en-us/windo…
  2. www.bilibili.com/video/BV1Nf…