专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > 信息/网络安全

巧用内存储器断点破解二元函数加密

发布时间:2011-07-03 06:59:54 文章来源:www.iduyao.cn 采编人员:星星草
巧用内存断点破解二元函数加密

系统 : Windows xp

程序 : Chafe.1

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

要求 : 注册机编写 

使用工具 : OD & IDA

这个CRACKME最初是在http://www.cnblogs.com/bbdxf/p/3817880.html这篇博文里发现的,跟你看到的一样,原文只分析了算法,并没有给出注册机的写法。

 

  原博主笨笨D幸福是一个逆向前辈,曾在一个多月里破解了37个CrackMe,是我这种破解新手非常崇拜的大牛。然而,2014年7月18日之后他的博客就再也没有更新过,最后的动态也只是说:“最近一直出差,这两个月都没时间了。现在还在外地呢”。

 

  我不知道他因为什么原因突然停更,但我觉得有必要走上他曾经探索过的道路。时间不够也罢,心情不好也罢,断在中途的这条道路就由我替你延续,这个CRACKME就由我来破解!

 

还是老规矩,IDA载入程序,查看字串表得到关键字串“YES! You found your serial!!”。定位字串调用位置并向上翻找到关键算法:

0040128D  |> \3D 13010000   cmp     eax, 113
00401292  |.  75 50         jnz     short 004012E4
00401294  |.  E8 BA010000   call    00401453                         ;  Case 113 (WM_TIMER) of switch 0040123F
00401299  |.  0FBE05 663140>movsx   eax, byte ptr [403166]           ;  eax值取自403166
004012A0  |.  3A05 67314000 cmp     al, byte ptr [403167]
004012A6  |.  75 06         jnz     short 004012AE
004012A8  |.  33C0          xor     eax, eax
004012AA  |.  C9            leave
004012AB  |.  C2 1000       retn    10
004012AE  |>  A2 67314000   mov     byte ptr [403167], al
004012B3  |.  83F8 10       cmp     eax, 10                          ;  如果eax的值为10,则成功
004012B6  |.  74 16         je      short 004012CE
004012B8  |.  68 65304000   push    00403065                         ; /Text = "Your serial is not valid."
004012BD  |.  FF35 7C314000 push    dword ptr [40317C]               ; |hWnd = 0019090C ('Your serial is not valid.',class='Edit',parent=0022092A)
004012C3  |.  E8 66020000   call    <jmp.&USER32.SetWindowTextA>     ; \SetWindowTextA
004012C8  |.  33C0          xor     eax, eax
004012CA  |.  C9            leave
004012CB  |.  C2 1000       retn    10
004012CE  |>  68 7F304000   push    0040307F                         ; /Text = "YES! You found your serial!!"
004012D3  |.  FF35 7C314000 push    dword ptr [40317C]               ; |hWnd = 0019090C ('Your serial is not valid.',class='Edit',parent=0022092A)
004012D9  |.  E8 50020000   call    <jmp.&USER32.SetWindowTextA>     ; \SetWindowTextA
004012DE  |.  33C0          xor     eax, eax
004012E0  |.  C9            leave

对403166内存下写入断点:运行程序找出4处对内存的写入操作:

0040146F   .  8B25 A0314000 mov     esp, dword ptr [4031A0]          ;  ↓获取int值成功加4(1)
00401475   .  6A 00         push    0                                ; /IsSigned = FALSE
00401477   .  8D45 FC       lea     eax, dword ptr [ebp-4]           ; |
0040147A   .  50            push    eax                              ; |pSuccess
0040147B   .  6A 64         push    64                               ; |ControlID = 64 (100.)
0040147D   .  FF35 70314000 push    dword ptr [403170]               ; |hWnd = 0022092A ('TEXme v1.0',class='TEXcls')
00401483   .  E8 64000000   call    <jmp.&USER32.GetDlgItemInt>      ; \GetDlgItemInt
00401488   .  A3 88314000   mov     dword ptr [403188], eax          ;  保存序列号
0040148D   .  837D FC 00    cmp     dword ptr [ebp-4], 0             ;  获取失败?
00401491   .  74 07         je      short 0040149A
00401493   .  8005 66314000>add     byte ptr [403166], 4             ;  成功数值加4,403166 = 4
0040149A   >  C9            leave
0040149B   .  C3            retn

还有:

00401069   .  6A 14         push    14                               ; /Count = 14 (20.)
0040106B   .  68 8C314000   push    0040318C                         ; |Buffer = Chafe_1.0040318C
00401070   .  FF35 74314000 push    dword ptr [403174]               ; |hWnd = 003D0922 (class='Edit',parent=0022092A)
00401076   .  E8 7D040000   call    <jmp.&USER32.GetWindowTextA>     ; \GetWindowTextA
0040107B   .  B9 14000000   mov     ecx, 14                          ;  ↑返回用户名长度
00401080   .  2BC8          sub     ecx, eax
00401082   .  8DB8 8C314000 lea     edi, dword ptr [eax+40318C]
00401088   >  C607 00       mov     byte ptr [edi], 0
0040108B   .  47            inc     edi
0040108C   .  49            dec     ecx
0040108D   .^ 75 F9         jnz     short 00401088
0040108F   .  85C0          test    eax, eax                         ;  用户名是0?
00401091   .  74 10         je      short 004010A3
00401093   .  8005 66314000>add     byte ptr [403166], 4             ;  用户名不为空则加4(2)
0040109A   .  C605 68314000>mov     byte ptr [403168], 0
004010A1   .  EB 06         jmp     short 004010A9
004010A3   >  8825 66314000 mov     byte ptr [403166], ah
004010A9   >  C9            leave
004010AA   .  C3            retn

以及很关键的第三处:

00401361   .  8D3D 8C314000 lea     edi, dword ptr [40318C]          ;  取用户名(一直调用这个子程序)
00401367   .  0FBE05 683140>movsx   eax, byte ptr [403168]           ;  取内存地址
0040136E   .  03F8          add     edi, eax
00401370   .  FE05 68314000 inc     byte ptr [403168]                ;  自增
00401376   .  A1 88314000   mov     eax, dword ptr [403188]
0040137B   .  8B25 A0314000 mov     esp, dword ptr [4031A0]
00401381   .  40            inc     eax
00401382   .  FF05 88314000 inc     dword ptr [403188]
00401388   .  3307          xor     eax, dword ptr [edi]
0040138A   .  A3 88314000   mov     dword ptr [403188], eax
0040138F   .  803D 68314000>cmp     byte ptr [403168], 10            ;  循环到第16次,403168为10
00401396   .  75 07         jnz     short 0040139F
00401398   .  8005 66314000>add     byte ptr [403166], 4             ;  调用第16次时+4(3)
0040139F   >  C9            leave
004013A0   .  C3            retn

最后一处:

0040149C   .  A1 88314000   mov     eax, dword ptr [403188]          ;  当此内存的值为F6EEDB88时,
004014A1   .  05 78241109   add     eax, 9112478
004014A6   .  85C0          test    eax, eax                         ;  eax为0
004014A8   .  75 09         jnz     short 004014B3                   ;  跳转+4,否则清空403166
004014AA   .  8005 66314000>add     byte ptr [403166], 4             ;  403166 = 0x10
004014B1   .  EB 07         jmp     short 004014BA
004014B3   >  C605 66314000>mov     byte ptr [403166], 0
004014BA   >  8B25 A0314000 mov     esp, dword ptr [4031A0]
004014C0   .  C9            leave
004014C1   .  C3            retn

结合第三、第四个汇编代码段可知程序将用户名和序列号进行了一些操作,并判断最后得出的操作数确定是否注册成功。这是典型的采用二元函数进行加密的方式: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 <= 19 ){                                        //格式控制。
        //模拟F(用户名,序列号)= 特定值
        /*
            char Name[20] = "";
            unsigned int Serial = 1;                                    //序列号123
        
            strcpy( Name,str );                                            //复制用户名字串
            //
            for ( int i = 0 ; i != 16 ; i++ ){
                Serial++;
                Serial ^= ( Name[i] + Name[i+1] * 0x100 + Name[i+2] * 0x10000 + Name[i+3] * 0x1000000 );
            }

            if ( Serial == 0xF6EEDB88 )
                MessageBox( "Ok" );
            else
                MessageBox( "Error" );
        */
        //写出F(用户名,序列号)= 特定值 的逆算法
        char Name[20] = "";
        unsigned int value = 0xF6EEDB88;
        
        strcpy( Name,str );                                            //复制用户名字串
        
        for ( int i = 15 ; i != -1 ; i-- ){
                value ^= ( Name[i] + Name[i+1] * 0x100 + Name[i+2] * 0x10000 + Name[i+3] * 0x1000000 );
                value--;
        }

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

再在OnInitDialog中添加此代码修改标题:SetWindowText(_T("Chafe.1_Keygen"));

运行效果:

友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

热门推荐: