首页
社区
课程
招聘
[原创]适合初学者的crackme算法分析
发表于: 2007-1-13 23:15 6662

[原创]适合初学者的crackme算法分析

2007-1-13 23:15
6662

【文章标题】: happytown'crackme算法分析
【文章作者】: netwind
【软件名称】: crackme
【下载地址】: http://bbs.pediy.com/attachment.php?s=&attachmentid=4026
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  右键,查找 所有参考文本串,找到good boy,双击来到如下位置:
  004012BE   .  6A 40         push    40                               ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  004012C0   .  68 DB624000   push    004062DB                         ; |Title = "Good boy..."
  004012C5   .  68 AC624000   push    004062AC                         ; |Text = "Yep, thats the right code!",LF,CR,"Go write a keygen!"
  004012CA   .  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
  004012CD   .  E8 CA000000   call    <jmp.&user32.MessageBoxA>        ; \MessageBoxA
  
  此处就是正确提示的地方
  向上观察有如下代码:
  00401141   .  E8 4A020000   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA
  00401146   .  83F8 03       cmp     eax, 3                           ;判断用户名长度是否小于等于3
  00401149   .  77 18         ja      short 00401163                   ;是则出错。
  0040114B   .  6A 10         push    10                               ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL
  0040114D   .  68 06634000   push    00406306                         ; |Title = "Bad boy..."
  00401152   .  68 0A624000   push    0040620A                         ; |Text = "Username must have at least 4 chars..."
  00401157   .  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
  0040115A   .  E8 3D020000   call    <jmp.&user32.MessageBoxA>        ; \MessageBoxA
  0040115F   .  C9            leave
  00401160   .  C2 1000       retn    10
  00401163   >  8D15 49634000 lea     edx, [406349]
  00401169   .  52            push    edx                              ; /String => ""
  0040116A   .  E8 8D020000   call    <jmp.&kernel32.lstrlenA>         ; \lstrlenA
  0040116F   .  8BE8          mov     ebp, eax
  00401171   .  B9 05000000   mov     ecx, 5
  00401176   .  33F6          xor     esi, esi
  00401178   .  33C0          xor     eax, eax
  0040117A   > /8A0C16        mov     cl, [esi+edx]          ;  第一处算法开始,从注册名第二个字符开始取字符
  0040117D   . |8AD9          mov     bl, cl
  0040117F   . |3298 28634000 xor     bl, [eax+406328]       ;  将取得字符与内存eax+406328处值xor运算
  00401185   . |40            inc     eax
  00401186   . |83F8 05       cmp     eax, 5
  00401189   . |881C32        mov     [edx+esi], bl          ;  将xor后的值存放
  0040118C   . |8888 27634000 mov     [eax+406327], cl       ;  将取得的用户名字符的值存放
  00401192   . |75 02         jnz     short 00401196         ;  eax 大于5则取 eax为0
  00401194   . |33C0          xor     eax, eax
  00401196   > |46            inc     esi
  00401197   . |3BF5          cmp     esi, ebp               ;  判断运算次数是否大于用户名长度
  00401199   .^\72 DF         jb      short 0040117A         ;循环运算
  0040119B   .  33FF          xor     edi, edi
  0040119D   .  33C9          xor     ecx, ecx
  0040119F   .  85ED          test    ebp, ebp
  004011A1   .  76 26         jbe     short 004011C9
  004011A3   >  8A9F 2D634000 mov     bl, [edi+40632D]       ;  第二步算法开始,接着从内存取值
  004011A9   .  8BF5          mov     esi, ebp
  004011AB   .  2BF1          sub     esi, ecx
  004011AD   .  4E            dec     esi
  004011AE   .  8A0432        mov     al, [edx+esi]          ;  取上面xor运算后存放的值
  004011B1   .  32D8          xor     bl, al                 ;  将取出的值同内存存放的值xor运算
  004011B3   .  47            inc     edi
  004011B4   .  881C32        mov     [edx+esi], bl
  004011B7   .  8887 2C634000 mov     [edi+40632C], al
  004011BD   .  83FF 05       cmp     edi, 5                 ;  如果大于5 ,再从40632d开始取
  004011C0   .  75 02         jnz     short 004011C4
  004011C2   .  33FF          xor     edi, edi
  004011C4   >  41            inc     ecx
  004011C5   .  3BCD          cmp     ecx, ebp               ;  运算次数为用户名长度
  004011C7   .^ 72 DA         jb      short 004011A3
  004011C9   >  33F6          xor     esi, esi
  004011CB   .  33FF          xor     edi, edi
  004011CD   .  85ED          test    ebp, ebp
  004011CF   .  76 21         jbe     short 004011F2
  004011D1   >  8A043A        mov     al, [edx+edi]          ;  第三处算法开始,取上一步xor后的值
  004011D4   .  8A8E 32634000 mov     cl, [esi+406332]       ;  继续从内存取值
  004011DA   .  32C8          xor     cl, al
  004011DC   .  46            inc     esi
  004011DD   .  880C3A        mov     [edx+edi], cl          ;  存放xor 运算后的值
  004011E0   .  8886 31634000 mov     [esi+406331], al
  004011E6   .  83FE 05       cmp     esi, 5                 ;  如果大于5 ,再从406332开始取
  004011E9   .  75 02         jnz     short 004011ED
  004011EB   .  33F6          xor     esi, esi
  004011ED   >  47            inc     edi
  004011EE   .  3BFD          cmp     edi, ebp               ;  运算次数为用户名长度
  004011F0   .^ 72 DF         jb      short 004011D1
  004011F2   >  33FF          xor     edi, edi
  004011F4   .  33C9          xor     ecx, ecx
  004011F6   .  85ED          test    ebp, ebp
  004011F8   .  76 26         jbe     short 00401220
  004011FA   >  8A9F 37634000 mov     bl, [edi+406337]       ;  第三处算法开始,接着从内存取值
  00401200   .  8BF5          mov     esi, ebp
  00401202   .  2BF1          sub     esi, ecx
  00401204   .  4E            dec     esi
  00401205   .  8A0432        mov     al, [edx+esi]          ;  取上一步xor运算后的值
  00401208   .  32D8          xor     bl, al                 ;  将两次取值xor 运算
  0040120A   .  47            inc     edi
  0040120B   .  881C32        mov     [edx+esi], bl
  0040120E   .  8887 36634000 mov     [edi+406336], al
  00401214   .  83FF 05       cmp     edi, 5                 ;  大于5再从本次取值开始取
  00401217   .  75 02         jnz     short 0040121B
  00401219   .  33FF          xor     edi, edi
  0040121B   >  41            inc     ecx
  0040121C   .  3BCD          cmp     ecx, ebp               ;  运算次数为用户名长度
  0040121E   .^ 72 DA         jb      short 004011FA
  00401220   >  8D3D 45634000 lea     edi, [406345]
  00401226   .  33C0          xor     eax, eax
  00401228   .  85ED          test    ebp, ebp
  0040122A   .  C705 45634000>mov     dword ptr [406345], 0
  00401234   .  76 17         jbe     short 0040124D
  00401236   >  8BC8          mov     ecx, eax               ;  第四处运算开始,
  00401238   .  83E1 03       and     ecx, 3                 ;  以ecx计数,四次运算后从头开始从内存取值运算
  0040123B   .  8A1C0F        mov     bl, [edi+ecx]          ;  从内存取值,此处初始为0
  0040123E   .  8D340F        lea     esi, [edi+ecx]
  00401241   .  8A0C02        mov     cl, [edx+eax]          ;  取上一步xor后的值
  00401244   .  02D9          add     bl, cl                 ;  将两次取值相加
  00401246   .  40            inc     eax
  00401247   .  3BC5          cmp     eax, ebp               ;  以用户名长度为运算次数
  00401249   .  881E          mov     [esi], bl              ;  将相加后低八位保存
  0040124B   .^ 72 E9         jb      short 00401236
  0040124D   >  5D            pop     ebp
  0040124E   .  B9 0A000000   mov     ecx, 0A
  00401253   .  A1 45634000   mov     eax, [406345]
  00401258   .  33DB          xor     ebx, ebx
  0040125A   >  33D2          xor     edx, edx               ;  第五出运算开始
  0040125C   .  F7F1          div     ecx                    ;  将上面加运算得到的值eax除以0xa取余数,eax取除后的整数
  0040125E   .  80C2 30       add     dl, 30                 ;  将余数转为对应的字符
  00401261   .  8893 49654000 mov     [ebx+406549], dl       ;  保存字符
  00401267   .  43            inc     ebx
  00401268   .  85C0          test    eax, eax               ;  若eax不为0继续运算
  0040126A   .^ 75 EE         jnz     short 0040125A
  0040126C   .  68 49654000   push    00406549               ; /得到上面运算后的字符串
  00401271   .  E8 86010000   call    <jmp.&kernel32.lstrlen>; \lstrlenA
  00401276   .  33DB          xor     ebx, ebx
  00401278   >  8A88 48654000 mov     cl, [eax+406548]
  0040127E   .  888B 49674000 mov     [ebx+406749], cl
  00401284   .  43            inc     ebx
  00401285   .  48            dec     eax
  00401286   .^ 75 F0         jnz     short 00401278
  00401288   .  68 49674000   push    00406749               ; /这里得到的是将上面字符串取反得到的串,就是注册码
  0040128D   .  68 49654000   push    00406549               ; |String1 = crackme.00406549
  00401292   .  E8 5F010000   call    <jmp.&kernel32.lstrcpy>; \lstrcpyA
  00401297   .  68 00020000   push    200                    ; /Count = 200 (512.)
  0040129C   .  68 49694000   push    00406949               ; |Buffer = crackme.00406949
  004012A1   .  6A 64         push    64                     ; |ControlID = 64 (100.)
  004012A3   .  FF75 08       push    dword ptr [ebp+8]      ; |hWnd
  004012A6   .  E8 E5000000   call    <jmp.&user32.GetDlgIte>; \GetDlgItemTextA
  004012AB   .  68 49654000   push    00406549               ; /String2 = ""
  004012B0   .  68 49694000   push    00406949               ; |String1 = ""
  004012B5   .  E8 36010000   call    <jmp.&kernel32.lstrcmp>; \lstrcmpA
  004012BA   .  0BC0          or      eax, eax
  004012BC   .  75 16         jnz     short 004012D4
  004012BE   .  6A 40         push    40                     ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
  004012C0   .  68 DB624000   push    004062DB               ; |Title = "Good boy..."
  004012C5   .  68 AC624000   push    004062AC               ; |Text = "Yep, thats the right code!",LF,CR,"Go write a keygen!"
  004012CA   .  FF75 08       push    dword ptr [ebp+8]      ; |hOwner
  004012CD   .  E8 CA000000   call    <jmp.&user32.MessageBo>; \MessageBoxA
  
  该crackme完全是对用户名字符串进行一系列xor 运算,把部分结果除以0xa取余数
  得到一字符串,再取反得到注册码。
  以下为注册机代码:
  #include <stdio.h>
  #include <string.h>
  void main()
  {
          char name[]="hello",result[20];
          int s[]={0xaa,0x89,0xc4,0xfe,0x46,
                       0x78,0xf0,0xd0,0x03,0xe7,
                           0xf7,0xfd,0xf4,0xe7,0xb9,
                           0xb5,0x1b,0xc9,0x50,0x73,
                           0x00,0x00,0x00,0x00,0x00,
          };
          int r[20];
          int i=0,j=0,tmp=0;
          unsigned long rr;
          printf("name is: %s\n",name);
          for(i=0;j<strlen(name);i++)
          {
                 
                  r[j]=name[j+1]^s[i];
                  s[i]=name[j+1];
                  if(i==4)
                          i=-1;
          j++;
          }
         
          j=strlen(name)-1;
          for(i=5;j>-1;i++)
          {
                  tmp=r[j];
                  r[j]^=s[i];
                  s[i]=tmp;
                  if(i==9)
                          i=4;
         
          j--;
          }
          j=0;
          for(i=10;j<strlen(name);i++)
          {
                  tmp=r[j];
                  r[j]^=s[i];
                  s[i]=tmp;
                  if(i==14)
                          i=9;
                  j++;
          }
         
          j=strlen(name)-1;
          for(i=15;j>-1;i++)
          {
                  tmp=r[j];
                  r[j]^=s[i];
                  s[i]=tmp;
                  if(i==19)
                          i=14;
                  j--;
          }
      j=4;
          for(i=0;j<strlen(name);i++,j++)
          {
         
                  r[i]+=r[j];
          if(r[i]>=0x100)r[i]=r[i]%0x100;
          if(i&&(i%3==0))
                  i=-1;
          }
          rr=r[0]+r[1]*0x100+r[2]*0x10000+r[3]*0x1000000;
          i=0;
          printf("key is:");
          while(rr)
          {
                  tmp=rr%0xa;
                  result[i++]=tmp+'0';
                  rr/=0xa;
          }
          result[i]='\0';
          for(i=strlen(result)-1;i>=0;i--)
          printf("%c",result[i]);
          printf("\n");
  }
  完全照汇编代码顺序写下来的,看代码可以帮助理解crackme运算过程。
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年01月13日 23:11:51


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2022-7-7 10:14 被netwind编辑 ,原因:
收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
2
出来了,顶一下
2007-1-13 23:16
0
雪    币: 200
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
zcg
3
学习了,再顶一下!
2007-1-13 23:18
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
分析的思路很清楚
2007-1-14 01:40
0
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
5
最初由 netwind 发布
...happytown'crackme算法分析......

改一下标题吧,这个我只是推荐人,程序作者不是我,是lafarge.
2007-1-17 09:34
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
可以
2007-1-19 13:36
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习了~~顶上!
2007-1-19 14:58
0
游客
登录 | 注册 方可回帖
返回
//