首页
社区
课程
招聘
[原创]ty123 Crackme 5的分析
发表于: 2007-2-5 18:45 5412

[原创]ty123 Crackme 5的分析

2007-2-5 18:45
5412

【文章标题】: ty123 Crackme 5的分析
【文章作者】: atomy
【作者主页】: http://2lin.net
--------------------------------------------------------------------------------
【详细过程】
  首先感谢作者写出这么好的Creakme给我们这些小菜鸟们练手。
    之前那个〈ty123的实用crackme- CPN Augur (新手飘过~~) 〉搞的偶晕头转向 确实不是新手练的。
    先来分析一下代码吧。
    新手拿到Crackme时可能不知道怎么下断点 如何找到代码 这个CrackMe代码比较小 可以手动查找 
    也可以输入命令 bp GetDlgItemTextA 
    有一处断点
    004011C6   .- FF25 20204000 jmp     [<&user32.GetDlgItemTextA>]      ;  user32.GetDlgItemTextA
    其实
    edi = 004011C6
    004010CD   > \83EF 08       sub     edi, 8
    004010D0   .  FFD7          call    edi                              ;  
   
    call edi 就是 call user32.GetDlgItemTextA 了
   
    好了可以从这里根下去了
   
    分析如下
   
    004010CD   > \83EF 08       sub     edi, 8
    004010D0   .  FFD7          call    edi                              ;  
    004010D2   .  85C0          test    eax, eax
    004010D4   .  0F84 92000000 je      0040116C
    004010DA   .  C1E0 08       shl     eax, 8                           ;  Count shl 8
    004010DD   .  66:3D 0020    cmp     ax, 2000
    004010E1   .  0F8F 85000000 jg      0040116C                         ;  ax > 2000 跳走 注册码最大32位
    004010E7   .  8D35 F9304000 lea     esi, [4030F9]                    ;  输入序列号
    004010ED   .  C1E8 08       shr     eax, 8                           ;  EAX = 序列号个数
    004010F0   .  91            xchg    eax, ecx                         ;  放入 ECX 循环次数
    004010F1   .  33C0          xor     eax, eax
    004010F3   .  33D2          xor     edx, edx
    004010F5   >  AC            lods    byte ptr [esi]
    004010F6   .  03D0          add     edx, eax                         ;  edx += eax  将序列号的 ascii 码相加
    004010F8   .^ E2 FB         loopd   short 004010F5
    004010FA   .  3315 B4314000 xor     edx, [4031B4]                    ;  xor C:\序号 GetVolumeInformation
   
    [4031B4] 哪里来的呢? 先在这个内存处下个硬件写断点 
    重新启动程序 发现 该内存 原来是用 GetVolumeInformation 获取 C:\ 的序号
   
    00401100   .  52            push    edx                              ;  保存 edx s
    00401101   .  8D3D A6114000 lea     edi, [4011A6]
    00401107   .  68 2B314000   push    0040312B
    0040110C   .  68 80000000   push    80
    00401111   .  EB 05         jmp     short 00401118
    00401113   .  44 46 43 47 0>ascii   "DFCG",0
    00401118   >  83EF 04       sub     edi, 4
    0040111B   .  FFD7          call    edi                              ;  获取当前目录
    0040111D   .  83E8 08       sub     eax, 8                           ;  目录值 - 8
    00401120   .  8D90 2B314000 lea     edx, [eax+40312B]                ;  取当前目录的最后面8个字符
    00401126   .  52            push    edx
    00401127   .  E8 AC000000   call    004011D8                         ;  将字符计算得到一个数字
    0040112C   .  5A            pop     edx
    0040112D   .  33C2          xor     eax, edx                         ;  将值 xor s
    0040112F      75 3B         jnz     short 0040116C                   ;  爆破点 s != 算出值 出错

这里不能单改成jz暴破需要动态修改 dx的值才行
   
   
    再看看 00401127   .  E8 AC000000   call    004011D8 是如何计算的
   
    004011DE  |.  8B7D 08       mov     edi, [ebp+8]                     ;  后面八个字符
    004011E1  |.  8B75 08       mov     esi, [ebp+8]
    004011E4  |>  8A07          /mov     al, [edi]
    004011E6  |.  47            |inc     edi
    004011E7  |.  0AC0          |or      al, al
    004011E9  |.^ 75 F9         \jnz     short 004011E4                  ;  有可能少于八个字符
    004011EB  |.  2BF7          sub     esi, edi                         ;  esi -= edi 取长度
    004011ED  |.  33DB          xor     ebx, ebx
    004011EF  |.  03FE          add     edi, esi                         ;  edi += esi 还原edi重新指向字符串头
    004011F1  |.  33D2          xor     edx, edx
    004011F3  |.  F7D6          not     esi                              ;  not esi (esi 实际长度)
    004011F5  |.  EB 23         jmp     short 0040121A
    004011F7  |>  8A07          /mov     al, [edi]
    004011F9  |.  3C 41         |cmp     al, 41                          ;  al < 41(A)
    004011FB  |.  72 0C         |jb      short 00401209
    004011FD  |.  2C 57         |sub     al, 57                          ;  al - 57(W)
    004011FF  |.  80D2 00       |adc     dl, 0
    00401202  |.  C0E2 05       |shl     dl, 5
    00401205  |.  02C2          |add     al, dl                          ;  al += dl(dl=0)
    00401207  |.  EB 02         |jmp     short 0040120B
    00401209  |>  2C 30         |sub     al, 30
    0040120B  |>  8D4E FF       |lea     ecx, [esi-1]
    0040120E  |.  83E0 0F       |and     eax, 0F                         ;  and 0F 取字节
    00401211  |.  C1E1 02       |shl     ecx, 2
    00401214  |.  D3E0          |shl     eax, cl
    00401216  |.  03D8          |add     ebx, eax
    00401218  |.  47            |inc     edi
    00401219  |.  4E            |dec     esi
    0040121A  |>  0BF6           or      esi, esi
    0040121C  |.^ 75 D9         \jnz     short 004011F7
    0040121E  |.  8BC3          mov     eax, ebx
  
--------------------------------------------------------------------------------
【经验总结】
  其实一开始我以为放在什么文件夹下都可以。
  如果按照我的想法的话 用户名输到天上去也不够
  后来看到论坛上别的兄弟写出的注册机才发现 
  原来 Crackme输入的地方是用户名,而文件夹名称就是注册码了。
  这才恍然大悟.原来可以这样变通的...
  
  1.将输入序列号的ascii码相加 再xor磁盘序号 得到 D1
  2.获取软件目录的后八位字符 s 算出一个数 D2
    D1 != D2 序列号无效
   
  以文件夹做注册码的话只要根据d2算出文件夹的名称就可以了
  再看下获取软件目录的后八位字符 s 算出一个数 D2 的算法
  写成passcal代码如下
  function Calc(Value: string) : DWORD;
   var
     i,k : Integer;
     p : DWORD;
   begin
     Result := 0;   
     for i := 1 to Length(Value) do
     begin
       if Value[i] < 'A' then
       begin
          p := Ord(Value[i]) - Ord('0');
       end
       else
       begin
         p := Ord(Value[i]) - Ord('W');
       end;
       k := Length(Value) - (i-1) - 1;
       k := k shl 2;      
       p := p and $0F;
       p := p shl k;
  
       Result := Result + p;
     end;  
   end;
  
  这个算法其实就是把字符串转换成等量的数字
  所以只要 把ascii码相加 再xor磁盘序号 
  得到的数值转换成字符就是注册码了
  

  引用会员“yugung”的注册机代码如下
  
  #include <stdio.h>
  #include <string.h>
  #include <windows.h>
  
  int main(int argc, char* argv[])
  {
      char Name[33],SN[9]={0};
      int NameLen;
      long sum=0;
      unsigned long CdiskVolSN;
      printf("Input your Name:");
      scanf("%s",Name);
      NameLen=strlen(Name);
      if(NameLen>32)
      {
          printf("\nName Tooooooo Long\n" );
          return 1;
      }
      for(int i=0;i<NameLen;i++)
      {
          sum+=Name[i];
      }
      GetVolumeInformationA(
      "c:\\",
      0,0,
      &CdiskVolSN,
      0,0,0,0);
      sum^=CdiskVolSN;
      sprintf(SN,"%X",sum);
      printf("\nIn order to Pass the check,\nChange your Dir Name to: %s",SN);
  
      return 0;
  }
  
  
  
  
  
  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年02月05日 18:42:44


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

收藏
免费 7
支持
分享
最新回复 (2)
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
2
就是如你所说的,我也是一样犯了错误,害死了
2007-2-5 20:24
0
雪    币: 242
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
Originally posted by 流动的情感
【文章标题】: ty123 Crackme 5的分析
【文章作者】: atomy
【作者主页】: http://2lin.net
--------------------------------------------------------------------------------
【详细过程】
........


分析得很详细、条理清晰,建议置“精华”。

源代码解压密码:Blood is thicker than water

感谢:流动的情感、yugung、KAN等大侠关注!

Until next time!
2007-2-6 08:44
0
游客
登录 | 注册 方可回帖
返回
//