首页
社区
课程
招聘
[原创]找到一个很适合新手的crackme(算法分析+注册机)
发表于: 2006-7-22 00:34 6522

[原创]找到一个很适合新手的crackme(算法分析+注册机)

2006-7-22 00:34
6522

【文章标题】: 找到一个很适合新手的crackme(算法分析+注册机)
【文章作者】: qwgboy2000
【作者邮箱】: qwgboy2000@126.com
【作者主页】: mland.icpcn.com
【作者QQ号】: 27141459
【软件名称】: Key-Crackme2.exe
【软件大小】: 207K
【下载地址】: 自己搜索下载
【加壳方式】: 无
【保护方式】: name、Serial
【编写语言】: MASM32 / TASM32
【使用工具】: PEiD、OD、windows自带计算器
【操作平台】: Windows XP
【软件介绍】: 从www.crackmes.de上找的一个Crackme
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  首先用PEiD看看,无壳、MASM32/TASM32写的,Ctrl+N发现了USER32.GetDlgItemTextA
  于是Command:bpx getdlgitemtexta
  按F9运行程序,输入name、Serial
  这里我name=qwgboy2000、Serial=7878781234
  点击确定,来到以下部分:
  
  004012B1  |.  6A 40         push    40                    ; /Count = 40 (64.)
  004012B3  |.  68 38304000   push    00403038              ; |Buffer = Key-Crac.00403038
  004012B8  |.  6A 6A         push    6A                    ; |ControlID = 6A (106.)
  004012BA  |.  FF75 08       push    dword ptr [ebp+8]     ; |hWnd
  004012BD  |.  E8 08010000   call    <jmp.&USER32.GetDlgIt>; \GetDlgItemTextA
  004012C2  |.  83F8 00       cmp     eax, 0                ;  判断name长度是否为0
  004012C5  |.  74 18         je      short 004012DF        ;  为0,则出错提示
  004012C7  |.  6A 40         push    40                    ; /Count = 40 (64.)
  004012C9  |.  68 38314000   push    00403138              ; |Buffer = Key-Crac.00403138
  004012CE  |.  6A 6B         push    6B                    ; |ControlID = 6B (107.)
  004012D0  |.  FF75 08       push    dword ptr [ebp+8]     ; |hWnd
  004012D3  |.  E8 F2000000   call    <jmp.&USER32.GetDlgIt>; \GetDlgItemTextA
  004012D8  |.  83F8 00       cmp     eax, 0                ;  判断Serial长度是否为0
  004012DB  |.  74 02         je      short 004012DF        ;  为0,则出错提示
  004012DD  |.  EB 17         jmp     short 004012F6        ;  跳往算法部分了 :)
  004012DF  |>  6A 00         push    0                     ; /Style = MB_OK|MB_APPLMODAL
  004012E1  |.  68 62344000   push    00403462              ; |Title = "Key/CrackMe #2   "
  004012E6  |.  68 00304000   push    00403000              ; |Text = "    Please Fill in 1 more Char!!"
  004012EB  |.  6A 00         push    0                     ; |hOwner = NULL
  004012ED  |.  E8 FC000000   call    <jmp.&USER32.MessageB>; \MessageBoxA
  004012F2  |.  C9            leave
  004012F3  |.  C2 1000       retn    10
  004012F6  |>  68 38304000   push    00403038              ; /String = ""
  004012FB  |.  E8 30010000   call    <jmp.&KERNEL32.lstrle>; \lstrlenA
  00401300  |.  33F6          xor     esi, esi
  00401302  |.  8BC8          mov     ecx, eax              ;  为进行次数是name长度的循环做好铺垫
  00401304  |.  B8 01000000   mov     eax, 1                ;  eax=1
  00401309  |>  8B15 38304000 /mov     edx, [403038]        ;  edx=name
  0040130F  |.  8A90 37304000 |mov     dl, [eax+403037]     ;  dl=name的第一位;以后依次往后取
  00401315  |.  81E2 FF000000 |and     edx, 0FF             ;  edx=name的第1位;以后依次往后取
  0040131B  |.  8BDA          |mov     ebx, edx             ;  ebx=edx
  0040131D  |.  0FAFDA        |imul    ebx, edx             ;  ebx=ebx*edx
  00401320  |.  03F3          |add     esi, ebx             ;  esi=esi+ebx
  00401322  |.  8BDA          |mov     ebx, edx             ;  ebx=edx
  00401324  |.  D1FB          |sar     ebx, 1               ;  ebx=ebx>>1
  00401326  |.  03F3          |add     esi, ebx             ;  esi=esi+ebx
  00401328  |.  2BF2          |sub     esi, edx             ;  esi=esi-edx
  0040132A  |.  40            |inc     eax                  ;  eax=eax+1
  0040132B  |.  49            |dec     ecx                  ;  ecx=ecx-1;准备下次循环
  0040132C  |.^ 75 DB         \jnz     short 00401309       ;  开始下次循环;直到ecx=0,跳出循环
  0040132E  |.  56            push    esi                   ;  esi=name的每个字符的(ASCII码平方+除以2-本身)累加,压栈准备与

Serial运算以后的结果比较
  0040132F  |.  68 38314000   push    00403138
  00401334  |.  E8 4A000000   call    00401383              ;  这里是对于Serial运算部分;跟进去看看(见下一大段)
  00401339  |.  5E            pop     esi                   ;  取出name运算以后的内容放入esi
  0040133A  |.  3BC6          cmp     eax, esi
  0040133C  |.  75 15         jnz     short 00401353        ;  暴破跳转点
  0040133E  |.  6A 00         push    0                     ; /Style = MB_OK|MB_APPLMODAL
  00401340  |.  68 62344000   push    00403462              ; |Title = "Key/CrackMe #2   "
  00401345  |.  68 B8344000   push    004034B8              ; |Text = " Good Job, I Wish You the Very Best"
  0040134A  |.  6A 00         push    0                     ; |hOwner = NULL
  0040134C  |.  E8 9D000000   call    <jmp.&USER32.MessageB>; \MessageBoxA
  00401351  |.  EB 13         jmp     short 00401366
  00401353  |>  6A 00         push    0                     ; /Style = MB_OK|MB_APPLMODAL
  00401355  |.  68 62344000   push    00403462              ; |Title = "Key/CrackMe #2   "
  0040135A  |.  68 86344000   push    00403486              ; |Text = " You Have Enter A Wrong Serial, Please Try Again "
  0040135F  |.  6A 00         push    0                     ; |hOwner = NULL
  00401361  |.  E8 88000000   call    <jmp.&USER32.MessageB>; \MessageBoxA
  00401366  |>  EB 15         jmp     short 0040137D
  00401368  |>  FF75 14       push    dword ptr [ebp+14]    ; /lParam
  0040136B  |.  FF75 10       push    dword ptr [ebp+10]    ; |wParam
  0040136E  |.  FF75 0C       push    dword ptr [ebp+C]     ; |Message
  00401371  |.  FF75 08       push    dword ptr [ebp+8]     ; |hWnd
  00401374  |.  E8 3F000000   call    <jmp.&USER32.DefWindo>; \DefWindowProcA
  00401379  |.  C9            leave
  0040137A  |.  C2 1000       retn    10
  0040137D  |>  33C0          xor     eax, eax
  0040137F  |.  C9            leave
  00401380  \.  C2 1000       retn    10
  
  
  这里是对于Serial运算部分;接上面那个CALL跟进来的
  00401383  /$  55            push    ebp
  00401384  |.  8BEC          mov     ebp, esp
  00401386  |.  FF75 08       push    dword ptr [ebp+8]     ; /String
  00401389  |.  E8 A2000000   call    <jmp.&KERNEL32.lstrle>; \lstrlenA
  0040138E  |.  53            push    ebx
  0040138F  |.  33DB          xor     ebx, ebx              ;  ebx=0
  00401391  |.  8BC8          mov     ecx, eax              ;  ecx=eax,即准备循环次数为Serial长度
  00401393  |.  8B75 08       mov     esi, [ebp+8]          ;  esi=Serial
  00401396  |>  51            /push    ecx                  ;  ecx进栈,因为下面有2个循环要用
  00401397  |.  33C0          |xor     eax, eax             ;  eax=0
  00401399  |.  AC            |lods    byte ptr [esi]       ;  字节串读取:AL←DS:[SI],SI←SI+/-1
  0040139A  |.  83E8 30       |sub     eax, 30              ;  eax=eax-30
  0040139D  |.  49            |dec     ecx                  ;  ecx=ecx-1
  0040139E  |.  74 05         |je      short 004013A5       ;  if ecx=0;跳转
  004013A0  |>  6BC0 0A       |/imul    eax, eax, 0A        ;  eax=eax*0A
  004013A3  |.^ E2 FB         |\loopd   short 004013A0      ;  对于一个字符的小循环,ecx=ecx-1
  004013A5  |>  03D8          |add     ebx, eax             ;  ebx=ebx+eax
  004013A7  |.  59            |pop     ecx                  ;  ecx出栈,准备下一个字符的大循环
  004013A8  |.^ E2 EC         \loopd   short 00401396       ;  大循环,ecx=ecx-1
  004013AA  |.  8BC3          mov     eax, ebx              ;  eax=ebx,Serial运算完以后的结果放进去,准备与name运算以后的结果

进行比较
  004013AC  |.  5B            pop     ebx
  004013AD  |.  C9            leave
  004013AE  \.  C2 0400       retn    4
  
  对Serial这部分的算法看着觉得有些眼熟。
  仔细看看发现总是有与A即10相乘的运算,倒过来一看不就是除以10取余吗?
  噢!原来逆反运算明明就是16进制换算成10进制的嘛。
  GAME OVER
  
  
--------------------------------------------------------------------------------
【经验总结】
  这个Crackme首先对name部分进行运算
  运算方法是:1、用每个字符进行乘方得到一个数,我们假装它为num1
              2、用每个字符右移1位得到一个数,假装是num2
              3、num1+num2-这个字符
              4、所有的字符以上进行运算以后累加起来得到一个数
  我这里name=qwgboy2000
  那么这里是用它们的ASCII码进行运算得到一个16进制数,我的运算以后的数为1448D
  
  Serial的运算部分逆算法是把一个数转化为10进制;
  那么把我的name运算以后的结果1448D转化为10进制以后就是Serial了,用计算器看一下我的Serial是83085

  即:  name=qwgboy2000
        Serial=83085
  
  注册机如下:

  #include"string.h"
  #include"stdio.h"

  main()
  {
   
   char name[32];
   int i;
   int Serial=0;
   
   printf("please input your name:");
   scanf("%s",name);
   i=strlen(name);
   
   for(i;i>=1;i--)
   Serial=Serial+((name[i-1]*name[i-1])+((int)name[i-1]>>1)-name[i-1]);

   printf("your Serial is:");
   printf("%d",Serial);
   
  }
  以上程序VC6.0调试通过  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2006年07月22日 0:01:27


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (8)
雪    币: 338
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
下载来试一下!!
2006-7-22 18:37
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢,你的头像是从冒险岛里截下来的吗?
2006-7-22 19:00
0
雪    币: 309
活跃值: (15)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
4
多谢~~
很精彩的文章,适合偶这样的新手~~
2006-7-23 08:10
0
雪    币: 151
活跃值: (66)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
不错.
最后一位比较.
不过运算起来感觉还是有些麻烦~~
昏~
2006-8-1 15:18
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
试过了,感觉不错呀
2006-8-4 09:30
0
雪    币: 0
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
7
试一下!!!
2006-8-5 00:29
0
雪    币: 174
活跃值: (10)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
8
靠,分析的太麻烦,没有必要的部分太多,关键部分讲得也不清楚,
2006-8-5 08:25
0
雪    币: 195
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
学习中...
2006-8-6 16:36
0
游客
登录 | 注册 方可回帖
返回
//