crackme破解

加密与解密买了有半个多月了,一直在学习。昨天把书的第五章看完了,理论知道后,技术只能通过大量的练习来提高。以我现在的水平,难度大的也不会,所以就挑些简单的来练习。

这个例子是《加密与解密 第四版》第五章中附带的2007年的CrackMe中给的。破解的作者是 爱在天涯 大佬,不过看到最后,大佬可能是困了,不分析了。这个例子对我来说,不算简单,但稍微思考一下,应该可以做出来。

新手破解,会存在很多纰漏,望大佬们加以指正,感谢。

image

根据错误提示,来到关键代码处:

00401139   $  6A 32         push    32                               ; /Count = 32 (50.)
0040113B   .  68 F3204000   push    004020F3                         ; |Buffer = Crackme1.004020F3
00401140   .  68 C8000000   push    0C8                              ; |ControlID = C8 (200.)
00401145   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
00401148   .  E8 DE000000   call        ; \GetDlgItemTextA
0040114D   .  83F8 00       cmp     eax, 0                           ;  空字符串
00401150   .  0F84 99000000 je      004011EF                         ;  失败
00401156   .  83F8 04       cmp     eax, 4
00401159   .  0F82 90000000 jb      004011EF                         ;  长度<4,失败
0040115F   .  33C9          xor     ecx, ecx                         ;  i = 0
00401161   .  33DB          xor     ebx, ebx
00401163   .  33F6          xor     esi, esi                         ;  sum = 0
00401165   .  8945 FC       mov     dword ptr [ebp-4], eax           ;  len = strlen(name)
00401168   >  0FBE81 F32040>movsx   eax, byte ptr [ecx+4020F3]
0040116F   .  83F8 20       cmp     eax, 20
00401172   .  74 07         je      short 0040117B                   ;  如果是空格,忽略,进行下一个循环
00401174   .  6BC0 04       imul    eax, eax, 4                      ;  用户名的单个字符的16进制*4
00401177   .  03D8          add     ebx, eax
00401179   .  8BF3          mov     esi, ebx                         ;  sum = sum+eax*4
0040117B   >  41            inc     ecx
0040117C   .  3B4D FC       cmp     ecx, dword ptr [ebp-4]
0040117F   .^ 75 E7         jnz     short 00401168                   ;  未处理完毕,继续循环
00401181   .  83FE 00       cmp     esi, 0
00401184   .  74 69         je      short 004011EF
00401186   .  BB 89476500   mov     ebx, 654789                      ;  tmp = 0x654789
0040118B   >  0FBE81 F22040>movsx   eax, byte ptr [ecx+4020F2]       ;  注册码的倒序
00401192   .  4B            dec     ebx                              ;  tmp--
00401193   .  6BC3 02       imul    eax, ebx, 2
00401196   .  03D8          add     ebx, eax                         ;  tmp = tmp * 0x2
00401198   .  4B            dec     ebx                              ;  tmp--
00401199   .  49            dec     ecx                              ;  len - 1
0040119A   .^ 75 EF         jnz     short 0040118B
0040119C   .  56            push    esi                              ; /<%lu>
0040119D   .  53            push    ebx                              ; |<%lX>
0040119E   .  68 C7204000   push    004020C7                         ; |Format = "BS-%lX-%lu"
004011A3   .  68 BB214000   push    004021BB                         ; |s = Crackme1.004021BB
004011A8   .  E8 6C000000   call              ; \wsprintfA
004011AD   .  58            pop     eax
004011AE   .  58            pop     eax
004011AF   .  58            pop     eax
004011B0   .  58            pop     eax
004011B1   .  E8 01000000   call    004011B7
004011B6   .  C3            retn
004011B7   $  33C9          xor     ecx, ecx
004011B9   .  6A 32         push    32                               ; /Count = 32 (50.)
004011BB   .  68 57214000   push    00402157                         ; |Buffer = Crackme1.00402157
004011C0   .  68 C9000000   push    0C9                              ; |ControlID = C9 (201.)
004011C5   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
004011C8   .  E8 5E000000   call        ; \GetDlgItemTextA
004011CD   .  83F8 00       cmp     eax, 0
004011D0   .  74 1D         je      short 004011EF                   ;  注册码为0,失败
004011D2   .  33C9          xor     ecx, ecx                         ;  j = 0
004011D4   >  0FBE81 572140>movsx   eax, byte ptr [ecx+402157]       ;  获取注册码首位
004011DB   .  0FBE99 BB2140>movsx   ebx, byte ptr [ecx+4021BB]       ;  取正确的注册码首位
004011E2   .  3BC3          cmp     eax, ebx
004011E4   .  75 09         jnz     short 004011EF                   ;  不相等,失败
004011E6   .  83F8 00       cmp     eax, 0
004011E9   .  74 19         je      short 00401204                   ;  输入的注册码为NULL,失败
004011EB   .  41            inc     ecx                              ;  j++
004011EC   .^ EB E6         jmp     short 004011D4                   ;  继续比较下一位
004011EE   .  C3            retn
004011EF   >  6A 10         push    10                               ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
004011F1   .  68 E4204000   push    004020E4                         ; |Title = "Nope"
004011F6   .  68 E9204000   push    004020E9                         ; |Text = "Try again"
004011FB   .  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
004011FE   .  E8 34000000   call            ; \MessageBoxA
00401203   .  C3            retn
00401204   >  6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401206   .  68 D2204000   push    004020D2                         ; |Title = "Solved"
0040120B   .  68 D9204000   push    004020D9                         ; |Text = "Well done."
00401210   .  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
00401213   .  E8 1F000000   call            ; \MessageBoxA
00401218   .  C3            retn

可以看到,程序调用了两次GetDlgItemTextA(),不出意外,分别是获取用户名和注册码。
具体的分析可以看注释。

贴一个简单的注册机:

/*

reference:http://bbs.pediy.com/showthread.php?threadid=10533 
author:lingyin
date:2018-12-30

*/

#include
#include

int main()
{
    char name[20];
    int i,sum = 0;
    int len = 0;
    char ch;
    int tmp = 0x654789;

    printf("请输入要破解的账号:\n");
    scanf("%s",name);
    len = strlen(name);

    if(len < 4)
    {
        printf("请至少输入4个字符!!!!");
        return;
    }

    //printf("%d",strlen(name));
    //printf("%s\n",name);

    for(i = 0;i < len;i++)
    {
        ch = name[i];

        if(ch < 0x20)
            return;

        sum += ch * 0x4;


    }

    for(i = len-1;i >= 0;i--)
    {
        ch = name[i];
        tmp--;
        tmp += tmp*0x2;
        tmp--;

    }


    //输出最后的正确的注册码
    printf("BS-%lX-%lu\n",tmp,sum);
    
    getch();
    return 0;

}
image

输入pediy,会输出注册码:BS-6022E527-2156.
这个注册机,我测试了几个账号,没问题,如果哪位朋友,发现存在BUG,麻烦告诉我,万分感谢.

你可能感兴趣的:(crackme破解)