系统 : Windows xp

程序 : Bxm_CrackMe1

程序下载地址 :http://pan.baidu.com/s/1pK0a0xt

要求 : 分析算法

使用工具 :OD

可在看雪论坛中查找关于此程序的讨论:传送门

 

OD载入程序,利用插件查看字串表,双击“破解成功”的字串进入关键算法:

00402406  |.  50            push    eax                              ; /src
00402407  |.  8D45 D0       lea     eax, dword ptr [ebp-30]          ; |
0040240A  |.  50            push    eax                              ; |dest
0040240B  |.  E8 24EDFFFF   call    <jmp.&MSVCRTD.strcpy>            ; \strcpy
00402410  |.  83C4 08       add     esp, 8
00402413  |.  8D4D D0       lea     ecx, dword ptr [ebp-30]          ;  取出字串地址
00402416  |.  51            push    ecx                              ; /s
00402417  |.  E8 1EEDFFFF   call    <jmp.&MSVCRTD.strlen>            ; \strlen
0040241C  |.  83C4 04       add     esp, 4
0040241F  |.  8945 E8       mov     dword ptr [ebp-18], eax          ;  保存长度
00402422  |.  C745 EC 00000>mov     dword ptr [ebp-14], 0            ;  取出一段内存置零
00402429  |.  EB 09         jmp     short 00402434
0040242B  |>  8B55 EC       /mov     edx, dword ptr [ebp-14]
0040242E  |.  83C2 01       |add     edx, 1
00402431  |.  8955 EC       |mov     dword ptr [ebp-14], edx         ;  循环变量自增
00402434  |>  8B45 EC        mov     eax, dword ptr [ebp-14]
00402437  |.  3B45 E8       |cmp     eax, dword ptr [ebp-18]         ;  迭代字串完毕则跳转
0040243A  |.  7D 12         |jge     short 0040244E
0040243C  |.  8B4D EC       |mov     ecx, dword ptr [ebp-14]
0040243F  |.  0FBE540D D0   |movsx   edx, byte ptr [ebp+ecx-30]      ;  取出字符
00402444  |.  8B45 F8       |mov     eax, dword ptr [ebp-8]
00402447  |.  03C2          |add     eax, edx                        ;  累加
00402449  |.  8945 F8       |mov     dword ptr [ebp-8], eax          ;  保存结果
0040244C  |.^ EB DD         \jmp     short 0040242B
0040244E  |>  8B4D F8       mov     ecx, dword ptr [ebp-8]
00402451  |.  F7D9          neg     ecx                              ;  对结果进行求补运算
00402453  |.  8B55 F8       mov     edx, dword ptr [ebp-8]
00402456  |.  0355 E8       add     edx, dword ptr [ebp-18]          ;  结果加上用户名字串的长度
00402459  |.  0FAFCA        imul    ecx, edx                         ;  相乘
0040245C  |.  894D F4       mov     dword ptr [ebp-C], ecx           ;  保存结果
0040245F  |.  8B4D FC       mov     ecx, dword ptr [ebp-4]
00402462  |.  83C1 64       add     ecx, 64
00402465  |.  E8 2AFBFFFF   call    <jmp.&MFC42D.#880>
0040246A  |.  50            push    eax                              ; /src
0040246B  |.  8D45 B8       lea     eax, dword ptr [ebp-48]          ; |
0040246E  |.  50            push    eax                              ; |dest
0040246F  |.  E8 C0ECFFFF   call    <jmp.&MSVCRTD.strcpy>            ; \strcpy
00402474  |.  83C4 08       add     esp, 8
00402477  |.  C745 B0 01000>mov     dword ptr [ebp-50], 1
0040247E  |.  8D4D B8       lea     ecx, dword ptr [ebp-48]
00402481  |.  51            push    ecx                              ; /s
00402482  |.  E8 B3ECFFFF   call    <jmp.&MSVCRTD.strlen>            ; \strlen
00402487  |.  83C4 04       add     esp, 4
0040248A  |.  83E8 01       sub     eax, 1                           ;  长度-1
0040248D  |.  8945 B4       mov     dword ptr [ebp-4C], eax          ;  保存
00402490  |.  EB 09         jmp     short 0040249B
00402492  |>  8B55 B4       /mov     edx, dword ptr [ebp-4C]
00402495  |.  83EA 01       |sub     edx, 1                          ;  循环变量自减
00402498  |.  8955 B4       |mov     dword ptr [ebp-4C], edx
0040249B  |>  837D B4 00     cmp     dword ptr [ebp-4C], 0           ;  迭代完毕则跳转
0040249F  |.  7C 22         |jl      short 004024C3
004024A1  |.  8B45 B4       |mov     eax, dword ptr [ebp-4C]
004024A4  |.  0FBE4C05 B8   |movsx   ecx, byte ptr [ebp+eax-48]      ;  倒序取字符
004024A9  |.  83E9 30       |sub     ecx, 30                         ;  转化为十进制
004024AC  |.  0FAF4D B0     |imul    ecx, dword ptr [ebp-50]         ;  相乘
004024B0  |.  8B55 F0       |mov     edx, dword ptr [ebp-10]
004024B3  |.  03D1          |add     edx, ecx
004024B5  |.  8955 F0       |mov     dword ptr [ebp-10], edx         ;  保存累加结果
004024B8  |.  8B45 B0       |mov     eax, dword ptr [ebp-50]
004024BB  |.  6BC0 0A       |imul    eax, eax, 0A                    ;  eax * 0A
004024BE  |.  8945 B0       |mov     dword ptr [ebp-50], eax         ;  再存回去
004024C1  |.^ EB CF         \jmp     short 00402492
004024C3  |>  8B4D F0       mov     ecx, dword ptr [ebp-10]          ;  取结果
004024C6  |.  6BC9 FF       imul    ecx, ecx, -1                     ;  取相反数
004024C9  |.  894D F0       mov     dword ptr [ebp-10], ecx          ;  再存回去
004024CC  |.  837D E8 00    cmp     dword ptr [ebp-18], 0            ;  用户名长度为0?
004024D0  |.  74 2F         je      short 00402501                   ;  为0则破解失败
004024D2  |.  8B55 F0       mov     edx, dword ptr [ebp-10]
004024D5  |.  0FAF55 F0     imul    edx, dword ptr [ebp-10]          ;  相反数 * 相反数
004024D9  |.  8B45 F0       mov     eax, dword ptr [ebp-10]          ;  取出结果
004024DC  |.  0FAF45 E8     imul    eax, dword ptr [ebp-18]          ;  结果乘以用户名长度
004024E0  |.  8B4D F4       mov     ecx, dword ptr [ebp-C]           ;  取F(用户名)
004024E3  |.  03CA          add     ecx, edx                         ;  累加之前的结果
004024E5  |.  03C1          add     eax, ecx
004024E7  |.  85C0          test    eax, eax                         ;  eax为0?
004024E9  |.  75 16         jnz     short 00402501                   ;  不为0则破解失败
004024EB  |.  6A 00         push    0
004024ED  |.  68 20514100   push    00415120                         ;  恭喜你
004024F2  |.  68 14514100   push    00415114                         ;  破解成功!
004024F7  |.  8B4D FC       mov     ecx, dword ptr [ebp-4]
004024FA  |.  E8 71ECFFFF   call    <jmp.&MFC42D.#3517>
004024FF  |.  EB 14         jmp     short 00402515
00402501  |>  6A 00         push    0
00402503  |.  68 08514100   push    00415108                         ;  破解失败
00402508  |.  68 58504100   push    00415058                         ;  重试?
0040250D  |.  8B4D FC       mov     ecx, dword ptr [ebp-4]
00402510  |.  E8 5BECFFFF   call    <jmp.&MFC42D.#3517>

算法比较简单,就不一一说明了,直接修改4024E9处的跳转指令就可以完成爆破。

有兴趣的朋友可以尝试写出注册机。

 

-------------------------------------------------------------------------------------------------------------------

既然算法简单,那就尝试着把注册机写出来吧。该cm采用了二元函数加密,检测F(用户名,密钥)==0来判断是否是正确的注册码。

我们直接打开之前搭建的框架,并修改OnBtnDecrypt函数如下:

 

void CKengen_TemplateDlg::OnBtnDecrypt() 
{
    // TODO: Add your control notification handler code here
    CString str;
    GetDlgItemText( IDC_EDIT_NAME,str );                    //获取用户名字串基本信息。
    int len = str.GetLength();

    if ( len != 0 ){                                        //格式控制。
        SetDlgItemText( IDC_EDIT_PASSWORD,str );

        unsigned int sum = 0;
        int FUserName;
        for ( int i = 0 ; i != len ; i++ )
            sum += str[i];
        FUserName = (~sum + 1) * (sum + 5);                                        
/*
        //模拟F(Serial)
        CString Serial = "12345";
        int product = 1;
        int SerialLen = Serial.GetLength() - 1;

        sum = 0;
        for ( ; SerialLen != -1 ; SerialLen-- ){
            sum += (Serial[SerialLen] - 0x30 ) * product;    //把字符串转化成对应的数值
            product *= 10;
        }

        //取相反数
        sum *= -1;
        //X^2+bx+c = 0
        if ( sum * sum + sum * len + FUserName == 0 )
            MessageBox( "注册成功!" );
*/
        int delt = len*len-4*1*FUserName;
        if ( delt < 0 )                                        //方程是否无根?
        {
            SetDlgItemText( IDC_EDIT_PASSWORD,"方程无解!无法找出注册码!" );
            return ;
        }
        //解方程
        int x = ((double)-len-sqrt(delt))/(double)(2*1);
        x = -x;

        CString PassWord;
        PassWord.Format( "%d",x );
        SetDlgItemText( IDC_EDIT_PASSWORD,PassWord );
    }
    else
        MessageBox( "用户名格式错误!" );
}

 

再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("bxm-firstcm_Keygen"));

运行效果: