破解 Rith's CrackMe #1(对比IDA查看动态分析中的MFC函数名)

系统 : Windows xp

程序 : Rith's CrackMe #1

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

要求 : 注册机编写 

使用工具 : IDA Pro & OD

可在“PEDIY CrackMe 2007”中查找关于此程序的破文,标题为“WAKU的第二个破文----Rith's CrackMe #1(非常简单)”。

使用IDA载入程序,在字串表中找出正确注册的提示“Well done cracker!”,并双击交叉参考来到关键代码处:

00401582   .  68 B81B4000   push    00401BB8                         ;  SE handler installation
00401587   .  64:A1 0000000>mov     eax, dword ptr fs:[0]
0040158D   .  50            push    eax
0040158E   .  64:8925 00000>mov     dword ptr fs:[0], esp
00401595   .  83EC 0C       sub     esp, 0C
00401598   .  53            push    ebx
00401599   .  55            push    ebp
0040159A   .  56            push    esi
0040159B   .  8BF1          mov     esi, ecx
0040159D   .  57            push    edi
0040159E   .  68 48304000   push    00403048                         ;  ASCII "31415926535897932384"
004015A3   .  8D4C24 14     lea     ecx, dword ptr [esp+14]
004015A7   .  897424 1C     mov     dword ptr [esp+1C], esi
004015AB   .  E8 FA020000   call    <jmp.&MFC42.#537>
004015B0   .  6A 01         push    1
004015B2   .  8BCE          mov     ecx, esi
004015B4   .  C74424 28 000>mov     dword ptr [esp+28], 0
004015BC   .  E8 E3020000   call    <jmp.&MFC42.#6334>               ;  MFC函数,此时,函数正在获取对话框的数据
004015C1   .  8B7E 60       mov     edi, dword ptr [esi+60]          ;  执行完此指令,edi存着用户名地址
004015C4   .  8B5F F8       mov     ebx, dword ptr [edi-8]           ;  用户名长度
004015C7   .  83FB 05       cmp     ebx, 5                           ;  长度不能小于5
004015CA   .  7C 7E         jl      short 0040164A
004015CC   .  8B46 64       mov     eax, dword ptr [esi+64]          ;  eax存着序列号地址
004015CF   .  894424 14     mov     dword ptr [esp+14], eax
004015D3   .  3958 F8       cmp     dword ptr [eax-8], ebx           ;  用户名序列号长度是否相同?
004015D6   .  75 72         jnz     short 0040164A
004015D8   .  83FB 14       cmp     ebx, 14                          ;  用户名长度大于0x14?
004015DB   .  7F 6D         jg      short 0040164A
004015DD   .  33C9          xor     ecx, ecx
004015DF   .  85DB          test    ebx, ebx                         ;  长度为0,则跳转。并没有用的一条指令
004015E1   .  7E 54         jle     short 00401637
004015E3   .  8B7424 10     mov     esi, dword ptr [esp+10]          ;  取密钥
004015E7   >  8A040F        mov     al, byte ptr [edi+ecx]           ;  迭代用户名字串
004015EA   .  0FBE2C31      movsx   ebp, byte ptr [ecx+esi]          ;  迭代密钥
004015EE   .  0FBEC0        movsx   eax, al
004015F1   .  99            cdq                                      ;  扩展指令
004015F2   .  F7FD          idiv    ebp                              ;  用户名字符除以密钥字符
004015F4   .  8BC2          mov     eax, edx                         ;  保留余数
004015F6   .  D1E0          shl     eax, 1                           ;  左移1位
004015F8   .  83F8 7B       cmp     eax, 7B                          ;  小于等于7B?
004015FB   .  7E 03         jle     short 00401600
004015FD   .  83E8 1A       sub     eax, 1A                          ;  大于7B则减去-1A
00401600   >  83F8 41       cmp     eax, 41                          ;  大于等于41?
00401603   .  7D 09         jge     short 0040160E                   ;  是则进入下一cmp
00401605   .  BA 82000000   mov     edx, 82
0040160A   .  2BD0          sub     edx, eax                         ;  edx-=eax
0040160C   .  8BC2          mov     eax, edx                         ;  保留edx
0040160E   >  83F8 5B       cmp     eax, 5B                          ;  小于等于5B?
00401611   .  7E 12         jle     short 00401625                   ;  是则直接去序列号进行对比
00401613   .  83F8 61       cmp     eax, 61                          ;  大于等于61?
00401616   .  7D 0D         jge     short 00401625                   ;  是则直接去序列号进行对比
00401618   .  99            cdq                                      ;  否则eax除以10
00401619   .  BD 0A000000   mov     ebp, 0A
0040161E   .  F7FD          idiv    ebp
00401620   .  83C2 30       add     edx, 30                          ;  余数+30
00401623   .  8BC2          mov     eax, edx                         ;  存入eax
00401625   >  8B5424 14     mov     edx, dword ptr [esp+14]          ;  取序列号
00401629   .  38040A        cmp     byte ptr [edx+ecx], al           ;  序列号与处理结果是否相同?
0040162C   .  75 1C         jnz     short 0040164A
0040162E   .  41            inc     ecx                              ;  循环变量自增
0040162F   .  3BCB          cmp     ecx, ebx                         ;  迭代结束?
00401631   .^ 7C B4         jl      short 004015E7
00401633   .  8B7424 18     mov     esi, dword ptr [esp+18]
00401637   >  6A 00         push    0
00401639   .  68 34304000   push    00403034                         ;  ASCII "Congratulations!"
0040163E   .  68 20304000   push    00403020                         ;  ASCII "Well done cracker!"
00401643   .  8BCE          mov     ecx, esi
00401645   .  E8 54020000   call    <jmp.&MFC42.#4224>               ;  MessageBox函数

以上就是注册的关键代码了,发现该程序调用了MFC函数,函数名并没有在OD中显示,不要紧,对比IDA中相同的地址就可以看到具体用了什么函数。快速破解这个程序需要对MFC有一定的了解。好了,仔细跟踪代码,发现程序采用了F(用户名)=序列号的判断形势,我们用高级语言实现F(用户名)即可。

打开http://www.cnblogs.com/ZRBYYXDM/p/5115596.html中搭建的框架,并修改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 >= 5 && len <= 0x14 ){                                        //格式控制。
        CString Serial = "31415926535897932384";                        //密钥
        CString PassWord = str;                                            //序列号
        
        for ( int i = 0 ; i != len ; i++ ){
            PassWord.SetAt( i,( PassWord[i] % Serial[i] ) << 1 );
            if ( PassWord[i] > 0x7B )
                PassWord.SetAt( i,PassWord[i] - 0x1A );
            if ( PassWord[i] < 0x41 )
                PassWord.SetAt( i,0x82 - PassWord[i] );

            if ( PassWord[i] > 0x5B && PassWord[i] < 0x61 )
                PassWord.SetAt( i,PassWord[i] % 10 + 0x30 );
        }

        SetDlgItemText( IDC_EDIT_PASSWORD,PassWord );
    }
    else
        MessageBox( "用户名格式错误!" );
}

再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("Rith's CrackMe #1_Keygen"));

运行效果:

我们一路奋战,不是为了改变世界,而是不让世界改变我们 ——《熔炉》
原文地址:https://www.cnblogs.com/ZRBYYXDM/p/5120411.html