小日本的一款16进制编辑器 AXE v3.41 的注册算法简单分析

Homepage:
http://www.axe-editor.com/

Download:
Installer AXE 3.4.1
http://www.axe-editor.com/downloads/installAXE.exe

一款感觉还不错的hex编辑器,分析了下,简单写出来。

下断点: BP GetWindowTextA后,打开注册窗口,输入注册名:aCaFeeL,输入注册码:12345678,点击OK按钮,被中断下来,ALT+F9建后,回到AXE的领空:

>>>>>>
004B56E2  /$  56            push    esi
004B56E3  |.  8BF1          mov     esi, ecx
004B56E5  |.  8B4E 38       mov     ecx, dword ptr [esi+38]
004B56E8  |.  85C9          test    ecx, ecx
004B56EA  |.  75 2E         jnz     short AXE.004B571A
004B56EC  |.  FF76 1C       push    dword ptr [esi+1C]               ; /hWnd
004B56EF  |.  FF15 C0664E00 call    dword ptr [<&USER32.GetWindowTex>; \GetWindowTextLengthA
004B56F5  |.  8D48 01       lea     ecx, dword ptr [eax+1]
004B56F8  |.  51            push    ecx
004B56F9  |.  8B4C24 0C     mov     ecx, dword ptr [esp+C]
004B56FD  |.  50            push    eax
004B56FE  |.  E8 05E6FFFF   call    AXE.004B3D08
004B5703  |.  50            push    eax                              ; |Buffer
004B5704  |.  FF76 1C       push    dword ptr [esi+1C]               ; |hWnd
004B5707  |.  FF15 A0654E00 call    dword ptr [<&USER32.GetWindowTex>; \GetWindowTextA
004B570D  |.  8B4C24 08     mov     ecx, dword ptr [esp+8]           ; 回到了这里!!!!!!
004B5711  |.  6A FF         push    -1
004B5713  |.  E8 C8E5FFFF   call    AXE.004B3CE0
004B5718  |.  EB 0C         jmp     short AXE.004B5726
004B571A  |>  8B01          mov     eax, dword ptr [ecx]
004B571C  |.  FF7424 08     push    dword ptr [esp+8]
004B5720  |.  FF90 88000000 call    dword ptr [eax+88]
004B5726  |>  5E            pop     esi
004B5727  \.  C2 0400       retn    4                                ; 走完这个子Call
>>>>>>



走完上面的子程序后,来到了这里:

>>>>>>
0043F547   .  E8 96610700   call    AXE.004B56E2                     ;  这就是上面的子call
0043F54C   .  8D4C24 14     lea     ecx, dword ptr [esp+14]          ;  走完后,来到了这里:
0043F550   .  51            push    ecx
0043F551   .  68 29040000   push    429
0043F556   .  8BCE          mov     ecx, esi
0043F558   .  E8 75860700   call    AXE.004B7BD2
0043F55D   .  8BC8          mov     ecx, eax
0043F55F   .  E8 7E610700   call    AXE.004B56E2
0043F564   .  8B5424 14     mov     edx, dword ptr [esp+14]          ;  注册名 -> edx
0043F568   .  68 044D5100   push    AXE.00514D04                     ;  notfound
0043F56D   .  52            push    edx                              ;  压
0043F56E   .  E8 1DF00400   call    AXE.0048E590
0043F573   .  83C4 08       add     esp, 8
0043F576   .  3BC3          cmp     eax, ebx
0043F578      75 0C         jnz     short AXE.0043F586
0043F57A   .  53            push    ebx                              ; /Arg3
0043F57B   .  53            push    ebx                              ; |Arg2
0043F57C   .  68 F04C5100   push    AXE.00514CF0                     ; |no matches found.
0043F581   .  E8 0D020800   call    AXE.004BF793                     ; \AXE.004BF793
0043F586   >  8B4424 18     mov     eax, dword ptr [esp+18]          ;  注册码 -> eax
0043F58A   .  8D7E 5C       lea     edi, dword ptr [esi+5C]
0043F58D   .  57            push    edi
0043F58E   .  68 58245100   push    AXE.00512458                     ;  %lu
0043F593   .  50            push    eax
0043F594   .  E8 26CB0400   call    AXE.0048C0BF
0043F599   .  83C4 0C       add     esp, 0C
0043F59C   .  8D4C24 14     lea     ecx, dword ptr [esp+14]
0043F5A0   .  8D6E 60       lea     ebp, dword ptr [esi+60]
0043F5A3   .  51            push    ecx
0043F5A4   .  8BCD          mov     ecx, ebp
0043F5A6   .  E8 EF430700   call    AXE.004B399A
0043F5AB   .  51            push    ecx
0043F5AC   .  8BCC          mov     ecx, esp
0043F5AE   .  896424 14     mov     dword ptr [esp+14], esp
0043F5B2   .  55            push    ebp
0043F5B3   .  E8 1E400700   call    AXE.004B35D6
0043F5B8   .  8B17          mov     edx, dword ptr [edi]
0043F5BA   .  C64424 6C 01  mov     byte ptr [esp+6C], 1
0043F5BF   .  52            push    edx
0043F5C0   .  53            push    ebx
0043F5C1   .  E8 BA24FEFF   call    AXE.00421A80
0043F5C6   .  8BC8          mov     ecx, eax
0043F5C8   .  E8 5300FFFF   call    AXE.0042F620                     ;  算法::F7进入,注册正确的话,eax<>0
0043F5CD   .  3BC3          cmp     eax, ebx                         ;  eax = $00(ebx) ?
0043F5CF      0F84 26030000 je      AXE.0043F8FB                     ;  //不跳
0043F5D5   .  A0 644B5100   mov     al, byte ptr [514B64]
0043F5DA   .  8A0D 684B5100 mov     cl, byte ptr [514B68]
0043F5E0   .  8A15 6C4B5100 mov     dl, byte ptr [514B6C]
0043F5E6   .  34 AA         xor     al, 0AA
0043F5E8   .  80F1 55       xor     cl, 55
0043F5EB   .  884424 24     mov     byte ptr [esp+24], al
0043F5EF   .  A0 704B5100   mov     al, byte ptr [514B70]
0043F5F4   .  884C24 25     mov     byte ptr [esp+25], cl
0043F5F8   .  8A0D 744B5100 mov     cl, byte ptr [514B74]
0043F5FE   .  80F2 66       xor     dl, 66
0043F601   .  34 CC         xor     al, 0CC
0043F603   .  80F1 77       xor     cl, 77
0043F606   .  885424 26     mov     byte ptr [esp+26], dl
>>>>>>



毫无疑问,注册成功与否,便是看 0043F5CD 这里的eax是否为0了,不为0才注册成功,要分析算法,自然要进入0043F5C8地址的

0043F5C8   .  E8 5300FFFF   call    AXE.0042F620

这里了,走到这里时,按F7建进入后:

>>>>>>
0042F620  /$  64:A1 0000000>mov     eax, dword ptr fs:[0]            ;  来到这里
0042F626  |.  6A FF         push    -1
0042F628  |.  68 48AE4D00   push    AXE.004DAE48
0042F62D  |.  50            push    eax
0042F62E  |.  64:8925 00000>mov     dword ptr fs:[0], esp
0042F635  |.  53            push    ebx
0042F636  |.  56            push    esi                              ;  esi := $0012FB28;
0042F637  |.  57            push    edi
0042F638  |.  8B4424 24     mov     eax, dword ptr [esp+24]          ;  注册名 -> eax
0042F63C  |.  C74424 14 000>mov     dword ptr [esp+14], 0
0042F644  |.  8B48 F8       mov     ecx, dword ptr [eax-8]           ;  注册名长度 -> ecx
0042F647  |.  85C9          test    ecx, ecx                         ;  ecx and ecx = 0 ?
0042F649  |.  0F84 BF000000 je      AXE.0042F70E                     ;  注册名长度为0的话,跳
0042F64F  |.  8B7424 20     mov     esi, dword ptr [esp+20]          ;  这里注意: esi := 注册码的16进制;
0042F653  |.  85F6          test    esi, esi                         ;  ecx 0 ?
0042F655  |.  0F84 B3000000 je      AXE.0042F70E                     ;  <>0
0042F65B  |.  81FE 25270000 cmp     esi, 2725                        ;  esi <> $2725 ?
0042F661  |.  75 2A         jnz     short AXE.0042F68D               ;  不等,肯定跳!
0042F663  |.  8D4C24 24     lea     ecx, dword ptr [esp+24]
0042F667  |.  C74424 14 FFF>mov     dword ptr [esp+14], -1
0042F66F  |.  E8 ED410800   call    AXE.004B3861
0042F674  |.  B8 01000000   mov     eax, 1                           ;  这里说明,等于$2725,注册成功
0042F679  |.  8B4C24 0C     mov     ecx, dword ptr [esp+C]
0042F67D  |.  64:890D 00000>mov     dword ptr fs:[0], ecx
0042F684  |.  5F            pop     edi
0042F685  |.  5E            pop     esi
0042F686  |.  5B            pop     ebx
0042F687  |.  83C4 0C       add     esp, 0C
0042F68A  |.  C2 0C00       retn    0C
0042F68D  |>  83F9 04       cmp     ecx, 4                           ;  注册名长度大于4 ?
0042F690  |.  7D 12         jge     short AXE.0042F6A4               ;  大于等于4,跳
0042F692  |.  68 2C415100   push    AXE.0051412C                     ;  abcd
0042F697  |.  8D4C24 28     lea     ecx, dword ptr [esp+28]
0042F69B  |.  E8 9D450800   call    AXE.004B3C3D
0042F6A0  |.  8B4424 24     mov     eax, dword ptr [esp+24]          ;  注册名长度小于4,则注册名+'abcd' -> eax
0042F6A4  |>  8B48 F8       mov     ecx, dword ptr [eax-8]           ;  注册名长度 -> ecx
0042F6A7  |.  8A58 02       mov     bl, byte ptr [eax+2]             ;  取注册名的第3位字符码 -> bl(ebx低位)
0042F6AA  |.  8A10          mov     dl, byte ptr [eax]               ;  取注册名的第1位字符码 -> dl(edx低位)
0042F6AC  |.  0FBE4401 FF   movsx   eax, byte ptr [ecx+eax-1]        ;  取注册名的最后位字符码 -> eax
0042F6B1  |.  0FBEFB        movsx   edi, bl                          ;  edi = bl;
0042F6B4  |.  0FBED2        movsx   edx, dl                          ;  edx = dl;
0042F6B7  |.  03C7          add     eax, edi                         ;  eax := eax + edi;
0042F6B9  |.  03C2          add     eax, edx                         ;  eax := eax + edx;
0042F6BB  |.  0FAFC1        imul    eax, ecx                         ;  eax := eax * ecx;
0042F6BE  |.  25 FFFFFF8F   and     eax, 8FFFFFFF                    ;  eax := eax and $8FFFFFFF;
0042F6C3  |.  79 07         jns     short AXE.0042F6CC               ;  为0? 跳!
0042F6C5  |.  48            dec     eax
0042F6C6  |.  0D 000000F0   or      eax, F0000000
0042F6CB  |.  40            inc     eax
0042F6CC  |>  81FE 00000010 cmp     esi, 10000000                    ;  esi 比较 $10000000
0042F6D2  |.  76 05         jbe     short AXE.0042F6D9               ;  小于或等于,跳
0042F6D4  |.  05 00000010   add     eax, 10000000                    ;  大于: eax:= eax + $10000000;
0042F6D9  |>  35 D7139A03   xor     eax, 39A13D7                     ;  eax := eax xor $39A13D7
0042F6DE  |.  33C9          xor     ecx, ecx                         ;  ecx 清零 ecx := 0;
0042F6E0  |.  3BF0          cmp     esi, eax                         ;  esi 比较 eax,『『这里相等便OK』』
0042F6E2  |.  C74424 14 FFF>mov     dword ptr [esp+14], -1
0042F6EA  |.  0F94C1        sete    cl                               ;  cl 设置1
0042F6ED  |.  8BF1          mov     esi, ecx                         ;  注意: esi := ecx;
0042F6EF  |.  8D4C24 24     lea     ecx, dword ptr [esp+24]
0042F6F3  |.  E8 69410800   call    AXE.004B3861
0042F6F8  |.  8BC6          mov     eax, esi                         ;  eax := esi; //最终结果
0042F6FA  |.  8B4C24 0C     mov     ecx, dword ptr [esp+C]
0042F6FE  |.  64:890D 00000>mov     dword ptr fs:[0], ecx
0042F705  |.  5F            pop     edi
0042F706  |.  5E            pop     esi
0042F707  |.  5B            pop     ebx
0042F708  |.  83C4 0C       add     esp, 0C
0042F70B  |.  C2 0C00       retn    0C
0042F70E  |>  8D4C24 24     lea     ecx, dword ptr [esp+24]
0042F712  |.  C74424 14 FFF>mov     dword ptr [esp+14], -1
0042F71A  |.  E8 42410800   call    AXE.004B3861
0042F71F  |.  8B4C24 0C     mov     ecx, dword ptr [esp+C]
0042F723  |.  5F            pop     edi
0042F724  |.  5E            pop     esi
0042F725  |.  33C0          xor     eax, eax
0042F727  |.  64:890D 00000>mov     dword ptr fs:[0], ecx
0042F72E  |.  5B            pop     ebx
0042F72F  |.  83C4 0C       add     esp, 0C
0042F732  \.  C2 0C00       retn    0C
>>>>>>


通过上面的分析,我们知道了其注册算法为:读入注册名和注册码,先将注册码转换为16进制数,放入esi中;然后读入注册名,取注册名的第3位字符,放入edi中,第1位字符放入edx中,注册名的最后位字符放入eax中,然后将这三个字符码相加,结果再与$8FFFFFFF做and运算,得到的结果再异或
$39A13D7后得到最终结果,放入eax中。用这个结果比较esi中的注册码,相等,就注册成功了!


放上一组可用的Key:

注册名: aCaFeeL
注册码: 60429493


注册机的算法在多台机器上使用不同注册名通过验证,但没有时间再优化它了,应该不存在bug的问题,附件中为我打包后的注册机源代码。