zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    源码分析清楚 AbstractQueuedSynchronizer
    Java 并发队列 BlockingQueue
    ReentrantLock以及AQS实现原理
    Java并发之Condition
    Java线程的6种状态及切换
    同步工具类
    Java 并发实践 — ConcurrentHashMap 与 CAS
    Java7/8 中的 HashMap 和 ConcurrentHashMap
    java HashMap、HashTable、ConcurrentHashMap区别
    Mysql的复制原理以及流程
  • 原文地址:https://www.cnblogs.com/mavaL/p/2674402.html
Copyright © 2011-2022 走看看