一个CrackMe核心代码的不完整分析

第一次对反汇编代码做深入阅读,学到了很多东西,但还没成系统。

00401BD0  /$  55            push    ebp
00401BD1  |.  8BEC          mov     ebp, esp
00401BD3  |.  81EC 14040000 sub     esp, 414
00401BD9  |.  56            push    esi
00401BDA  |.  57            push    edi
00401BDB  |.  BF B0534000   mov     edi, 004053B0                    ;  ttttttt
00401BE0  |.  83C9 FF       or      ecx, FFFFFFFF                    ;  ecx赋值为FFFFFFFF,下面讲解为什么。
00401BE3  |.  33C0          xor     eax, eax                         ;  eax清0,此时al也为0,下面会用到。
00401BE5  |.  F2:AE         repne   scas byte ptr es:[edi]           ;  在es:[edi]中循环查找,直到es:[di]与al(al=0)相等或者ecx为0为止,每查找一次,ecx就会减1。
00401BE7  |.  F7D1          not     ecx                              ;  逻辑非命令,如果ecx为FFFFFFF6,执行not ecx后,ecx就变成了9。此时ecx代表了字符串长度+1。
00401BE9  |.  49            dec     ecx                              ;  获取字符串的实际长度。
00401BEA  |.  83F9 04       cmp     ecx, 4                           ;  用户名长度与4比较
00401BED  |.  0F82 BE010000 jb      00401DB1                         ;  小于4就会自动跳出,无弹窗
00401BF3  |.  BF A0534000   mov     edi, 004053A0                    ;  tttttttt
00401BF8  |.  83C9 FF       or      ecx, FFFFFFFF                    ;  同上面的差不多
00401BFB  |.  F2:AE         repne   scas byte ptr es:[edi]           ;  其实这些代码就是strlen()优化后的代码。
00401BFD  |.  F7D1          not     ecx                              ;
00401BFF  |.  49            dec     ecx                              ;
00401C00  |.  83F9 08       cmp     ecx, 8                           ;  ecx是注册码长度,不得小于8
00401C03  |.  0F82 A8010000 jb      00401DB1                         ; 
00401C09  |.  8B15 74114000 mov     edx, dword ptr [401174]          ;  把401174指向的4个字节的数据给edx,执行后edx=401178
00401C0F  |.  B9 00030000   mov     ecx, 300                         ;  
00401C14  |.  BF A0474000   mov     edi, 004047A0                    ;  目测指向4047A0这块区域的定义比保存密码、用户名的要早,但初始化晚。不知道对不对。
00401C19  |.  F3:AB         rep     stos dword ptr es:[edi]          ;  STOS是将eax中的值拷贝到ES:EDI指向的地址,向上找eax有关的代码,可以知道是0。rep是指上面代码重复执行ecx次。
00401C1B  |>  8BC8          /mov     ecx, eax                        ;  上面一行,我的理解是分配缓冲区,初始化为0。
00401C1D  |.  8BFA          |mov     edi, edx                        ;   edi=401178,eax=0,ecx=0。
00401C1F  |.  83E1 0F       |and     ecx, 0F                         ;   让ecx高16位清0,干啥用?
00401C22  |.  0FBEB1 A05340>|movsx   esi, byte ptr [ecx+4053A0]      ;  密码    带符号扩展,是不是把ANSI转换成UNICODE?看后面代码,又感觉不像。可能只是为了计算地址方便吧。
00401C29  |.  0FBE89 B05340>|movsx   ecx, byte ptr [ecx+4053B0]      ;  用户名 例子:MOV BL,80H    MOVSX AX,BL  此时AX=FF80H。
00401C30  |.  03FE          |add     edi, esi                        ;  edi+=esi(输入的密码,按位提取);
00401C32  |.  40            |inc     eax                             ;  eax自增,应该是为了记录循环次数。
00401C33  |.  3D 000C0000   |cmp     eax, 0C00                       ;  循环0xc00次,好多次啊。
00401C38  |.  8A0C39        |mov     cl, byte ptr [ecx+edi]          ;  edi+ecx(输入的用户名,按位提取),
00401C3B  |.  8888 9F474000 |mov     byte ptr [eax+40479F], cl       ;  最终是把401178+密码的第N位的ASCII+用户名的第N位ASCII的字节拷贝到40479F开头的地址里。(N每次加1)
00401C41  |.^ 72 D8         \jb      short 00401C1B                  ;  40479F 所指向的就是前面 行00401C14 初始化为0的那一片区域。
00401C43  |.  B9 FF000000   mov     ecx, 0FF                         ;  ecx=0xFF
00401C48  |.  33C0          xor     eax, eax                         ;  eax置0,一般不使用mov eax,0 机器指令为5个,而前者只有2个。
00401C4A  |.  8DBD F0FBFFFF lea     edi, dword ptr [ebp-410]         ;
00401C50  |.  C785 ECFBFFFF>mov     dword ptr [ebp-414], 0           ;
00401C5A  |.  F3:AB         rep     stos dword ptr es:[edi]          ;  貌似又是分配缓冲区,
00401C5C  |.  83CA FF       or      edx, FFFFFFFF                    ;  edx=FFFFFFFF
00401C5F  |.  B9 00010000   mov     ecx, 100                         ;
00401C64  |>  8D41 FF       /lea     eax, dword ptr [ecx-1]          ;------------------------------------------------------------------------------------
00401C67  |.  51            |push    ecx                             ;这部分是双重循环的东西
00401C68  |.  B9 08000000   |mov     ecx, 8                          ;  for(DWORD i=0x100;i=0;--i)
00401C6D  |>  D1E8          |/shr     eax, 1                         ;  {
00401C6F  |.  73 05         ||jnb     short 00401C76                 ;     	 for(DWORD j=0;j<8;++j)
00401C71  |.  35 2083B8ED   ||xor     eax, EDB88320                  ;       { 
00401C76  |>  49            ||dec     ecx                            ;            i>>1;//这个操作到底是会生成逻辑右移,还是算术右移,就要看编译器的了。
00401C77  |.^ 75 F4         |\jnz     short 00401C6D                 ;            i=i^0xEDB88320 ;
00401C79  |.  59            |pop     ecx                             ;       }
00401C7A  |.  89848D E8FBFF>|mov     dword ptr [ebp+ecx*4-418], eax  ;       i保存到刚才分配的缓冲区中。
00401C81  |.  49            |dec     ecx                             ;  }
00401C82  |.^ 75 E0         \jnz     short 00401C64                  ;------------------------------------------------------------------------------------  
00401C84  |.  33C0          xor     eax, eax                         ;------------------------------------------------------------------------------------
00401C86  |>  33C9          /xor     ecx, ecx                        ; eax,ecx清0。edx一开始为FFFFFFFF
00401C88  |.  8BF2          |mov     esi, edx                        ;
00401C8A  |.  8A88 A0474000 |mov     cl, byte ptr [eax+4047A0]       ;  这里是取出密码
00401C90  |.  81E6 FF000000 |and     esi, 0FF                        ;  清esi高24位,只保留低8位。
00401C96  |.  33CE          |xor     ecx, esi                        ;  esi与ecx只有低8位有数据,做异或运算。赋值给ecx。
00401C98  |.  C1EA 08       |shr     edx, 8                          ;  edx右移8位。FFFFFFFF--->00FFFFFF
00401C9B  |.  8B8C8D ECFBFF>|mov     ecx, dword ptr [ebp+ecx*4-414]  ;  取出地址ebp+ecx*4-414 地址中的数据,做为一个新的ecx。
00401CA2  |.  33D1          |xor     edx, ecx                        ;  与edx做异或运算,赋值给edx。
00401CA4  |.  40            |inc     eax                             ;  eax自增。
00401CA5  |.  3D 000C0000   |cmp     eax, 0C00                       ;  循环0xC00次。
00401CAA  |.^ 7C DA         \jl      short 00401C86                  ;------------------------------------------------------------------------------------
00401CAC  |.  8BC2          mov     eax, edx                         ;  上面循环结束后,把edx传出,其它的值都是辅助。
00401CAE  |.  33D2          xor     edx, edx                         ;  清0
00401CB0  |.  F7D0          not     eax                              ;  取反
00401CB2  |.  25 FF000000   and     eax, 0FF                         ;  前16位清0
00401CB7  |.  B9 6D000000   mov     ecx, 6D                          ;  ecx=0x6D
00401CBC  |.  F7F1          div     ecx                              ;  除数是edx:eax,被除数是ecx,商是eax,余数是edx。
00401CBE  |.  C645 EC 00    mov     byte ptr [ebp-14], 0             ;  
00401CC2  |.  8D4D EC       lea     ecx, dword ptr [ebp-14]          ;  为什么要这样来搞?lea可以来计算复杂表达式。是不是把[ebp-14]清0,取[ebp-14]地址给ecx呢? 
00401CC5  |.  8DB2 DE104000 lea     esi, dword ptr [edx+4010DE]      ;  上次除法余数+4010DE 的地址中数据给esi
00401CCB  |.  33D2          xor     edx, edx                         ;
00401CCD  |.  8955 ED       mov     dword ptr [ebp-13], edx          ;  栈清0,edx,eax清0。
00401CD0  |.  33C0          xor     eax, eax                         ;
00401CD2  |.  8955 F1       mov     dword ptr [ebp-F], edx           ;
00401CD5  |.  8955 F5       mov     dword ptr [ebp-B], edx           ;
00401CD8  |.  8955 F9       mov     dword ptr [ebp-7], edx           ;------------------------------------------------------------------------------------
00401CDB  |>  8A1406        /mov     dl, byte ptr [esi+eax]          ;
00401CDE  |.  83C0 02       |add     eax, 2                          ;把esi+eax中的一个字节赋值给ecx所在地址,eax变化0--->2--->4--->.....
00401CE1  |.  8811          |mov     byte ptr [ecx], dl              ;ecx是自增1。
00401CE3  |.  41            |inc     ecx                             ;
00401CE4  |.  83F8 20       |cmp     eax, 20                         ;  循环10次,
00401CE7  |.^ 72 F2         \jb      short 00401CDB                  ;------------------------------------------------------------------------------------
00401CE9  |.  B9 FF000000   mov     ecx, 0FF                         ;------------------------------------------------------------------------------------
00401CEE  |.  33C0          xor     eax, eax                         ; 这部分代码与上面00401C43到00401C82代码完全一样。
00401CF0  |.  8DBD F0FBFFFF lea     edi, dword ptr [ebp-410]         ;
00401CF6  |.  C785 ECFBFFFF>mov     dword ptr [ebp-414], 0           ;
00401D00  |.  F3:AB         rep     stos dword ptr es:[edi]          ;
00401D02  |.  83CA FF       or      edx, FFFFFFFF                    ;
00401D05  |.  B9 00010000   mov     ecx, 100                         ;
00401D0A  |>  8D41 FF       /lea     eax, dword ptr [ecx-1]          ;
00401D0D  |.  51            |push    ecx                             ;
00401D0E  |.  B9 08000000   |mov     ecx, 8                          ;
00401D13  |>  D1E8          |/shr     eax, 1                         ;
00401D15  |.  73 05         ||jnb     short 00401D1C                 ;
00401D17  |.  35 2083B8ED   ||xor     eax, EDB88320                  ;
00401D1C  |>  49            ||dec     ecx                            ;
00401D1D  |.^ 75 F4         |\jnz     short 00401D13                 ;
00401D1F  |.  59            |pop     ecx                             ;
00401D20  |.  89848D E8FBFF>|mov     dword ptr [ebp+ecx*4-418], eax  ;
00401D27  |.  49            |dec     ecx                             ;
00401D28  |.^ 75 E0         \jnz     short 00401D0A                  ;-----------------------------------------------------------------------------------
00401D2A  |.  33C0          xor     eax, eax                         ;-----------------------------------------------------------------------------------
00401D2C  |>  33C9          /xor     ecx, ecx                        ;又是一个循环,与00401C84 到 00401CA5 代码相同,只是处理的数据地址不同,循环次数不同。
00401D2E  |.  8BFA          |mov     edi, edx                        ;
00401D30  |.  8A4C05 EC     |mov     cl, byte ptr [ebp+eax-14]       ;
00401D34  |.  81E7 FF000000 |and     edi, 0FF                        ;
00401D3A  |.  33CF          |xor     ecx, edi                        ;
00401D3C  |.  C1EA 08       |shr     edx, 8                          ;
00401D3F  |.  8B8C8D ECFBFF>|mov     ecx, dword ptr [ebp+ecx*4-414]  ;
00401D46  |.  33D1          |xor     edx, ecx                        ;
00401D48  |.  40            |inc     eax                             ;
00401D49  |.  83F8 10       |cmp     eax, 10                         ;
00401D4C  |.^ 7C DE         \jl      short 00401D2C                  ;----------------------------------------------------------------------------------
00401D4E  |.  8B46 20       mov     eax, dword ptr [esi+20]          ;
00401D51  |.  F7D2          not     edx                              ;
00401D53  |.  3BD0          cmp     edx, eax                         ;
00401D55      75 44         jnz     short 00401D9B                   ;这地方是关键跳,爆破的话,虽然不会出现错误提示,但是会出现乱码。
00401D57  |.  8B55 08       mov     edx, dword ptr [ebp+8]           ;---------------------------------------------------------------------
00401D5A  |.  6A 00         push    0                                ; /lParam = NULL            下面都是为CreateWindowExA传入的参数。
00401D5C  |.  6A 00         push    0                                ; |hInst = NULL
00401D5E  |.  6A 00         push    0                                ; |hMenu = NULL
00401D60  |.  52            push    edx                              ; |hParent
00401D61  |.  6A 5A         push    5A                               ; |Height = 5A (90.)
00401D63  |.  68 B4000000   push    0B4                              ; |Width = B4 (180.)
00401D68  |.  6A 00         push    0                                ; |Y = 0
00401D6A  |.  6A 00         push    0                                ; |X = 0
00401D6C  |.  68 0100CF10   push    10CF0001                         ; |Style = WS_OVERLAPPED|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_VISIBLE|WS_SYSMENU|WS_THICKFRAME|WS_CAPTION|1
00401D71  |.  68 F8134000   push    004013F8                         ; |提示
00401D76  |.  68 F0134000   push    004013F0                         ; |static
00401D7B  |.  68 00000200   push    20000                            ; |ExtStyle = WS_EX_STATICEDGE
00401D80  |.  FF15 AC104000 call    dword ptr [<&USER32.CreateWindow>; \CreateWindowExA
00401D86  |.  85C0          test    eax, eax                         ;
00401D88  |.  74 27         je      short 00401DB1                   ;
00401D8A  |.  8D4D EC       lea     ecx, dword ptr [ebp-14]          ;
00401D8D  |.  51            push    ecx                              ; /Text          为SetWindowTextA传入参数。
00401D8E  |.  50            push    eax                              ; |hWnd
00401D8F  |.  FF15 B0104000 call    dword ptr [<&USER32.SetWindowTex>; \SetWindowTextA
00401D95  |.  5F            pop     edi                              ;
00401D96  |.  5E            pop     esi                              ;
00401D97  |.  8BE5          mov     esp, ebp                         ;
00401D99  |.  5D            pop     ebp                              ;
00401D9A  |.  C3            retn                                     ;--------------------------------------------返回。。
00401D9B  |>  8B55 08       mov     edx, dword ptr [ebp+8]           ;
00401D9E  |.  6A 10         push    10                               ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
00401DA0  |.  68 E8134000   push    004013E8                         ; |错误
00401DA5  |.  68 DC134000   push    004013DC                         ; |注册失败
00401DAA  |.  52            push    edx                              ; |hOwner
00401DAB  |.  FF15 B4104000 call    dword ptr [<&USER32.MessageBoxA>>; \MessageBoxA
00401DB1  |>  5F            pop     edi                              ;
00401DB2  |.  5E            pop     esi                              ;
00401DB3  |.  8BE5          mov     esp, ebp                         ;
00401DB5  |.  5D            pop     ebp                              ;
00401DB6  \.  C3            retn                                     ;


你可能感兴趣的:(一个CrackMe核心代码的不完整分析)