首页
社区
课程
招聘
[原创][求助]我的第7个CRACKEME,分析出了算法,但不知道如何逆推注册码 ?
发表于: 2008-4-20 12:36 6003

[原创][求助]我的第7个CRACKEME,分析出了算法,但不知道如何逆推注册码 ?

2008-4-20 12:36
6003
【文章标题】: 加密解密第二版补充习题09
【文章作者】: kanghtta
【作者邮箱】: kanghtta@hotmail.com
【作者主页】: http://kanghtta.cublog.cn
【作者QQ号】: 18381291
【软件名称】: czCrackMe_09
【软件大小】: 96kb
【下载地址】: 见附件
【加壳方式】: 无
【编写语言】: MASM
【使用工具】: peid OllyICE
【操作平台】: xp
【软件介绍】: Name/Serial  难度 3
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  大家好,今天洛阳下了点小雨,这段时间刚开始学习PE文件格式,由于自我感觉它很重要,所以打算花点时间学学。就把Crackme
  冷落了,但至少 一星期一个是必须的。好了,废话不说了,以后尽量做到直奔主题。JMP 正文
  正文:
     用PEid打开,无壳,信息收集见上文;这个程序在我的屏幕上看起来有些好笑,一个按钮隐藏在位图后面,不过,
  不用担心,它能用;
  2)运行程序,name/serial 系列号保护方式,输入name: kanghtta  serial:cracker  
      嘿嘿。。messagebox : sorry Cracker, wrong。  首先考虑用字串参考;
  3)OD载入 ,反汇编窗口中,右键-〉查找-〉所有参考文本字串
     
  文本字串参考位于 czCrackM:.text, 条目 7
   地址=0040144E   反汇编=push    00403041  文本字串=ASCII "   Sorry Cracker, wrong."
  4)在字串上直接回车,当然你也可以右键-〉反汇编窗口跟随   在00401340处F2,F9运行窗口;
      输入:name: kanghtta  serial:Cracker   后,check 它,程序被断下来;
  
   
  00401340  |.  6A 40         push    40                               ; /Count = 40 (64.)
  00401342  |.  68 30314000   push    00403130                         ; |Buffer = czCrackM.00403130
  00401347  |.  FF35 C3304000 push    dword ptr [4030C3]               ; |hWnd = NULL
  0040134D  |.  E8 A6030000   call    <jmp.&USER32.GetWindowTextA>     ; \GetWindowTextA     取name,
  00401352  |.  83F8 04       cmp     eax, 4          ;name不得小于4位,否则完蛋
  00401355  |.  0F8E E9000000 jle     00401444
  0040135B  |.  6A 40         push    40                               ; /Count = 40 (64.)
  0040135D  |.  68 70314000   push    00403170                         ; |Buffer = czCrackM.00403170
  00401362  |.  68 B90B0000   push    0BB9                             ; |ControlID = BB9 (3001.)
  00401367  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
  0040136A  |.  E8 77030000   call    <jmp.&USER32.GetDlgItemTextA>    ; \GetDlgItemTextA   取 serial
  0040136F  |.  83F8 04       cmp     eax, 4                      ; serial不得小于四位,否则完蛋
  00401372  |.  0F8E CC000000 jle     00401444
  00401378  |.  A3 BF304000   mov     dword ptr [4030BF], eax
  0040137D  |.  FF35 C3304000 push    dword ptr [4030C3]               ; /hWnd = NULL
  00401383  |.  E8 AC030000   call    <jmp.&USER32.SetFocus>           ; \SetFocus      设置键盘焦点
  00401388  |.  BF 30314000   mov     edi, 00403130           name地址送edi
  0040138D  |.  BE 30314000   mov     esi, 00403130           name地址送esi
  00401392  |>  AC            /lods    byte ptr [esi]       将name按字节送al
  00401393  |.  0C 00         |or      al, 0                判断字符串是否结束
  00401395  |.  74 05         |je      short 0040139C      
  00401397  |.  0C 20         |or      al, 20              第五位置1     
  00401399  |.  AA            |stos    byte ptr es:[edi]   运算后的字符按字节存储
  0040139A  |.^ EB F6         \jmp     short 00401392
  0040139C  |>  BF 70314000   mov     edi, 00403170        serial地址送edi
  004013A1  |.  BE 70314000   mov     esi, 00403170        serial地址送esi
  004013A6  |.  8D1D 30314000 lea     ebx, dword ptr [403130]  name送ebx
  004013AC  |>  AC            /lods    byte ptr [esi]   按字节从串取,这里取的serial,
  004013AD  |.  0C 00         |or      al, 0            
  004013AF  |.  74 0A         |je      short 004013BB
  004013B1  |.  8A13          |mov     dl, byte ptr [ebx]  name按字节送dl
  004013B3  |.  2AD0          |sub     dl, al              相减
  004013B5  |.  8AC2          |mov     al, dl               结果送al
  004013B7  |.  AA            |stos    byte ptr es:[edi]   存入serial串
  004013B8  |.  43            |inc     ebx                   ebx指针加一 ,指向下一字符
  004013B9  |.^ EB F1         \jmp     short 004013AC
  004013BB  |>  8B0D BF304000 mov     ecx, dword ptr [4030BF]   serial字符数送ecx
  
  
  004013C1  |>  80C9 00       /or      cl, 0
  004013C4  |.  74 60         |je      short 00401426
  004013C6  |.  51            |push    ecx                  serial字符数进栈
  004013C7  |.  68 70314000   |push    00403170             运算后的serial字串进栈
  004013CC  |.  E8 83020000   |call    00401654          F7跟进
  
  00401654  /$  55            push    ebp
  00401655  |.  8BEC          mov     ebp, esp  ; 现场保存
  00401657  |.  51            push    ecx
  00401658  |.  57            push    edi
  00401659  |.  52            push    edx
  0040165A  |.  56            push    esi
  0040165B  |.  33C9          xor     ecx, ecx   ;  ecx清零
  0040165D  |.  8B7D 08       mov     edi, dword ptr [ebp+8]       ;serial指针送edi
  00401660  |.  FF75 08       push    dword ptr [ebp+8]                ; /String
  00401663  |.  E8 FC000000   call    <jmp.&KERNEL32.lstrlenA>         ; \lstrlenA   ;计算serial的字符串长度
  00401668  |.  EB 23         jmp     short 0040168D             ; 跳转处判断eax是否为零,不为跳回40166A处
  
  0040166A  |>  33D2          /xor     edx, edx                ;edx清零
  0040166C  |.  8A17          |mov     dl, byte ptr [edi]      ;serial送dl
  0040166E  |.  80EA 30       |sub     dl, 30                  ;减30
  00401671  |.  8BF0          |mov     esi, eax                ;serial字符数送esi
  00401673  |.  4E            |dec     esi                      ;serial字符数减一
  00401674  |.  50            |push    eax                    ;保存serial字符数
  00401675  |.  8BC2          |mov     eax, edx               ;相减的结果送eax
  00401677  |.  53            |push    ebx                    ;  保存ebx  
  00401678  |.  BB 0A000000   |mov     ebx, 0A                 0A送ebx
  0040167D  |.  EB 03         |jmp     short 00401682
  0040167F  |>  F7E3          |/mul     ebx                  结果存:edx:eax
  00401681  |.  4E            ||dec     esi
  00401682  |>  83FE 00       | cmp     esi, 0                 serial字符串是否处理完,没有就将ebx值相乘,循环乘seial字符数-1次
  00401685  |.^ 77 F8         |\ja      short 0040167F
  00401687  |.  5B            |pop     ebx
  00401688  |.  03C8          |add     ecx, eax           ;相乘的结果和ecx
  0040168A  |.  58            |pop     eax                 ;eax出栈,字符数
  0040168B  |.  47            |inc     edi
  0040168C  |.  48            |dec     eax
  0040168D  |>  0BC0           or      eax, eax                 ; 判断eax是否为零
  0040168F  |.^ 75 D9         \jnz     short 0040166A            ;不为零返回循环
  00401691  |.  8BC1          mov     eax, ecx
  00401693  |.  5E            pop     esi
  00401694  |.  5A            pop     edx
  00401695  |.  5F            pop     edi
  00401696  |.  59            pop     ecx
  00401697  |.  C9            leave
  00401698  \.  C2 0400       retn    4
  
  
  
  004013D1  |.  F7E1          |mul     ecx
  004013D3  |.  68 B0314000   |push    004031B0
  004013D8  |.  50            |push    eax
  004013D9  |.  E8 BE020000   |call    0040169C                调用: wsprintf 转换 % Lu
  004013DE  |.  BF B0314000   |mov     edi, 004031B0
  004013E3  |.  BE B0314000   |mov     esi, 004031B0         004031B0  03 06 02 03 05 09 06 07 03                       .
  004013E8  |>  AC            |/lods    byte ptr [esi]
  004013E9  |.  0C 00         ||or      al, 0
  004013EB  |.  74 06         ||je      short 004013F3
  004013ED  |.  83E0 0F       ||and     eax, 0F
  004013F0  |.  AA            ||stos    byte ptr es:[edi]
  004013F1  |.^ EB F5         |\jmp     short 004013E8
  004013F3  |>  8B0D BF304000 |mov     ecx, dword ptr [4030BF]   字符数送ecx
  004013F9  |.  D1E9          |shr     ecx, 1                    逻辑右移一位
  004013FB  |.  BF F0304000   |mov     edi, 004030F0            目的串送edi      
  00401400  |.  BE B0314000   |mov     esi, 004031B0            源串送esi
  00401405  |.  8D99 B0314000 |lea     ebx, dword ptr [ecx+4031B0]    源串地址+ecx送ebx
  0040140B  |>  80C9 00       |/or      cl, 0
  0040140E  |.  74 12         ||je      short 00401422
  00401410  |.  AC            ||lods    byte ptr [esi]    ;从esi串按字节将数字串串取出
  00401411  |.  33D2          ||xor     edx, edx        ;edx清0
  00401413  |.  8A13          ||mov     dl, byte ptr [ebx]   取ebx数字送dl
  00401415  |.  02C2          ||add     al, dl                相加
  00401417  |.  8A17          ||mov     dl, byte ptr [edi]   
  00401419  |.  02C2          ||add     al, dl               al和dl加
  0040141B  |.  24 0F         ||and     al, 0F               取al低4位
  0040141D  |.  AA            ||stos    byte ptr es:[edi]    al存004030F0
  0040141E  |.  49            ||dec     ecx                   循环计数器减一
  0040141F  |.  43            ||inc     ebx                   ebx指针加一
  00401420  |.^ EB E9         |\jmp     short 0040140B                        循环以上直到ecx为0跳转
  00401422  |>  59            |pop     ecx                       
  00401423  |.  49            |dec     ecx                  
  00401424  |.^ EB 9B         \jmp     short 004013C1         跳转直到ecx为0               
  
  00401426  |>  BE F0304000   mov     esi, 004030F0         运算结果送esi
  0040142B  |.  8B1D BF304000 mov     ebx, dword ptr [4030BF]  serial字符数送ebx
  00401431  |.  8BCB          mov     ecx, ebx   
  00401433  |.  D1E9          shr     ecx, 1                   ecx逻辑右移一位
  00401435  |>  8A06          /mov     al, byte ptr [esi]
  00401437  |.  80C9 00       |or      cl, 0              是否为0,为0 则注册成功
  0040143A  |.  74 39         |je      short 00401475  
  0040143C  |.  38D8          |cmp     al, bl                按字节比较004030F0和字符数,相同则ecx减一;减到0 则注册成功;
  0040143E  |.  75 04         |jnz     short 00401444
  00401440  |.  46            |inc     esi
  00401441  |.  49            |dec     ecx
  00401442  |.^ EB F1         \jmp     short 00401435
  00401444  |>  68 00200000   push    2000                             ; /Style = MB_OK|MB_TASKMODAL
  00401449  |.  68 18304000   push    00403018                         ; |Title = "               Error"
  0040144E  |.  68 41304000   push    00403041                         ; |Text = "   Sorry Cracker, wrong."
  00401453  |.  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
  00401456  |.  E8 BB020000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
  0040145B  |.  6A 40         push    40                               ; /Length = 40 (64.)
  0040145D  |.  68 F0304000   push    004030F0                         ; |Destination = czCrackM.004030F0
  00401462  |.  E8 0F030000   call    <jmp.&KERNEL32.RtlZeroMemory>    ; \RtlZeroMemory
  00401467  |.  6A 40         push    40                               ; /Length = 40 (64.)
  00401469  |.  68 B0314000   push    004031B0                         ; |Destination = czCrackM.004031B0
  0040146E  |.  E8 03030000   call    <jmp.&KERNEL32.RtlZeroMemory>    ; \RtlZeroMemory
  00401473  |.  EB 2F         jmp     short 004014A4
  00401475  |>  68 00200000   push    2000                             ; /Style = MB_OK|MB_TASKMODAL
  0040147A  |.  68 2D304000   push    0040302D                         ; |Title = "       <Registered>"
  0040147F  |.  68 5A304000   push    0040305A                         ; |Text = "            You did it!"
  00401484  |.  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
  00401487  |.  E8 8A020000   call    <jmp.&USER32.MessageBoxA>        ; \MessageBoxA
  0040148C  |.  6A 40         push    40                               ; /Length = 40 (64.)
  0040148E  |.  68 F0304000   push    004030F0                         ; |Destination = czCrackM.004030F0
  00401493  |.  E8 DE020000   call    <jmp.&KERNEL32.RtlZeroMemory>    ; \RtlZeroMemory
  00401498  |.  6A 40         push    40                               ; /Length = 40 (64.)
  0040149A  |.  68 B0314000   push    004031B0                         ; |Destination = czCrackM.004031B0
  0040149F  |.  E8 D2020000   call    <jmp.&KERNEL32.RtlZeroMemory>    ; \RtlZeroMemory
  004014A4  |>  EB 0E         jmp     short 004014B4
  004014A6  |>  66:83F8 67    cmp     ax, 67
  004014AA  |.  75 08         jnz     short 004014B4
  004014AC  |.  FF75 08       push    dword ptr [ebp+8]                ; /hWnd
  004014AF  |.  E8 26020000   call    <jmp.&USER32.DestroyWindow>      ; \DestroyWindow
  004014B4  |>  EB 15         jmp     short 004014CB
  004014B6  |>  FF75 14       push    dword ptr [ebp+14]               ; /lParam
  004014B9  |.  FF75 10       push    dword ptr [ebp+10]               ; |wParam
  004014BC  |.  FF75 0C       push    dword ptr [ebp+C]                ; |Message
  004014BF  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
  004014C2  |.  E8 0D020000   call    <jmp.&USER32.DefWindowProcA>     ; \DefWindowProcA
  004014C7  |.  C9            leave
  004014C8  |.  C2 1000       retn    10
  004014CB  |>  33C0          xor     eax, eax
  004014CD  |.  C9            leave
  004014CE  \.  C2 1000       retn    10
  
  算法分析:
  #include<iostream.h>
#include<windows.h>
#include<string.h>
#include<assert.h>
#include<iomanip.h>

#define C_ECX 0x7C80BDE6
long _cover(int count,char lpszSerial[])
{
         int ecx=C_ECX;
         int edx=0;
                for(int i=0;i<count;i++)
                {
                edx=lpszSerial[i]-0x30;
                int esi=count;
                esi--;
                int eax=edx;
                int ebx=0x0A;
                for(int j=0;j<esi;j++)
                        {
                                eax=ebx*eax;
                        }
               
                ecx=ecx+eax;
                }
                return ecx;
}

bool _check_Key(int count,char *lpStr)
{              int bl=count;
        count=count/2;
        for(int i=0;i<=count;i++)
        {
                if(lpStr[i]!=bl)
                        return 0;
        }
        return 1;
}

void main()
{
         char szName[20]={0,0,0};
         char szSerial[20]={0,0,0};
        //输入用户名
        cout<<"请输入用户名 (大于4位):"<<endl;
        cin>>szName;
        int n_count=strlen(szName);  //求用户名长度
        assert(n_count>4);
    //输入系列号
        cout<<"请输入注册号(大于4位):"<<endl;
        cin>>szSerial;
        int s_count=strlen(szSerial);//求注册号长度
        assert(s_count>4);

     for(int i=0;i<n_count;i++)
        {
                szName[i]=szName[i]|0x20;
                cout<<szName[i];
        }
        cout<<endl;

    for(int j=0;j<s_count;j++)
        {
        char szMd1=szName[j];
        szMd1-=szSerial[j];
        szSerial[j]=szMd1;
        cout<<szSerial[j];
        }
        cout<<endl;

        char temp_string[10]={0,0,0};
        char end_string[10]={0,0,0};       
        long int middle=0;
       
     for(int k=0;k<s_count;k++)       
         {
                middle=_cover(s_count,szSerial);
                middle=middle*s_count;
                wsprintf(temp_string,"%lu",middle);
                i=0;
                cout<<hex<<middle<<endl;

                while(temp_string[i])
                {        temp_string[i]&=0x0f;
                        i++;
                }

                middle=s_count/2;
                i=middle;
                j=0;
                while(middle)
                        {       
                        end_string[j]+=(temp_string[j]+temp_string[i]);
                        end_string[j]&=0x0f;
                        j++;
                        i++;
                        middle--;
                }

        }
        s_count=strlen(szSerial);
        cout<<"s_count"<<s_count<<endl;
        bool a;
   a=_check_Key(s_count,end_string);
   if(a)
  {
   cout<<"you did it"<<endl;
}
esle cout<<"sorry cracker wrong"<<endl;
}

       
  
  分析的过程中,被人打断多次,看有同学能弄出这个CRACKER的注册机来,注意:我要的是注册机算法,不是暴破,关于怎么爆破,我不需要;请另发别出;谢谢;

               
   程序基本上是,反汇编到C 的还原 ;嘿嘿,转换的中间数值不知道怎么得出;
大虾们帮个忙?
  
  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2008年04月20日 PM 12:29:44

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
2
瞧瞧看。。。
2008-4-20 14:30
0
雪    币: 420
活跃值: (77)
能力值: ( LV13,RANK:500 )
在线值:
发帖
回帖
粉丝
3
这个CRACKE
循环有点多,比较的是注册号的位数,相同则计数器减一, 减到0就成功破解!  
  
所以把004030F0  里的数据 都假定为注册号数,在逆推;应该可以! 一会我也试试看!
2008-4-20 18:03
0
雪    币: 926
活跃值: (397)
能力值: (RANK:500 )
在线值:
发帖
回帖
粉丝
4
Name:humourkyo
Serial:7E<:A?5A
2008-4-21 03:59
0
雪    币: 420
活跃值: (77)
能力值: ( LV13,RANK:500 )
在线值:
发帖
回帖
粉丝
5
  能点一下如何算的吗 !谢谢;
2008-4-21 09:11
0
雪    币: 347
活跃值: (30)
能力值: ( LV9,RANK:420 )
在线值:
发帖
回帖
粉丝
6
你把算法理解错了
2008-4-21 11:00
0
雪    币: 420
活跃值: (77)
能力值: ( LV13,RANK:500 )
在线值:
发帖
回帖
粉丝
7
????
算法是指完成一个任务准确而完整的描述。也就是说给定初始状态或输入数据,经过计算机程序的有限次运算,能够得出所要求或期望的终止状态或输出数据。

算法常常含有重复的步骤和一些比较或逻辑判断。如果一个算法有缺陷,或不适合于某个问题,执行这个算法将不会解决这个问题。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。
“算法”的中文名称出自周髀算经;而英文名称 Algorithm 来自于9世纪波斯数学家比阿勒·霍瓦里松的名字al-Khwarizmi,因为比阿勒·霍瓦里松在数学上提出了算法这个概念。“算法”原为"algorism",意思是阿拉伯数字的运算法则,在18世纪演变为"algorithm"。欧几里得算法被人们认为是史上第一个算法。...........
2008-4-21 12:35
0
雪    币: 295
活跃值: (11)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
8
我也来一个
我发现里面有一个ecx的值  在条件相同的情况下 winXP和win2003 得到不一样的值
就是
00401660  |.  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; /String
00401663  |.  E8 FC000000   CALL <JMP.&KERNEL32.lstrlenA>            ; \lstrlenA

这个函数。

win2003下:
findlakes
59>,4*:1

winxp下:
findlakes
59=/8.5-

这个crackme很有意思。只是楼主应该多思考。象这样的没任何ANTI的,还是ASM写的 分析起来和看原代码又有何区别呢?楼主把其还原成C对于这个算法而言有用吗?
给个提示,你可以穷举下啊。
2008-4-21 13:29
0
游客
登录 | 注册 方可回帖
返回
//