CrackMe练习之Bigman's Crackme6

这里练习用到的CrackmMe都来自<<加密与解密>>第3版第5章习题的"PEDIY CrackMe 2007.chm"集合.

 CrackMe下载

                        

 先将这个CrackMe用PEID侦测下,发现是加了壳的,鉴于还未学到壳的相关知识,还好这里附带提供了解壳后的文件.OD跟踪,Ctrl+N看到熟悉的GetDlgItemTextA,直接对其下断,然后F9运行随意输入用户名和密码后,点击Check,断在下面:

00401528  |.  68 00010000   push    100                              ; /Count = 100 (256.)
0040152D  |.  8D85 00FFFFFF lea     eax, [local.64]                  ; |
00401533  |.  50            push    eax                              ; |Buffer
00401534  |.  6A 65         push    65                               ; |ControlID = 65 (101.)
00401536  |.  FF75 08       push    [arg.1]                          ; |hWnd
00401539  |.  E8 FA010000   call    <jmp.&USER32.GetDlgItemTextA>    ; \GetDlgItemTextA
0040153E  |.  89C3          mov     ebx, eax
00401540  |.  09DB          or      ebx, ebx
00401542  |.  75 04         jnz     short 00401548
00401544  |.  31C0          xor     eax, eax
00401546  |.  EB 50         jmp     short 00401598
00401548  |>  BF BC020000   mov     edi, 2BC
0040154D  |.  BE 30000000   mov     esi, 30
00401552  |.  B8 48000000   mov     eax, 48
00401557  |.  99            cdq
00401558  |.  F7FB          idiv    ebx
0040155A  |.  29C6          sub     esi, eax
0040155C  |.  8D34B6        lea     esi, dword ptr [esi+esi*4]       ;  (initial cpu selection)
0040155F  |.  29F7          sub     edi, esi
00401561  |.  6BFF 6B       imul    edi, edi, 6B
00401564  |.  81EF 6CCF0000 sub     edi, 0CF6C
0040156A  |.  81FF 00230000 cmp     edi, 2300
00401570  |.  7F 08         jg      short 0040157A
00401572  |.  81FF 90010000 cmp     edi, 190
00401578  |.  7D 04         jge     short 0040157E
0040157A  |>  31C0          xor     eax, eax
0040157C  |.  EB 1A         jmp     short 00401598                   ;  通过计算,用户名长度必须在[3,9]
0040157E  |>  8D85 00FFFFFF lea     eax, [local.64]
00401584  |.  50            push    eax
00401585  |.  53            push    ebx
00401586  |.  FF75 08       push    [arg.1]
00401589  |.  E8 77FDFFFF   call    00401305                         ;  关键,校验过程
0040158E  |.  83C4 0C       add     esp, 0C
00401591  |.  09C0          or      eax, eax
00401593  |.  74 03         je      short 00401598                   ;  返回0
00401595  |.  31C0          xor     eax, eax
00401597  |.  40            inc     eax                              ;  返回1
00401598  |>  5F            pop     edi
00401599  |.  5E            pop     esi
0040159A  |.  5B            pop     ebx
0040159B  |.  C9            leave
0040159C  \.  C3            retn

可以看到00401305是校验过程,会返回0或1.先不管,先找到调用此处的地址00401625,如下:

 1 00401625  |.  E8 DFFEFFFF   call    00401509                         ;  WM_COMMAND控件响应
 2 0040162A  |.  59            pop     ecx
 3 0040162B  |.  09C0          or      eax, eax
 4 0040162D  |.  74 53         je      short 00401682                   ;  处理结果:0完蛋,1成功
 5 0040162F  |.  6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
 6 00401631  |.  8D45 C7       lea     eax, dword ptr [ebp-39]          ; |
 7 00401634  |.  50            push    eax                              ; |Title
 8 00401635  |.  8D45 D3       lea     eax, dword ptr [ebp-2D]          ; |
 9 00401638  |.  50            push    eax                              ; |Text
10 00401639  |.  FF75 08       push    [arg.1]                          ; |hOwner
11 0040163C  |.  E8 1B010000   call    <jmp.&USER32.MessageBoxA>        ; \成功

 可以看到返回0表示失败,1是成功,接下来安心分析校验过程了:

  1 0040139E  |.  68 00010000   push    100                              ; /Count = 100 (256.)
  2 004013A3  |.  8D85 E1FCFFFF lea     eax, dword ptr [ebp-31F]         ; |取得输入密码放入缓冲区
  3 004013A9  |.  50            push    eax                              ; |Buffer
  4 004013AA  |.  6A 66         push    66                               ; |ControlID = 66 (102.)
  5 004013AC  |.  FF75 08       push    [arg.1]                          ; |hWnd
  6 004013AF  |.  E8 84030000   call    <jmp.&USER32.GetDlgItemTextA>    ; \GetDlgItemTextA
  7 004013B4  |.  09C0          or      eax, eax
  8 004013B6  |.  0F84 48010000 je      00401504
  9 004013BC  |.  B8 CF110000   mov     eax, 11CF
 10 004013C1  |.  0FB68D E1FCFF>movzx   ecx, byte ptr [ebp-31F]          ;  密码第1位放入ECX
 11 004013C8  |.  99            cdq
 12 004013C9  |.  F7F9          idiv    ecx
 13 004013CB  |.  83FA 17       cmp     edx, 17
 14 004013CE  |.  74 07         je      short 004013D7                   ;  前面的除法求得密码第一位是6
 15 004013D0  |.  31C0          xor     eax, eax
 16 004013D2  |.  E9 2D010000   jmp     00401504                         ;  完蛋,返回0
 17 004013D7  |>  31DB          xor     ebx, ebx
 18 004013D9  |.  EB 0B         jmp     short 004013E6
 19 004013DB  |>  8B45 10       /mov     eax, [arg.3]
 20 004013DE  |.  0FBE0418      |movsx   eax, byte ptr [eax+ebx]
 21 004013E2  |.  0145 FC       |add     [local.1], eax
 22 004013E5  |.  43            |inc     ebx
 23 004013E6  |>  3B5D 0C        cmp     ebx, [arg.2]
 24 004013E9  |.^ 7C F0         \jl      short 004013DB                  ;  用户名各字符累加
 25 004013EB  |.  31DB          xor     ebx, ebx
 26 004013ED  |.  E9 83000000   jmp     00401475
 27 004013F2  |>  8B55 10       /mov     edx, [arg.3]
 28 004013F5  |.  0FBE3C1A      |movsx   edi, byte ptr [edx+ebx]         ;  EDI为用户名当前字符
 29 004013F9  |.  8B75 FC       |mov     esi, [local.1]
 30 004013FC  |.  89D9          |mov     ecx, ebx
 31 004013FE  |.  C1E1 02       |shl     ecx, 2
 32 00401401  |.  89DA          |mov     edx, ebx
 33 00401403  |.  42            |inc     edx
 34 00401404  |.  29D1          |sub     ecx, edx                        ;  ECX=循环变量i*4-(i+1)
 35 00401406  |.  0FB68C0D E1FE>|movzx   ecx, byte ptr [ebp+ecx-11F]     ;  ebp-11F是字母表的开始,ECX查表,第一次必为0
 36 0040140E  |.  89FA          |mov     edx, edi
 37 00401410  |.  31CA          |xor     edx, ecx                        ;  EDX=用户名当前字符与ECX异或
 38 00401412  |.  89F1          |mov     ecx, esi                        ;  ESI是用户名字符累加
 39 00401414  |.  0FAFCB        |imul    ecx, ebx
 40 00401417  |.  29F1          |sub     ecx, esi
 41 00401419  |.  89CE          |mov     esi, ecx                        ;  ESI=ESI*i-ESI
 42 0040141B  |.  83F6 FF       |xor     esi, FFFFFFFF                   ;  ESI再与-1异或
 43 0040141E  |.  8DB432 4D0100>|lea     esi, dword ptr [edx+esi+14D]    ;  ESI=EDX+ESI+14D
 44 00401425  |.  8B4D 0C       |mov     ecx, [arg.2]                    ;  ECX=用户名长度
 45 00401428  |.  89DA          |mov     edx, ebx
 46 0040142A  |.  83C2 03       |add     edx, 3
 47 0040142D  |.  0FAFCA        |imul    ecx, edx
 48 00401430  |.  0FAFCF        |imul    ecx, edi                        ;  ECX=ECX*(i+3)*EDI
 49 00401433  |.  89F0          |mov     eax, esi
 50 00401435  |.  01C8          |add     eax, ecx                        ;  EAX=ESI+ECX
 51 00401437  |.  B9 0A000000   |mov     ecx, 0A
 52 0040143C  |.  31D2          |xor     edx, edx
 53 0040143E  |.  F7F1          |div     ecx                             ;  EAX=EAX/A
 54 00401440  |.  83C2 30       |add     edx, 30                         ;  EDX=EAX%A+30
 55 00401443  |.  88941D FCFEFF>|mov     byte ptr [ebp+ebx-104], dl
 56 0040144A  |.  0FB6BC1D FCFE>|movzx   edi, byte ptr [ebp+ebx-104]
 57 00401452  |.  81F7 ACAD0000 |xor     edi, 0ADAC                      ;  EDI=DL^0ADAC
 58 00401458  |.  89DE          |mov     esi, ebx
 59 0040145A  |.  83C6 02       |add     esi, 2
 60 0040145D  |.  89F8          |mov     eax, edi
 61 0040145F  |.  0FAFC6        |imul    eax, esi                        ;  EAX=EDI*(i+2)
 62 00401462  |.  B9 0A000000   |mov     ecx, 0A
 63 00401467  |.  99            |cdq
 64 00401468  |.  F7F9          |idiv    ecx                             ;  EAX=EAX/A
 65 0040146A  |.  83C2 30       |add     edx, 30                         ;  EDX=EAX%A+30
 66 0040146D  |.  88941D FCFEFF>|mov     byte ptr [ebp+ebx-104], dl
 67 00401474  |.  43            |inc     ebx
 68 00401475  |>  3B5D 0C        cmp     ebx, [arg.2]                    ;  循环次数为用户名长度
 69 00401478    ^ 0F8C 74FFFFFF jl      004013F2
 70 0040147E  |.  8D85 FCFEFFFF lea     eax, [local.65]                  ;  上面的计算将用户名转化为一个字符串
 71 00401484  |.  50            push    eax
 72 00401485  |.  6A 54         push    54                               ;  'T'
 73 00401487  |.  8D85 DCFBFFFF lea     eax, [local.265]
 74 0040148D  |.  50            push    eax                              ; |Format
 75 0040148E  |.  8D85 E1FBFFFF lea     eax, dword ptr [ebp-41F]         ; |
 76 00401494  |.  50            push    eax                              ; |s
 77 00401495  |.  E8 CE020000   call    <jmp.&USER32.wsprintfA>          ; \wsprintfA
 78 0040149A  |.  8B7D 0C       mov     edi, [arg.2]
 79 0040149D  |.  89F8          mov     eax, edi
 80 0040149F  |.  0FAF45 FC     imul    eax, [local.1]                   ;  EAX=用户名长度*用户名累加
 81 004014A3  |.  B9 64000000   mov     ecx, 64
 82 004014A8  |.  99            cdq
 83 004014A9  |.  F7F9          idiv    ecx
 84 004014AB  |.  89D7          mov     edi, edx
 85 004014AD  |.  83C7 30       add     edi, 30                          ;  EDI=EAX%64+30
 86 004014B0  |.  57            push    edi
 87 004014B1  |.  8DBD E1FBFFFF lea     edi, dword ptr [ebp-41F]
 88 004014B7  |.  57            push    edi
 89 004014B8  |.  8DBD D6FBFFFF lea     edi, dword ptr [ebp-42A]
 90 004014BE  |.  57            push    edi                              ; |Format
 91 004014BF  |.  8DBD E1FDFFFF lea     edi, dword ptr [ebp-21F]         ; |
 92 004014C5  |.  57            push    edi                              ; |s
 93 004014C6  |.  E8 9D020000   call    <jmp.&USER32.wsprintfA>          ; \wsprintfA
 94 004014CB  |.  83C4 20       add     esp, 20
 95 004014CE  |.  8D8D E1FDFFFF lea     ecx, dword ptr [ebp-21F]
 96 004014D4  |.  83C8 FF       or      eax, FFFFFFFF
 97 004014D7  |>  40            /inc     eax
 98 004014D8  |.  803C01 00     |cmp     byte ptr [ecx+eax], 0
 99 004014DC  |.^ 75 F9         \jnz     short 004014D7
100 004014DE  |.  50            push    eax
101 004014DF  |.  8D85 E1FCFFFF lea     eax, dword ptr [ebp-31F]
102 004014E5  |.  50            push    eax
103 004014E6  |.  8D85 E1FDFFFF lea     eax, dword ptr [ebp-21F]
104 004014EC  |.  50            push    eax
105 004014ED  |.  E8 D0FDFFFF   call    004012C2                         ;  最终校验函数
 1 004012C2  /$  55            push    ebp
 2 004012C3  |.  89E5          mov     ebp, esp
 3 004012C5  |.  53            push    ebx
 4 004012C6  |.  56            push    esi
 5 004012C7  |.  57            push    edi
 6 004012C8  |.  8B5D 10       mov     ebx, [arg.3]                     ;  EBX=格式化字串长度
 7 004012CB  |.  31F6          xor     esi, esi
 8 004012CD  |.  46            inc     esi                              ;  ESI初始化为1
 9 004012CE  |.  EB 29         jmp     short 004012F9
10 004012D0  |>  8B55 08       /mov     edx, [arg.1]
11 004012D3  |.  0FBE3C32      |movsx   edi, byte ptr [edx+esi]
12 004012D7  |.  89F8          |mov     eax, edi
13 004012D9  |.  83F0 20       |xor     eax, 20
14 004012DC  |.  B9 0A000000   |mov     ecx, 0A
15 004012E1  |.  99            |cdq
16 004012E2  |.  F7F9          |idiv    ecx
17 004012E4  |.  89D7          |mov     edi, edx
18 004012E6  |.  83C7 30       |add     edi, 30                         ;  EDI=(字串当前数字^20)%A+30
19 004012E9  |.  8B55 0C       |mov     edx, [arg.2]
20 004012EC  |.  0FBE1432      |movsx   edx, byte ptr [edx+esi]         ;  EDX=密码当前数字(第2位开始,第1位恒为6)
21 004012F0  |.  39D7          |cmp     edi, edx
22 004012F2  |.  74 04         |je      short 004012F8                  ;  EDI,EDX,不等则完蛋
23 004012F4  |.  31C0          |xor     eax, eax
24 004012F6  |.  EB 08         |jmp     short 00401300
25 004012F8  |>  46            |inc     esi
26 004012F9  |>  39DE           cmp     esi, ebx
27 004012FB  |.^ 7C D3         \jl      short 004012D0                  ;  下一次比较
28 004012FD  |.  31C0          xor     eax, eax
29 004012FF  |.  40            inc     eax
30 00401300  |>  5F            pop     edi
31 00401301  |.  5E            pop     esi
32 00401302  |.  5B            pop     ebx
33 00401303  |.  5D            pop     ebp
34 00401304  \.  C3            retn

主要就是边调试边翻译出加密算法,记录好,这个CrackMe没什么技术难题可言.对于我这样的新手来说,其实这种新手题练的就是耐心和细心,流程跟完了,记录记完了,大致总结一下它的加密方法,然后就可以把笔记汇总写出KeyGen了,如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 
 5 const char g_Table[27] = {0,'A','B','C','D','E','F','G','H','I','J',
 6                                 'K','L','M','N','O','P','Q','R','S','T','U',
 7                                 'V','W','X','Y','Z'};
 8 const char* g_letterTable = g_Table + 1;
 9 
10 void Keygen(const char* user, char* outCode)
11 {
12     const size_t len = strlen(user);
13     int sum = 0;
14     char transform1[10] = {0};
15     //用户名字符累加
16     for(size_t i=0; i<len; ++i)
17         sum += user[i];
18 
19     for (size_t i=0; i<len; ++i)
20     {
21         int curUserChar = user[i];
22         //查字母表
23         int ch = *(g_letterTable + i * 4 - (i + 1));
24 
25         int sum1 = sum * i - sum;
26         sum1 = sum1 ^ 0xffffffff;
27         sum1 = (curUserChar ^ ch) + sum1 + 0x14D;
28 
29         int a = sum1 + len * (i + 3) * curUserChar;
30         int b = (a % 0xA) + 0x30;
31 
32         int c = (b ^ 0xADAC) * (i + 2);
33         int d = (c % 0xA) + 0x30;
34 
35         transform1[i] = d;
36     }
37 
38     int e = (len * sum) % 0x64 + 0x30;
39     char transform2[20] = {0};
40     sprintf(transform2, "T%s-%d", transform1, e);
41 
42     //根据用户名的变换字符串计算序列号
43     size_t len1 = strlen(transform2);
44 
45     //序列号第1位恒为6
46     outCode[0] = '6';
47     for (int i=1; i<len1; ++i)
48     {
49         outCode[i] = (transform2[i] ^ 0x20) % 0xA + 0x30;
50     }
51     outCode[len1] = 0;
52 }
53 
54 int main()
55 {
56     char szUser[50];
57     char szCode[50];
58     printf("请输入用户名:");
59     scanf("%s", szUser);
60 
61     size_t len = strlen(szUser);
62     if(len<3 || len>9)
63     {
64         printf("错误!用户名长度范围必须在3-9!\n");
65         system("pause");
66         return 0;
67     }
68 
69     Keygen(szUser, szCode);
70     printf("序列号是: %s\n", szCode);
71     system("pause");
72 
73     return 0;
74 }
原文地址:https://www.cnblogs.com/mavaL/p/2674402.html