[逆向工程]160个CrackMe入门实战之ajj1.2解析(五)

[逆向工程]160个CrackMe入门实战之ajj1.2解析(五)

一.CKme002.exe功能

当"注册"按钮变为"注册了"则表明注册成功

以下是逆向步骤:

执行固定操作序列:程序会持续检查你是否遵循了特定的交互逻辑。你需要按顺序完成以下动作:

  • ok.txt 文件放入 X:\ajj.126.c0m\j\o\j\o\ok.txt路径下,解锁Edit2` 输入框。默认是X盘符,本次为方便修改内存为D盘。ok.txt的文本内容为

    shell 复制代码
    #写入文本 20 61 6A 6A D0 B4 B5 C4 43 4B 6D 65 D5 E6 C0 C3 21 FF FF 会在桌面生成一个ok.txt文件,将该文件拷贝到D:\ajj.126.c0m\j\o\j\o\ok.txt 该路径下
    $bytes = 0x20,0x61,0x6A,0x6A,0xD0,0xB4,0xB5,0xC4,0x43,0x4B,0x6D,0x65,0xD5,0xE6,0xC0,0xC3,0x21,0xFF,0xFF; [System.IO.File]::WriteAllBytes("$env:USERPROFILE\Desktop\ok.txt", $bytes)
  • 右键点击 程序界面的"注册"按钮 5次 ,当图片框中空白时左键双击,解除 Edit2 输入框的禁用状态。

  • 在用户名处输入 ajj

  • Edit2 框中输入 1_345,78,然后左键双击该输入框的任意位置。

  • 当图片显示为"性相近"时,将鼠标从程序窗口的右下角移入窗口内。

  • 当图片显示为"性本善"时,将鼠标从程序窗口的左下角移入窗口内。

  • 完成上述所有步骤后,label3 会显示一个介于 0 到 3 之间的数字,将它记录下来

  • 注册机源码如下,先编译为crackme_solver.exe可执行程序,运行注册机输入数字

    c++ 复制代码
    // crackme_solver.cpp
    // 编译方式:在 VSCode 中打开终端,执行:
    //  g++ crackme_solver.cpp -o crackme_solver.exe
    // 或者使用 MSVC:
    //   cl crackme_solver.cpp
    
    #include <iostream>
    #include <cstdio>
    
    #include <cstring>
    #include <algorithm>
    
    // 图片结构体
    struct Image {
        char szname[7];   // 图片名称,最多6个汉字+结束符
        int nNumber;      // 编号(1~4)
        int nLef;         // 左键点击对应的系数
        int nRight;       // 右键点击对应的系数
    };
    
    int main() {
        // 1. 初始化图片数组(与原始代码完全一致)
        Image aImage[4] = {0};
        sprintf_s(aImage[0].szname, sizeof(aImage[0].szname), "人之初");
        aImage[0].nNumber = 1;
        aImage[0].nLef = 0x2;   // 2
        aImage[0].nRight = 0x11; // 17
    
        sprintf_s(aImage[1].szname, sizeof(aImage[1].szname), "性本善");
        aImage[1].nNumber = 2;
        aImage[1].nLef = 0x3;   // 3
        aImage[1].nRight = 0x13; // 19
    
        sprintf_s(aImage[2].szname, sizeof(aImage[2].szname), "性相近");
        aImage[2].nNumber = 3;
        aImage[2].nLef = 0x5;   // 5
        aImage[2].nRight = 0x17; // 23
    
        sprintf_s(aImage[3].szname, sizeof(aImage[3].szname), "习相远");
        aImage[3].nNumber = 4;
        aImage[3].nLef = 0x7;   // 7
        aImage[3].nRight = 0x1B; // 27
    
        // 2. 获取用户输入
        int input;
        std::cout << "请输入前期步骤得到的数值 (1, 2, 3 或其他): ";
        std::cin >> input;
    
        // 3. 数值映射(与原始代码 switch 完全一致)
        int n;
        switch (input) {
        case 1:  n = 0x3D; break;   // 61
        case 2:  n = 0x34; break;   // 52
        case 3:  n = 0xDF; break;   // 223
        default: n = 0x41; break;   // 65
        }
    
        std::cout << "映射后的目标数值 n = " << n << std::endl;
    
        // 4. 暴力求解最优组合
        int nRes = 112;          // 最小点击次数初始值
        int nIL = 0, nIR = 0;    // 左键图片下标、右键图片下标
        int nJ = 0, nK = 0;      // 右键点击次数 j, 左键点击次数 k
    
        // 遍历所有图片组合
        for (int iL = 0; iL < 4; ++iL) {          // 左键图片(系数 nLef)
            for (int iR = 0; iR < 4; ++iR) {      // 右键图片(系数 nRight)
                // j 范围 1~14(右键次数,原始代码从1开始)
                for (int j = 1; j <= 14; ++j) {
                    // k 范围 0~112(左键次数,原始代码从0开始)
                    for (int k = 0; k <= 112; ++k) {
                        int value = aImage[iR].nRight * j + aImage[iL].nLef * k;
                        if (value == n && (j + k) < nRes) {
                            nIL = iL;
                            nIR = iR;
                            nJ = j;
                            nK = k;
                            nRes = j + k;
                        }
                    }
                }
            }
        }
    
        // 5. 输出结果
        if (nRes == 112) {
            std::cout << "未找到任何有效组合,请检查输入或算法边界!" << std::endl;
        } else {
            char szKey[512];
            sprintf_s(szKey, sizeof(szKey),
                "在"%s"图片时左键点击图片%d次\r\n\r\n在"%s"图片时右键点击图片%d次\r\n\r\n即可注册成功!",
                aImage[nIL].szname, nK,   // 注意:左键次数是 k
                aImage[nIR].szname, nJ);  // 右键次数是 j
            std::cout << szKey << std::endl;
        }
    
        // 暂停,方便查看结果(可选)
        system("pause");
        return 0;
    }
  • 当图是"习相远"时,左键点击一次,右键点击两次,注册成功

需要注意的点如下:

检查项 变量/地址 核心条件 逆向得出的操作要求
禁用点击注册 [ebx+31C] 其值不能为 0x3E7 绝对不能点击"注册"按钮
解锁第一个控件 [ebx+304] 其值不能为 0xC34 程序启动时,会检查固定路径下是否存在特定文件 (ok.txt)
解锁第二个控件 [ebx+308] 其值不能为 0x230D 需要右键点击 "注册"按钮5次 ,然后双击空白区域
鼠标移动与点击 [ebx+310] 其值必须为 0xF94 这是一个多步的、依赖上下文(如图片ID和鼠标坐标)的验证
用户名验证 [ebx+314] - 用户名必须为 ajj
另一个数据输入 [ebx+318] - 这对应于 Edit2 输入框的内容必须为 1_345,78

注册成功截图:

二.开始破解

2.1 Exeinfo查壳

32位程序,upx壳,未有明显语言标识

2.1.1 脱壳

既然有壳并且是upx壳,那么接下来可以用UPX 脱壳 工具进行脱壳操作

脱壳后重新命名程序为CKme002new.exe

再次查壳发现是Delphi语言编写,壳已经去掉了

注意:脱壳这一步可以不操作,因为现在一些的动态调试工具可以无视UPX壳,根据实际情况操作

2.2 x32dbg动态分析

2.2.1 查找核心逻辑

动态分析前先观察运行程序,运行程序有"注册"按钮,那么可以用E2A2工具查看"注册"按钮地址下断点

dbg在004474C0地址处下断点 输入注册名,点击"注册"按钮,运行至004474C0断点处

shift+f8 单步运行后发现代码处有ret ,相当于直接返回了,说明按正常思路找"注册",的思路是错误的,第一处就是不能点击注册那么在xdbg中继续查找发现有"注册了"字符串。依次在dbg反汇编窗口往上查看代码,发现有疑似段首代码

根据一般段首规则可猜测出入口地址代码

push ebx

mov ebx,eax

发现该代码地址为004473E4

004473E4在E2A2中是Timer2 事件入口地址

shell 复制代码
004473E4 | 53                       | push ebx                                             | ebx:&"<珺"
004473E5 | 8BD8                     | mov ebx,eax                                          | ebx:&"<珺", eax:&"<珺"
004473E7 | 81BB 04030000 340C0000   | cmp dword ptr ds:[ebx+304],C34                       |304=C34相等FormCreate读文件相关
004473F1 | 0F84 88000000            | je ckme002.44747F                                    | 
004473F7 | 81BB 08030000 0D230000   | cmp dword ptr ds:[ebx+308],230D                      |308不能等于230D Button1MouseDown相关
00447401 | 74 7C                    | je ckme002.44747F                                    |
00447403 | 81BB 10030000 940F0000   | cmp dword ptr ds:[ebx+310],F94                       |310 FormMouseMove Edit2双击图片框开启相关
0044740D | 75 70                    | jne ckme002.44747F                                   |
0044740F | 8B83 18030000            | mov eax,dword ptr ds:[ebx+318]                       | 318鼠标左键右键点不同图片累加不同的值,初始值为0
00447415 | 3B83 14030000            | cmp eax,dword ptr ds:[ebx+314]                       | 314 页面显示数字 1 2 3相关
0044741B | 75 62                    | jne ckme002.44747F                                   |
0044741D | 81BB 1C030000 E7030000   | cmp dword ptr ds:[ebx+31C],3E7                       |
00447427 | 74 56                    | je ckme002.44747F                                    |
00447429 | 33D2                     | xor edx,edx                                          | edx:&"<珺"
0044742B | 8B83 D8020000            | mov eax,dword ptr ds:[ebx+2D8]                       | eax:&"<珺"
00447431 | 8B08                     | mov ecx,dword ptr ds:[eax]                           | [eax]:"<珺"
00447433 | FF51 5C                  | call dword ptr ds:[ecx+5C]                           |
00447436 | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00447438 | 8B83 DC020000            | mov eax,dword ptr ds:[ebx+2DC]                       | eax:&"<珺"
0044743E | 8B08                     | mov ecx,dword ptr ds:[eax]                           | [eax]:"<珺"
00447440 | FF51 5C                  | call dword ptr ds:[ecx+5C]                           |
00447443 | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00447445 | 8B83 E0020000            | mov eax,dword ptr ds:[ebx+2E0]                       | eax:&"<珺"
0044744B | 8B08                     | mov ecx,dword ptr ds:[eax]                           | [eax]:"<珺"
0044744D | FF51 5C                  | call dword ptr ds:[ecx+5C]                           |
00447450 | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00447452 | 8B83 E4020000            | mov eax,dword ptr ds:[ebx+2E4]                       | eax:&"<珺"
00447458 | 8B08                     | mov ecx,dword ptr ds:[eax]                           | [eax]:"<珺"
0044745A | FF51 5C                  | call dword ptr ds:[ecx+5C]                           |
0044745D | A1 A8984400              | mov eax,dword ptr ds:[4498A8]                        | eax:&"<珺"
00447462 | 83C0 70                  | add eax,70                                           | eax:&"<珺"
00447465 | BA 8C744400              | mov edx,ckme002.44748C                               | edx:&"<珺", 44748C:"厉害厉害真厉害!佩服佩服真佩服!!"
0044746A | E8 EDC4FBFF              | call ckme002.40395C                                  |
0044746F | BA B8744400              | mov edx,ckme002.4474B8                               | edx:&"<珺", 4474B8:"注册了"

从Timer2 事件中可以看到有不同的五个判断,这5个判断和内存中的值有关 分别是[ebx+304]、[ebx+308]、[ebx+310]、[ebx+318]、[ebx+314]、[ebx+31C] 这几个内存地址中的值和不同的常量进行判断,有一个判断不通过则注册不了

2.2.2 判断层分析

接下来逐层分析这五个判断所用到值,顺序依次为

ebx+31C

ebx+304

ebx+308

ebx+310

ebx+314

ebx+318

其中31C 304 308 310 314 318 这些为常量,在dbg中可以使用常量跟踪法,查看那些地方都对这些值做了操作

dbg中鼠标指定这行代码0044741D | 81BB 1C030000 E7030000 | cmp dword ptr ds:[ebx+31C],3E7

2.2.2.1.右键查找引用 常数31C搜寻

查询到两处

查看代码

shell 复制代码
004474C0 | C780 1C030000 E7030000   | mov dword ptr ds:[eax+31C],3E7                       |
004474CA | C3                       | ret                                                  |

004474C0 是Button1Click事件,也就是"注册"事件,点击"注册"按钮后会直接退出,所以"注册"按钮是第一层障碍,不需要去点击

2.2.2.2 右键查找引用 常数304搜寻
shell 复制代码
地址=00446D8F
反汇编=mov dword ptr ds:[ebx+304],C34
地址=00446DB8
反汇编=mov dword ptr ds:[ebx+304],C34
地址=004473E7
反汇编=cmp dword ptr ds:[ebx+304],C34

目的是cmp dword ptr ds:[ebx+304],C34这个比较不能相等,如果相等则je ckme002.44747F 注册会失败

如果mov dword ptr ds:[ebx+304],C34和mov dword ptr ds:[ebx+304],C34这两处赋值的地方跳过,则会绕过je ckme002.44747F 判断,接着走下面的判断了

排查mov dword ptr ds:[ebx+304],C34这个赋值产生的条件,继续浏览代码发现,发现段首

push ebp

mov ebp,esp 地址00446C1C为 FormCreate 事件函数入口地址

shell 复制代码
00446C1C | 55                       | push ebp                                             |
00446C1D | 8BEC                     | mov ebp,esp                                          |
00446C1F | 81C4 30FEFFFF            | add esp,FFFFFE30                                     |
00446C25 | 53                       | push ebx                                             | ebx:&"<珺"
00446C26 | 33C9                     | xor ecx,ecx                                          |
00446C28 | 894D FC                  | mov dword ptr ss:[ebp-4],ecx                         |
00446C2B | 8BD8                     | mov ebx,eax                                          | ebx:&"<珺", eax:&"<珺"
00446C2D | 33C0                     | xor eax,eax                                          | eax:&"<珺"
00446C2F | 55                       | push ebp                                             |
00446C30 | 68 D86D4400              | push ckme002.446DD8                                  |
00446C35 | 64:FF30                  | push dword ptr fs:[eax]                              |
00446C38 | 64:8920                  | mov dword ptr fs:[eax],esp                           |
00446C3B | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00446C3D | 8B83 D8020000            | mov eax,dword ptr ds:[ebx+2D8]                       | eax:&"<珺"
00446C43 | E8 5CD3FDFF              | call ckme002.423FA4                                  |
00446C48 | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00446C4A | 8B83 DC020000            | mov eax,dword ptr ds:[ebx+2DC]                       | eax:&"<珺"
00446C50 | E8 4FD3FDFF              | call ckme002.423FA4                                  |
00446C55 | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00446C57 | 8B83 E0020000            | mov eax,dword ptr ds:[ebx+2E0]                       | eax:&"<珺"
00446C5D | E8 42D3FDFF              | call ckme002.423FA4                                  |
00446C62 | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00446C64 | 8B83 E4020000            | mov eax,dword ptr ds:[ebx+2E4]                       | eax:&"<珺"
00446C6A | E8 35D3FDFF              | call ckme002.423FA4                                  |
00446C6F | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00446C71 | 8B83 D8020000            | mov eax,dword ptr ds:[ebx+2D8]                       | eax:&"<珺"
00446C77 | E8 28D3FDFF              | call ckme002.423FA4                                  |
00446C7C | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00446C7E | 8B83 FC020000            | mov eax,dword ptr ds:[ebx+2FC]                       | eax:&"<珺"
00446C84 | E8 1BD3FDFF              | call ckme002.423FA4                                  |
00446C89 | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00446C8B | 8B83 F0020000            | mov eax,dword ptr ds:[ebx+2F0]                       | eax:&"<珺"
00446C91 | 8B08                     | mov ecx,dword ptr ds:[eax]                           | [eax]:"<珺"
00446C93 | FF51 5C                  | call dword ptr ds:[ecx+5C]                           |
00446C96 | 33D2                     | xor edx,edx                                          | edx:&"<珺"
00446C98 | 8B83 F0020000            | mov eax,dword ptr ds:[ebx+2F0]                       | eax:&"<珺"
00446C9E | E8 01D3FDFF              | call ckme002.423FA4                                  |
00446CA3 | BA 01000000              | mov edx,1                                            | edx:&"<珺"
00446CA8 | 8B83 D8020000            | mov eax,dword ptr ds:[ebx+2D8]                       | eax:&"<珺"
00446CAE | E8 19CCFDFF              | call ckme002.4238CC                                  |
00446CB3 | BA C0FEFFFF              | mov edx,FFFFFEC0                                     | edx:&"<珺"
00446CB8 | 8B83 D8020000            | mov eax,dword ptr ds:[ebx+2D8]                       | eax:&"<珺"
00446CBE | E8 E9CBFDFF              | call ckme002.4238AC                                  |
00446CC3 | BA 01000000              | mov edx,1                                            | edx:&"<珺"
00446CC8 | 8B83 DC020000            | mov eax,dword ptr ds:[ebx+2DC]                       | eax:&"<珺"
00446CCE | E8 F9CBFDFF              | call ckme002.4238CC                                  |
00446CD3 | BA 7E000000              | mov edx,7E                                           | edx:&"<珺", 7E:'~'
00446CD8 | 8B83 DC020000            | mov eax,dword ptr ds:[ebx+2DC]                       | eax:&"<珺"
00446CDE | E8 C9CBFDFF              | call ckme002.4238AC                                  |
00446CE3 | BA 01000000              | mov edx,1                                            | edx:&"<珺"
00446CE8 | 8B83 E0020000            | mov eax,dword ptr ds:[ebx+2E0]                       | eax:&"<珺"
00446CEE | E8 B9CBFDFF              | call ckme002.4238AC                                  |
00446CF3 | BA 7A000000              | mov edx,7A                                           | edx:&"<珺", 7A:'z'
00446CF8 | 8B83 E0020000            | mov eax,dword ptr ds:[ebx+2E0]                       | eax:&"<珺"
00446CFE | E8 C9CBFDFF              | call ckme002.4238CC                                  |
00446D03 | BA 01000000              | mov edx,1                                            | edx:&"<珺"
00446D08 | 8B83 E4020000            | mov eax,dword ptr ds:[ebx+2E4]                       | eax:&"<珺"
00446D0E | E8 99CBFDFF              | call ckme002.4238AC                                  |
00446D13 | BA C0FEFFFF              | mov edx,FFFFFEC0                                     | edx:&"<珺"
00446D18 | 8B83 E4020000            | mov eax,dword ptr ds:[ebx+2E4]                       | eax:&"<珺"
00446D1E | E8 A9CBFDFF              | call ckme002.4238CC                                  |
00446D23 | C783 08030000 8E020000   | mov dword ptr ds:[ebx+308],28E                       |
00446D2D | C783 0C030000 09000000   | mov dword ptr ds:[ebx+30C],9                         | 09:'\t'
00446D37 | C783 14030000 0B000000   | mov dword ptr ds:[ebx+314],B                         | 0B:'\v'
00446D41 | 33C0                     | xor eax,eax                                          | eax:&"<珺"
00446D43 | 8983 18030000            | mov dword ptr ds:[ebx+318],eax                       | eax:&"<珺"
00446D49 | BA EC6D4400              | mov edx,ckme002.446DEC                               | 原本作者要求的路径 "X:\\ajj.126.c0m\\j\\o\\j\\o\\ok.txt"
00446D4E | 8D85 30FEFFFF            | lea eax,dword ptr ss:[ebp-1D0]                       | [ebp-1D0]:"ヲA"
00446D54 | E8 EDE7FBFF              | call ckme002.405546                                  |
00446D59 | 8D85 30FEFFFF            | lea eax,dword ptr ss:[ebp-1D0]                       | [ebp-1D0]:"ヲA"
00446D5F | E8 07EAFBFF              | call ckme002.40576B                                  |
00446D64 | E8 8BBAFBFF              | call ckme002.4027F4                                  |
00446D69 | 85C0                     | test eax,eax                                         | 判断文件路径内容等是否正确
00446D6B | 75 4B                    | jne ckme002.446DB8                                   | 
00446D6D | 8D55 FC                  | lea edx,dword ptr ss:[ebp-4]                         |
00446D70 | 8D85 30FEFFFF            | lea eax,dword ptr ss:[ebp-1D0]                       | [ebp-1D0]:"ヲA"
00446D76 | E8 5DD1FBFF              | call ckme002.403ED8                                  |
00446D7B | E8 44BAFBFF              | call ckme002.4027C4                                  |
00446D80 | 8B45 FC                  | mov eax,dword ptr ss:[ebp-4]                         |从实际路径得到的字符串
00446D83 | BA 146E4400              | mov edx,ckme002.446E14                               | 实际的字符串
00446D88 | E8 0BCFFBFF              | call ckme002.403C98                                  |比较字符串
00446D8D | 74 0A                    | je ckme002.446D99                                    | 是必须要相等则跳过赋值,路径能找到,必须查找到字符串实际内容
00446D8F | C783 04030000 340C0000   | mov dword ptr ds:[ebx+304],C34                       |要越过这一步赋值
00446D99 | 8D85 30FEFFFF            | lea eax,dword ptr ss:[ebp-1D0]                       | [ebp-1D0]:"ヲA"
shell 复制代码
00446D54 | E8 EDE7FBFF              | call ckme003.405546                                  |
这行代码是跳转到405546地址,具体功能为
0040557A | 85D2                     | test edx,edx                                         | 检查传入的字符串指针(即文件路径 "D:\\ajj.126.c0m\\j\\o\\j\\o\\ok.txt")是否为 NULL
0040557C | 74 1B                    | je ckme003.405599                                    |

作者原本文件路径是X盘符,所以为了方便并且符合不为null将盘符修改为D盘

446DEC:"X:\ajj.126.c0m\j\o\j\o\ok.txt" 修改盘符

X 58 --->D 44 保证字符串长度一致 鼠标双击修改 修改为D盘 打补丁保存为CKme003.exe

DarkDe打开FormCreate 事件代码静态分析,发现字符串为' ajj写的CKme真烂! ' ,需注意前后都有不可见字符,那么需要跟代码在内存中查找前后空格十六进制值

跟踪代码找到 ajj写的CKme真烂! 对应的十六进制: 20 61 6A 6A D0 B4 B5 C4 43 4B 6D 65 D5 E6 C0 C3 21 FF FF

20 代表空格字符

FF FF 代表 ÿ ÿ (带分音符的小写 y)

需要用命令行将生成ok.txt文件以及将以上内容写入该文件,windows下Po'werShell执行以下命令,生成后将桌面生成的ok.txt复制到固定路径下:

shell 复制代码
#写入文本 20 61 6A 6A D0 B4 B5 C4 43 4B 6D 65 D5 E6 C0 C3 21 FF FF 会在桌面生成一个ok.txt文件,将该文件拷贝到D:\ajj.126.c0m\j\o\j\o\ok.txt 该路径下
$bytes = 0x20,0x61,0x6A,0x6A,0xD0,0xB4,0xB5,0xC4,0x43,0x4B,0x6D,0x65,0xD5,0xE6,0xC0,0xC3,0x21,0xFF,0xFF; [System.IO.File]::WriteAllBytes("$env:USERPROFILE\Desktop\ok.txt", $bytes)
2.2.2.3 右键查找引用 常数308搜寻
shell 复制代码
地址=00446D23
反汇编=mov dword ptr ds:[ebx+308],28E   FormCreate 事件赋初值
地址=00446FA7
反汇编=mov edx,dword ptr ds:[eax+308] 
地址=00446FBA
反汇编=add dword ptr ds:[eax+308],3
地址=00446FCB
反汇编=mov dword ptr ds:[eax+308],230D
地址=00446FDC
反汇编=cmp dword ptr ds:[eax+308],29D
地址=004473F7
反汇编=cmp dword ptr ds:[ebx+308],230D

从Timer2事件看,308不能等于230D,如果相等直接跳转到44747F 程序直接ret

shell 复制代码
004473F7 | 81BB 08030000 0D230000   | cmp dword ptr ds:[ebx+308],230D         | 308
00447401 | 74 7C                    | je ckme003.44747F                       |

Button1MouseDown 事件入口地址 注册按钮,需注意:

MouseDown 事件,其函数原型大致是 ,由此可判断是鼠标右键还是左键

shell 复制代码
procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

其中 Button 参数是一个枚举类型:

  • mbLeft = 0(左键)
  • mbRight = 1(右键)
  • mbMiddle = 2(中键)

这个 Button 参数正是通过 cl 寄存器传入的。因此:

  • 左键点击cl = 0
  • 右键点击cl = 1
shell 复制代码
00446FA4 | 55                       | push ebp                                | Button1MouseDown 事件入口地址 注册按钮
00446FA5 | 8BEC                     | mov ebp,esp                             |
00446FA7 | 8B90 08030000            | mov edx,dword ptr ds:[eax+308]          |
00446FAD | 81FA 0D230000            | cmp edx,230D                            |
00446FB3 | 74 20                    | je ckme003.446FD5                       |
00446FB5 | 80F9 01                  | cmp cl,1                                | cl 要等于1 代表是鼠标右键点击 ECX低8位
00446FB8 | 75 09                    | jne ckme003.446FC3                      |
00446FBA | 8380 08030000 03         | add dword ptr ds:[eax+308],3            | 点击一次加3 直至29D 0x29D减去0x28E再除以0x3最后结果等于5 也就是点击5次
00446FC1 | EB 12                    | jmp ckme003.446FD5                      |
00446FC3 | 81FA 94020000            | cmp edx,294                             |
00446FC9 | 7D 0A                    | jge ckme003.446FD5                      |
00446FCB | C780 08030000 0D230000   | mov dword ptr ds:[eax+308],230D         |
00446FD5 | 5D                       | pop ebp                                 |
00446FD6 | C2 0C00                  | ret C                                   |
00446FD9 | 8D40 00                  | lea eax,dword ptr ds:[eax]              | eax:&"<珺", [eax]:"<珺"
00446FDC | 81B8 08030000 9D020000   | cmp dword ptr ds:[eax+308],29D          | 图片框左键双击 图片不能点击 双击事件的处理函数名通常包含 DblClick 这个是Panel1DblClick事件入口地址Panel1DblClick事件就可以解禁 Edit2控件  308值等于29D时
00446FE6 | 75 0D                    | jne ckme003.446FF5                      | 308不等于29D就跳转
00446FE8 | B2 01                    | mov dl,1                                |
00446FEA | 8B80 F0020000            | mov eax,dword ptr ds:[eax+2F0]          | 双击图片框启用Edit2 2F0是控件Edit2的ID
00446FF0 | 8B08                     | mov ecx,dword ptr ds:[eax]              | [eax]:"<珺"
00446FF2 | FF51 5C                  | call dword ptr ds:[ecx+5C]              |启用Edit2
00446FF5 | C3                       | ret                                     |

从寄存器中也可判断位右键,右键点击"注册":

2.2.2.4 右键查找引用 常数310搜寻

310值,必须等于0xF94

相关事件函数 FormMouseMove、Edit2DblClick

要令地址 [310] 最终被赋值为 0xF94,必须依次通过三重判断:

  1. **控件 ID 为 0xE20(图片"性相近")**时,鼠标右下角移动(FormMouseMove 的 XY 坐标均足够大)→ 将 [310] 暂赋值为 0x10
  2. **控件 ID 为 0x2DC(图片"性本善")**时,鼠标左下角移动(X 小、Y 大)。
  3. [30C] 不能等于初始值 0x9
    • [30C] 的赋值条件:Edit2 字符串长度为 8,且第 2 位为 _、第 6 位为 ,(如 1_345,78 符合);
    • 用户名长度须为 3 的整数倍;
    • Edit2左键双击 ,此时 [30C] 的值由磁盘剩余空间决定。

以上三重条件全部满足后,[310] 最终被赋值为 0xF94

此外,若用户名为 "ajj",则显示隐藏控件 ID=0x2FC(Label3),其显示内容为 [30C] 的值。

shell 复制代码
004470EC | 55                       | push ebp                                | FormMouseMove事件入口 鼠标移动
004470ED | 8BEC                     | mov ebp,esp                             |
004470EF | 6A 00                    | push 0                                  |
004470F1 | 6A 00                    | push 0                                  |
004470F3 | 53                       | push ebx                                | ebx:&"<珺"
004470F4 | 8BD8                     | mov ebx,eax                             | ebx:&"<珺", eax:&"<珺"
004470F6 | 8B55 08                  | mov edx,dword ptr ss:[ebp+8]            | y坐标
004470F9 | 8B45 0C                  | mov eax,dword ptr ss:[ebp+C]            | x坐标
004470FC | 33C9                     | xor ecx,ecx                             | ecx:"<FD"
004470FE | 55                       | push ebp                                |
004470FF | 68 17724400              | push <ckme003.sub_447217>               |
00447104 | 64:FF31                  | push dword ptr fs:[ecx]                 |
00447107 | 64:8921                  | mov dword ptr fs:[ecx],esp              |
0044710A | 8B8B E0020000            | mov ecx,dword ptr ds:[ebx+2E0]          | image3控件地址
00447110 | 8079 47 01               | cmp byte ptr ds:[ecx+47],1              |
00447114 | 75 19                    | jne ckme003.44712F                      |
00447116 | 3D E2000000              | cmp eax,E2                              | eax:&"<珺"
0044711B | 7E 12                    | jle ckme003.44712F                      | X小于E2则跳
0044711D | 81FA 2C010000            | cmp edx,12C                             | y小于12c则跳
00447123 | 7E 0A                    | jle ckme003.44712F                      |
00447125 | C783 10030000 10000000   | mov dword ptr ds:[ebx+310],10           |
0044712F | 8B8B DC020000            | mov ecx,dword ptr ds:[ebx+2DC]          | image2控件
00447135 | 8079 47 01               | cmp byte ptr ds:[ecx+47],1              |
00447139 | 75 6C                    | jne ckme003.4471A7                      | 不是image2则跳
0044713B | 83F8 17                  | cmp eax,17                              | eax:&"<珺"
0044713E | 7D 67                    | jge ckme003.4471A7                      | x大于17则跳
00447140 | 81FA 2C010000            | cmp edx,12C                             | edx:"h4D"
00447146 | 7E 5F                    | jle ckme003.4471A7                      | y小于12c则跳
00447148 | 83BB 10030000 10         | cmp dword ptr ds:[ebx+310],10           |
0044714F | 75 56                    | jne ckme003.4471A7                      | 满足第一步则跳
00447151 | 83BB 0C030000 09         | cmp dword ptr ds:[ebx+30C],9            | 30c值初始值为9则跳
00447158 | 74 4D                    | je ckme003.4471A7                       |
0044715A | C783 10030000 940F0000   | mov dword ptr ds:[ebx+310],F94          | 最终目标
shell 复制代码
00446FF8 | 55                       | push ebp                                | Edit2双击事件入口地址
00446FF9 | 8BEC                     | mov ebp,esp                             |
00446FFB | 33C9                     | xor ecx,ecx                             | ecx:"<FD"
00446FFD | 51                       | push ecx                                | ecx:"<FD"
00446FFE | 51                       | push ecx                                | ecx:"<FD"
00446FFF | 51                       | push ecx                                | ecx:"<FD"
00447000 | 51                       | push ecx                                | ecx:"<FD"
00447001 | 51                       | push ecx                                | ecx:"<FD"
00447002 | 53                       | push ebx                                | ebx:&"<珺"
00447003 | 8BD8                     | mov ebx,eax                             | ebx:&"<珺", eax:&"<珺"
00447005 | 33C0                     | xor eax,eax                             | eax:&"<珺"
00447007 | 55                       | push ebp                                |
00447008 | 68 DF704400              | push <ckme003.sub_4470DF>               |
0044700D | 64:FF30                  | push dword ptr fs:[eax]                 |
00447010 | 64:8920                  | mov dword ptr fs:[eax],esp              |
00447013 | 8D55 FC                  | lea edx,dword ptr ss:[ebp-4]            | [ebp-04]:"h4D"
00447016 | 8B83 F0020000            | mov eax,dword ptr ds:[ebx+2F0]          | Edit2控件ID
0044701C | E8 6BD0FDFF              | call <ckme003.sub_42408C>               |
00447021 | 8B45 FC                  | mov eax,dword ptr ss:[ebp-4]            | [ebp-04]:"h4D"
00447024 | E8 5FCBFBFF              | call <ckme003.sub_403B88>               |
00447029 | 83F8 08                  | cmp eax,8                               | 8个字符强制要求
0044702C | 0F85 92000000            | jne ckme003.4470C4                      |
00447032 | 8D55 F8                  | lea edx,dword ptr ss:[ebp-8]            |
00447035 | 8B83 F0020000            | mov eax,dword ptr ds:[ebx+2F0]          | eax:&"<珺", [ebx+2F0]:&"<珺"
0044703B | E8 4CD0FDFF              | call <ckme003.sub_42408C>               |
00447040 | 8B45 F8                  | mov eax,dword ptr ss:[ebp-8]            |
00447043 | 8078 01 5F               | cmp byte ptr ds:[eax+1],5F              | eax+01:"iD", 5F:'_' 第二个字符是_
00447047 | 75 7B                    | jne ckme003.4470C4                      |
00447049 | 8D55 F4                  | lea edx,dword ptr ss:[ebp-C]            |
0044704C | 8B83 F0020000            | mov eax,dword ptr ds:[ebx+2F0]          | eax:&"<珺", [ebx+2F0]:&"<珺"
00447052 | E8 35D0FDFF              | call <ckme003.sub_42408C>               |
00447057 | 8B45 F4                  | mov eax,dword ptr ss:[ebp-C]            |
0044705A | 8078 05 2C               | cmp byte ptr ds:[eax+5],2C              | 2C:',' 第六个字符,
0044705E | 75 64                    | jne ckme003.4470C4                      |
00447060 | 8D55 F0                  | lea edx,dword ptr ss:[ebp-10]           |
00447063 | 8B83 E8020000            | mov eax,dword ptr ds:[ebx+2E8]          | 第一个输入框
00447069 | E8 1ED0FDFF              | call <ckme003.sub_42408C>               |
0044706E | 8B45 F0                  | mov eax,dword ptr ss:[ebp-10]           |
00447071 | E8 12CBFBFF              | call <ckme003.sub_403B88>               | eax = 用户名长度
00447076 | 83C0 03                  | add eax,3                               | eax = eax +3
00447079 | B9 03000000              | mov ecx,3                               | ecx:"<FD"
0044707E | 99                       | cdq                                     |
0044707F | F7F9                     | idiv ecx                                | 取模运算eax = eax % 3
00447081 | 85D2                     | test edx,edx                            | 不等于0则跳转
00447083 | 75 3F                    | jne ckme003.4470C4                      |
00447085 | 6A 00                    | push 0                                  |
00447087 | 6A 04                    | push 4                                  |
00447089 | 8D55 EC                  | lea edx,dword ptr ss:[ebp-14]           |
0044708C | 8B83 E8020000            | mov eax,dword ptr ds:[ebx+2E8]          | eax:&"<珺", [ebx+2E8]:&"<珺"
00447092 | E8 F5CFFDFF              | call <ckme003.sub_42408C>               |
00447097 | 8B45 EC                  | mov eax,dword ptr ss:[ebp-14]           |
0044709A | E8 E9CAFBFF              | call <ckme003.sub_403B88>               |
0044709F | 99                       | cdq                                     |
004470A0 | 52                       | push edx                                | edx:"h4D"
004470A1 | 50                       | push eax                                | eax:&"<珺"
004470A2 | 33C0                     | xor eax,eax                             | eax:&"<珺"
004470A4 | E8 E70EFCFF              | call <ckme003.sub_407F90>               | 磁盘余量的函数值当随机数
004470A9 | 030424                   | add eax,dword ptr ss:[esp]              | [esp]:"h4D"
004470AC | 135424 04                | adc edx,dword ptr ss:[esp+4]            | [esp+04]:sub_444774+12
004470B0 | 83C4 08                  | add esp,8                               |
004470B3 | 83C0 02                  | add eax,2                               | eax:&"<珺"
004470B6 | 83D2 00                  | adc edx,0                               | edx:"h4D"
004470B9 | E8 47ECFBFF              | call <ckme003.sub_405D05>               | 随机数hash 最终算出30c的值 只有0 1 2 3 四种可能

2.2.2.5 右键查找引用 常数314和318搜寻

314的值等于318的值

image1~4MouseDown 事件函数

[314] 已在上一流程中根据 [30C] 赋值:

  • 30C = 0/1/2/3 时,314 = 0x41 / 0x3D / 0x34 / 0xDF

[318] 通过点击第 1~4 幅图片(区分左/右键)累加不同数值得到。

最终条件[318] 必须等于 [314]

shell 复制代码
00447179 | C783 14030000 41000000   | mov dword ptr ds:[ebx+314],41           | 鼠标移动事件 依据30c值给314赋值
00447183 | EB 22                    | jmp ckme003.4471A7                      |
00447185 | C783 14030000 3D000000   | mov dword ptr ds:[ebx+314],3D           | 鼠标移动事件 依据30c值给314赋值
0044718F | EB 16                    | jmp ckme003.4471A7                      |
00447191 | C783 14030000 34000000   | mov dword ptr ds:[ebx+314],34           | 鼠标移动事件 依据30c值给314赋值
0044719B | EB 0A                    | jmp ckme003.4471A7                      |
0044719D | C783 14030000 DF000000   | mov dword ptr ds:[ebx+314],DF           | 鼠标移动事件 依据30c值给314赋值
004471A7 | 81BB 10030000 940F0000   | cmp dword ptr ds:[ebx+310],F94          |
004471B1 | 75 46                    | jne ckme003.4471F9                      |
004471B3 | 8D55 FC                  | lea edx,dword ptr ss:[ebp-4]            | [ebp-04]:"h4D"
004471B6 | 8B83 E8020000            | mov eax,dword ptr ds:[ebx+2E8]          | eax:&"<珺", [ebx+2E8]:&"<珺"
004471BC | E8 CBCEFDFF              | call <ckme003.sub_42408C>               |
004471C1 | 8B45 FC                  | mov eax,dword ptr ss:[ebp-4]            | [ebp-04]:"h4D"
004471C4 | BA 30724400              | mov edx,ckme003.447230                  | edx:"h4D", 447230:"ajj" 用户名是ajj 显示隐藏的label3 30c的值显示
004471C9 | E8 CACAFBFF              | call <ckme003.sub_403C98>               |
004471CE | 75 29                    | jne ckme003.4471F9                      |
004471D0 | B2 01                    | mov dl,1                                |
004471D2 | 8B83 FC020000            | mov eax,dword ptr ds:[ebx+2FC]          | label3 控件id
004471D8 | E8 C7CDFDFF              | call <ckme003.sub_423FA4>               |
004471DD | 8D55 F8                  | lea edx,dword ptr ss:[ebp-8]            |
004471E0 | 8B83 0C030000            | mov eax,dword ptr ds:[ebx+30C]          | eax:&"<珺"
004471E6 | E8 AD0AFCFF              | call <ckme003.sub_407C98>               |
004471EB | 8B55 F8                  | mov edx,dword ptr ss:[ebp-8]            |
004471EE | 8B83 FC020000            | mov eax,dword ptr ds:[ebx+2FC]          | label3 控件id

三.总结

整个验证流程涉及多重条件嵌套:控件图片触发、鼠标坐标范围、字符串格式与长度、磁盘剩余空间、以及多幅图片的左右键点击累加。

如果爆破会简单很多,目的是学习,更多细节还需慢慢补充,期待和大家一起进步!

相关推荐
浩浩测试一下3 小时前
汇编 数组与串指令(逆向分析)
汇编·逆向·二进制·免杀·串指令·汇编数组
程序0075 小时前
.NET玩转爬虫 遇到反爬 jsl cookie
逆向
RSCompany11 小时前
Frida 17 以后 Python API 跑旧版 JS 报 Java is not defined ?一行 import 直接恢复 Frida 16 体验
开发语言·python·逆向·hook·frida·android逆向·frida17
浩浩测试一下1 天前
汇编中的JCC指令 (逆向分析)
汇编·逆向·标志位·jcc指令·跳转指令·标志位寄存器
浩浩测试一下1 天前
汇编中的段与段寄存器(大小)段序 (逆向分析)
汇编·逆向·二进制·字节序·windows编程·内存地址排序
浩浩测试一下3 天前
汇编 位运算 (逆向分析)
汇编·逆向·位运算·asm·windows编程·二进制逆向
浩浩测试一下3 天前
汇编 高低八位寄存器数据存储方式(逆向分析)
汇编·网络安全·逆向·二进制·免杀·寄存器·windows编程
泡泡以安7 天前
Unidbg学习笔记(十三):固定随机干扰项
android·逆向
泡泡以安7 天前
Unidbg学习笔记(十六):Console Debugger
android·逆向
泡泡以安7 天前
Unidbg学习笔记(八):文件系统层补环境
android·逆向