吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 15978|回复: 42
收起左侧

[原创] 新手教程:两个简单CrackMe的算法分析 适合初学算法的新手

[复制链接]
wellen 发表于 2009-4-23 22:22
本帖最后由 wellen 于 2009-4-26 21:45 编辑

新手教程:两个简单CrackMe的算法分析 适合初学算法的新手         

本来不想发这东西的感觉好像别人都不屑一看的 难度太低了 但感觉毕竟很多人还是和我一样的菜鸟就做个新

手教程来让广大和我一样菜的人学习下  两个CrackMe都论坛上翻到的地址在哪忘了 看了看难度很低 非常适合

初入算法分析又感觉迷茫的人学习!

1.第一个CarckMe      ArturDents CrackMe #2   
首先我们了解下CrackMe的概况 我们运行下 输入Name和Serial 点击Check It  没任何提示 Peid看了下无壳

ASM写的 了解大概后我们OD载入
第一步我们首先要确定关键位置 这一步至关重要! 我们可以下断点( BP GetDlgItemTextA等 )或者查找字

符串找到注册成功的部位断下  然后F9运行它 输入假码 Name:332211 Serial:wecwec
点击Checkit 可以看到断下了  

0013FBA8   00401113  /CALL 到 GetDlgItemTextA 来自 AD_CM#2.0040110E
0013FBAC   001E0348  |hWnd = 001E0348 ('ArturDents CrackMe #2',class='#32770')
0013FBB0   00000BB8  |ControlID = BB8 (3000.)
0013FBB4   00403080  |Buffer = AD_CM#2.00403080
0013FBB8   00000014  \Count = 14 (20.)

既然说要分析算法 我们就找找算法的位置 来到0040110E处 很明显这里是算法CALL内 取消断点

GetDlgItemTextA 然后断下4010FC 看下它的操作流程 我们F9运行下再点击Check It 断下后F8慢慢看

004010FC    55              push ebp
004010FD    8BEC            mov ebp,esp
004010FF    6A 14           push 14
00401101    68 80304000     push AD_CM#2.00403080                 ; ASCII "332211"
00401106    68 B80B0000     push 0BB8                             ; 上面压入用户名
0040110B    FF75 08         push dword ptr ss:[ebp+8]
0040110E    E8 77000000     call <jmp.&USER32.GetDlgItemTextA>    ; eax Name长度 下面算法用到
00401113    8BF0            mov esi,eax                           ; esi赋eax 长度
00401115    8D01            lea eax,dword ptr ds:[ecx]
00401117    83FE 05         cmp esi,5                             ; name长度和5比较
0040111A    7D 18           jge short AD_CM#2.00401134            ; 大于等于5则跳
0040111C    6A 40           push 40
0040111E    68 12304000     push AD_CM#2.00403012                 ; ASCII "ArturDents CrackMe#2"
00401123    68 44304000     push AD_CM#2.00403044                 ; ASCII "Your name must be at

least five characters long!"
00401128    FF75 08         push dword ptr ss:[ebp+8]
0040112B    E8 60000000     call <jmp.&USER32.MessageBoxA>
00401130    33C0            xor eax,eax
00401132    EB 40           jmp short AD_CM#2.00401174
00401134    6A 14           push 14
00401136    68 80324000     push AD_CM#2.00403280                 ; ASCII "wecwec"
0040113B    68 B90B0000     push 0BB9                             ; 上面压入我们的假码
00401140    FF75 08         push dword ptr ss:[ebp+8]
00401143    E8 42000000     call <jmp.&USER32.GetDlgItemTextA>
00401148    B8 80304000     mov eax,AD_CM#2.00403080              ; ASCII "332211"
0040114D    BB 80324000     mov ebx,AD_CM#2.00403280              ; ASCII "wecwec"
00401152    8BCE            mov ecx,esi                           ; 上面Name的长度
00401154    8A10            mov dl,byte ptr ds:[eax]              ; 逐一取Name每一位
00401156    2AD1            sub dl,cl                             ; 每一位减去 cl
00401158    3813            cmp byte ptr ds:[ebx],dl              ; 是否相等
0040115A    75 18           jnz short AD_CM#2.00401174            ; 不相等就结束 这里是爆破点
0040115C    40              inc eax
0040115D    43              inc ebx
0040115E  ^ E2 F4           loopd short AD_CM#2.00401154          ; 循环每一位运算后ECX-1 直到

ECX=1时结束
00401160    6A 40           push 40
00401162    68 12304000     push AD_CM#2.00403012                 ; ASCII "ArturDents CrackMe#2"
00401167    68 27304000     push AD_CM#2.00403027                 ; ASCII "Yeah, you did it!"
0040116C    FF75 08         push dword ptr ss:[ebp+8]
0040116F    E8 1C000000     call <jmp.&USER32.MessageBoxA>
00401174    C9              leave
00401175    C2 0400         retn 4

稍微看下马上就能看到爆破点 0040115A 接下来看看算法 0040110E 取得用户名长度 最后保存到esi 判断用户

名长度大于5就继续运行 00401154 开始就是真正的计算部分了 它怎么在算已经摆的很明了了 循环取Name每一

位的16进制ACSII码减去ECX  每循环一次ECX-1 0040115A处判断是否和假码每一位相等  直到ECX=1时跳出循环
弹出注册成功信息 332211 计算下就能得出  注册码  (33-6)(33-5)(32-4)(32-3)(31-2)(31-1) = -..//0  

既然知道了算法就可以开动写注册机了 这就作为作业留给大家了



2.Make in H&Y   记得好像是Z前辈发的   此程序相对上面个提高了点难度不过还是十分简单的 同样我们OD载

入  上面我们断GetDlgItemTextA 这次再试试
输入用户名332211 假码 53212214
同样断下了  断下后我们先看堆栈
0013FBB4   00401128  /CALL 到 GetDlgItemTextA 来自 Keygenme.00401123
0013FBB8   00080600  |hWnd = 00080600 ('Make in H&Y.',class='#32770')
0013FBBC   0000000C  |ControlID = C (12.)
0013FBC0   0040352C  |Buffer = Keygenme.0040352C
0013FBC4   00000100  \Count = 100 (256.)

来到00401123处 F8单步向下看

00401123  |.  E8 FA010000   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA
00401128  |.  33C0          xor     eax, eax
0040112A  |.  52            push    edx                              ; /IsSigned
0040112B  |.  68 2C344000   push    0040342C                         ; |pSuccess =

Keygenme.0040342C
00401130  |.  6A 0B         push    0B                               ; |ControlID = B (11.)
00401132  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
00401135  |.  E8 E2010000   call    <jmp.&user32.GetDlgItemInt>      ; \GetDlgItemInt
0040113A  |.  803D 2C344000>cmp     byte ptr [40342C], 0
00401141  |.  75 30         jnz     short 00401173

稍微分析下就能发现它检测了是否输入的为整数 如果用户名输入了非数字字符就字节跳向失败


继续向下看 很明显的关键跳 0040117A  |. /75 33         jnz     short 004011AF     这里可以爆破

那看样子 401173处就是关键算法call了 我们跟进去看看 算得多了可以看出它注册码的生成形式为A+B+C型不

过别急慢慢来

00401201  /$  8BD8          mov     ebx, eax                         ;  ebx 赋 ID
00401203  |.  8BC3          mov     eax, ebx                         ;  EAX = EBX
00401205  |.  B9 E4120000   mov     ecx, 12E4
0040120A  |.  33D2          xor     edx, edx
0040120C  |.  F7F1          div     ecx                              ;  eax余ecx
0040120E  |.  81F2 F1250B00 xor     edx, 0B25F1                      ;  结果代入进行异或运算
00401214  |.  8BDA          mov     ebx, edx                         ;  ebx 保存运算后结果
00401216  |.  8BC3          mov     eax, ebx                         ;  eax = ebx
00401218  |.  33D2          xor     edx, edx                         ;  edx 清零
0040121A  |.  52            push    edx
0040121B  |.  50            push    eax
0040121C  |.  8BD0          mov     edx, eax                         ;  edx 赋 731346
0040121E  |.  52            push    edx                              ; /<%d>
0040121F  |.  68 00304000   push    00403000                         ; |%d
00401224  |.  68 10304000   push    00403010                         ; |731346
00401229  |.  E8 D0000000   call    <jmp.&user32.wsprintfA>          ; \wsprintfA
0040122E  |.  83C4 0C       add     esp, 0C
00401231  |.  5A            pop     edx
00401232  |.  5A            pop     edx


这里可以算第一步了  我们慢慢来先理清下算法的思路 先是ID的16进制和12E4求余 计算后的结果再和0B25F1

进行异或运算 结果就是 B28D2 也就是 10进制的 731346

好了我们继续看下去

00401233  |.  8D05 10304000 lea     eax, dword ptr [403010]          ;  取第一位
00401239  |.  0FB605 103040>movzx   eax, byte ptr [403010]           ;  取第一位ASCII eax 37
00401240  |.  8D15 10304000 lea     edx, dword ptr [403010]          ;  取第一位
00401246  |.  0FB615 113040>movzx   edx, byte ptr [403011]           ;  取第二位ASCII edx 33
0040124D  |.  03C2          add     eax, edx                         ;  eax+edx
0040124F  |.  B9 05000000   mov     ecx, 5                           ;  ecx赋5
00401254  |.  33D2          xor     edx, edx                         ;  edx清0
00401256  |.  F7F1          div     ecx                              ;  eax余ecx
00401258  |.  80C2 04       add     dl, 4                            ;  edx+4
0040125B  |.  52            push    edx
0040125C  |.  50            push    eax
0040125D  |.  8BC2          mov     eax, edx                         ;  eax = 5
0040125F  |.  50            push    eax                              ; /<%d>
00401260  |.  68 03304000   push    00403003                         ; |%d
00401265  |.  68 10314000   push    00403110                         ; |5
0040126A  |.  E8 8F000000   call    <jmp.&user32.wsprintfA>          ; \wsprintfA
0040126F  |.  83C4 0C       add     esp, 0C
00401272  |.  5A            pop     edx
00401273  |.  5A            pop     edx

这里我们就算第二步 分析下看看  首先把第一步的运算结果搬过来 731346 取第一位的acsii码 37 然后再取

第二位的 acsii码 33  接着 两数相加 再余5 结果再加4 最后出来的是5  初次学的是不是感觉有点头晕呢 没

关系坚持下去因为胜利就在眼前了 !

00401274  |.  8D05 10304000 lea     eax, dword ptr [403010]
0040127A  |.  0FB605 123040>movzx   eax, byte ptr [403012]           ;  EAX 31
00401281  |.  8D15 10304000 lea     edx, dword ptr [403010]
00401287  |.  0FB615 133040>movzx   edx, byte ptr [403013]           ;  EDX 33
0040128E  |.  03C2          add     eax, edx                         ;  EAX 31+33
00401290  |.  B9 05000000   mov     ecx, 5                           ;  ECX 5
00401295  |.  33D2          xor     edx, edx                         ;  edx清零
00401297  |.  F7F1          div     ecx
00401299  |.  80C2 03       add     dl, 3                            ;  (initial cpu selection)
0040129C  |.  52            push    edx
0040129D  |.  50            push    eax
0040129E  |.  8BC2          mov     eax, edx
004012A0  |.  50            push    eax                              ; /<%d>
004012A1  |.  68 06304000   push    00403006                         ; |%d
004012A6  |.  68 10324000   push    00403210                         ; |3
004012AB  |.  E8 4E000000   call    <jmp.&user32.wsprintfA>          ; \wsprintfA

这是第三步 取 731346 第三位acsii码31     第四位acsii码 33 又是两位相加和5求余 结果再加3 最后出来

的是 3


最后看看最后的运算
004012B0  |.  83C4 0C       add     esp, 0C
004012B3  |.  68 10324000   push    00403210                     
004012B8  |.  68 10314000   push    00403110                     
004012BD  |.  68 10304000   push    00403010                       
004012C2  |.  68 09304000   push    00403009                     
004012C7  |.  68 10334000   push    00403310                       
004012CC  |.  E8 2D000000   call    <jmp.&user32.wsprintfA>        
004012D1  |.  83C4 14       add     esp, 14
004012D4  |.  68 10334000   push    00403310                     
004012D9  |.  68 2C354000   push    0040352C                     
004012DE  |.  E8 15000000   call    <jmp.&kernel32.lstrcmpA>     
004012E3  |.  5A            pop     edx
004012E4  |.  5A            pop     edx


可以看到把第一步 第二步 第三步的结果都加了起来 731346 + 5 + 3  也就是 73134653

用户名 332211 注册码 73134653 我们输入进去瞧瞧 注册成功了吧

最后我用最最通俗易懂的语言来概括下它的算法 别说这样你都看不懂

B25F1 的10进制 730609
12E4  的10进制   4836

&1 = (用户名 div 4836) xor 730609
&2 =((&1第一位ASCII + &1第二位ASCII ) div 5) +4

&3 =((&1第三位ASCII + &1第四位ASCII ) div 5) +3

Serial = &1 + &2 + &3

囧 最笨的表达方式 如果还看不懂那我就真的没办法了

第一次发这帖不知道写的格式对不对 = = 最后留给大家个作业 完成第一个和第二个CrackMe的KeyGen~~~

Keygenme.rar

5.41 KB, 下载次数: 91, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 1威望 +2 收起 理由
wgz001 + 2 谢谢

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| wellen 发表于 2009-4-23 22:25
难得发帖沙发当然自己做了
zapline 发表于 2009-4-23 22:56
本帖最后由 zapline 于 2009-4-23 22:59 编辑

板凳。。。。
Make in H&Y 都是xiaojiam(看雪ID)莱沙(吾爱ID)大侠的作品,专业研究CM的大牛
 楼主| wellen 发表于 2009-4-23 23:06
板凳。。。。
Make in H&Y 都是xiaojiam(看雪ID)莱沙(吾爱ID)大侠的作品,专业研究CM的大牛
zapline 发表于 2009-4-23 22:56
哇 拜拜[s:397]
mayl8822 发表于 2009-4-23 23:14
4# wellen


谢谢分享哦
冰封秋雪 发表于 2009-4-23 23:14
上面是什么我都看不懂啊!!唉!!!
wgz001 发表于 2009-4-23 23:18
学习算法   一直都入不了门   :'(
CHHSun 发表于 2009-4-24 10:32
算法我还没考虑,直接不去想。
ming_feiyang 发表于 2009-4-24 11:46
我也看看!
热火朝天 发表于 2009-4-24 11:55
支持一下楼主的好帖,学习学习
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-18 02:43

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表