首页
社区
课程
招聘
新手请教一个Crackme,实在没看懂
发表于: 2005-1-18 00:03 6258

新手请教一个Crackme,实在没看懂

2005-1-18 00:03
6258
下载了一个流行时代整理的密界文集,资料丰富。其中有个CRACKME练习表,以为找到入门的好材料,准备一个个练下去。但看了以后实在不明白为什么会这样或那样,发帖请教大家。
CrackMe之chap204 破解分析

【破文标题】 CrackMe之chap204 破解分析

【破文作者】 weiyi75[Dfcg][D.4S]

【作者邮箱】 [email]weiyi75@sohu.com[/email]

【作者主页】 Dfcg官方大本营、龙族联盟论坛

【使用工具】 peid,W32Dasm,olldbg,Keymake

【破解平台】 Win2000/XP

【软件名称】 chap204

【软件大小】 24KB
  
【下载地址】 本地下载

【编程语言】 Microsoft Visual C++ 6.0
         
【软件简介】 加密和解密第一版第二章第四个CrackMe。

【破解目的】 从头学起,打好基础。
   
【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享:)

------------------------------------------------------------

首先 Peid 检测程序编程语言是Microsoft Visual C++ 6.0,运行程序。

没输入用户名提示

"User Name must have at least 5."

错误注册码提示

"Incorrect!!, Try Again."

用W32Dasm查找字符参考。

于是为OD的动态跟踪找到下面一段代码。

* Reference To: MFC42.Ordinal:0C19, Ord:0C19h
                                  |
:00401565 E820080000              Call 00401D8A
:0040156A 8D4DEC                  lea ecx, dword ptr [ebp-14]
:0040156D E8DE020000              call 00401850
:00401572 8945E4                  mov dword ptr [ebp-1C], eax
:00401575 837DE405                cmp dword ptr [ebp-1C], 00000005
:00401579 7D43                    jge 004015BE
:0040157B 6A40                    push 00000040

* Possible StringData Ref from Data Obj ->"CrackMe"
                                  |
:0040157D 6820404000              push 00404020

* Possible StringData Ref from Data Obj ->"User Name must have at least 5 "
                                        ->"characters."
..................................................................

我们切换到OD里面。

任意填入

用户

David

序列号

12345

00401551  |.  E8 34080000   call <jmp.&MFC42.#3097_?GetDlgItemTextA@>
00401556  |.  8D4D E8       lea ecx, dword ptr ss:[ebp-18]  //读取用户名 David
00401559  |.  51            push ecx
0040155A  |.  68 E9030000   push 3E9
0040155F  |.  8B8D 40FEFFFF mov ecx, dword ptr ss:[ebp-1C0]
00401565  |.  E8 20080000   call <jmp.&MFC42.#3097_?GetDlgItemTextA@>
0040156A  |.  8D4D EC       lea ecx, dword ptr ss:[ebp-14] //读取注册码123456789
0040156D  |.  E8 DE020000   call chap204.00401850
00401572  |.  8945 E4       mov dword ptr ss:[ebp-1C], eax //eax=5=用户名位数
00401575  |.  837D E4 05    cmp dword ptr ss:[ebp-1C], 5 //比较姓名是否大于等于5个字符。
00401579  |.  7D 43         jge short chap204.004015BE
0040157B  |.  6A 40         push 40
0040157D  |.  68 20404000   push chap204.00404020                    ;  ASCII "CrackMe"
00401582  |.  68 28404000   push chap204.00404028                    ;  ASCII "User Name must have at least 5 characters."  //提示用户名必需是5个字符。
00401587  |.  8B8D 40FEFFFF mov ecx, dword ptr ss:[ebp-1C0]
0040158D  |.  E8 F2070000   call <jmp.&MFC42.#4224_?MessageBoxA@CWnd>
00401592  |.  C645 FC 01    mov byte ptr ss:[ebp-4], 1
00401596  |.  8D4D DC       lea ecx, dword ptr ss:[ebp-24]
00401599  |.  E8 C2070000   call <jmp.&MFC42.#800_??1CString@@QAE@XZ>
0040159E  |.  C645 FC 00    mov byte ptr ss:[ebp-4], 0
004015A2  |.  8D4D E8       lea ecx, dword ptr ss:[ebp-18]
004015A5  |.  E8 B6070000   call <jmp.&MFC42.#800_??1CString@@QAE@XZ>
004015AA  |.  C745 FC FFFFF>mov dword ptr ss:[ebp-4], -1
004015B1  |.  8D4D EC       lea ecx, dword ptr ss:[ebp-14]
004015B4  |.  E8 A7070000   call <jmp.&MFC42.#800_??1CString@@QAE@XZ>
004015B9  |.  E9 F9010000   jmp chap204.004017B7
004015BE  |>  C745 E0 00000>mov dword ptr ss:[ebp-20], 0  //ebp-20=0,这个程序的算法比较麻烦,准备好纸笔记录每次寄存器等值,详细见标签1。
004015C5  |.  EB 09         jmp short chap204.004015D0
004015C7  |>  8B55 E0       /mov edx, dword ptr ss:[ebp-20] //edx=ebp-20=0(开始记数n)
004015CA  |.  83C2 01       |add edx, 1  //edx=edx+1=1
004015CD  |.  8955 E0       |mov dword ptr ss:[ebp-20], edx   //记数n=edx
004015D0  |>  8B45 E0        mov eax, dword ptr ss:[ebp-20]  //eax=记数n
004015D3  |.  3B45 E4       |cmp eax, dword ptr ss:[ebp-1C] //eax与姓名长度比较
004015D6  |.  7D 42         |jge short chap204.0040161A    //大于等于就跳走。
004015D8      8B4D E0       |mov ecx, dword ptr ss:[ebp-20] //ecx=记数n
004015DB  |.  51            |push ecx                                ; /Arg1
004015DC  |.  8D4D EC       |lea ecx, dword ptr ss:[ebp-14]          ; |
004015DF  |.  E8 1C030000   |call chap204.00401900                   ; \chap204.00401900
004015E4  |.  0FBED0        |movsx edx, al  //取用户名第0位,44('D')
004015E7      8B45 F0       |mov eax, dword ptr ss:[ebp-10] //注册码将起始值81276345放入eax,地址ebp-10将一直保存注册码。
004015EA  |.  03C2          |add eax, edx //edx=eax+edx  //就是 81276345+44('d')=81276389
004015EC  |.  8945 F0       |mov dword ptr ss:[ebp-10], eax  //保存结果。
004015EF  |.  8B4D E0       |mov ecx, dword ptr ss:[ebp-20] //ecx=记数n
004015F2  |.  C1E1 08       |shl ecx, 8  SHL    SHl 逻辑左移 这个命令不是很理解

0 SHL 8 =0

1 SHL 8 =100   //感觉就是*100一样。

2 SHL 8 =200

004015F5  |.  8B55 F0       |mov edx, dword ptr ss:[ebp-10]
004015F8  |.  33D1          |xor edx, ecx  //edx=ecx xor edx
004015FA  |.  8955 F0       |mov dword ptr ss:[ebp-10], edx   //保存结果。
004015FD  |.  8B45 E0       |mov eax, dword ptr ss:[ebp-20]  //eax=记数n
00401600  |.  83C0 01       |add eax, 1  eax=eax+1=1
00401603  |.  8B4D E4       |mov ecx, dword ptr ss:[ebp-1C]  ecx=5=姓名长度。
00401606  |.  0FAF4D E0     |imul ecx, dword ptr ss:[ebp-20] ecx=ecx*记数n
0040160A  |.  F7D1          |not ecx  //not ecx 取反
0040160C  |.  0FAFC1        |imul eax, ecx  //eax=eax*ecx
0040160F  |.  8B55 F0       |mov edx, dword ptr ss:[ebp-10]   //eax=ebp-10
00401612  |.  0FAFD0        |imul edx, eax  //edx=edx*eax
00401615  |.  8955 F0       |mov dword ptr ss:[ebp-10], edx  //保存结果。
00401618  |.^ EB AD         \jmp short chap204.004015C7  //循环。
0040161A  |>  8B45 F0       mov eax, dword ptr ss:[ebp-10] //循环完毕的ebp-10即是真码

eax=D6AA35BC

0040161D  |.  50            push eax
0040161E  |.  68 54404000   push chap204.00404054                    ;  ASCII "%lu"
00401623  |.  8D4D DC       lea ecx, dword ptr ss:[ebp-24]
00401626  |.  51            push ecx
00401627  |.  E8 52070000   call <jmp.&MFC42.#2818_?Format@CString@@>
0040162C  |.  83C4 0C       add esp, 0C  //格式转换  D6AA35BC to 3601479100
0040162F  |.  8D4D DC       lea ecx, dword ptr ss:[ebp-24]
00401632  |.  E8 79020000   call chap204.004018B0
00401637  |.  50            push eax                                 ; /Arg1
00401638  |.  8D4D E8       lea ecx, dword ptr ss:[ebp-18]           ; |
0040163B  |.  E8 80020000   call chap204.004018C0   //判断是否注册正确。
00401640  |.  85C0          test eax, eax  //eax=0 就注册。
00401642  |.  0F85 FF000000 jnz chap204.00401747
00401648  |.  8D8D ACFEFFFF lea ecx, dword ptr ss:[ebp-154]
0040164E  |.  E8 19070000   call <jmp.&MFC42.#540_??0CString@@QAE@XZ>
00401653  |.  C645 FC 03    mov byte ptr ss:[ebp-4], 3
00401657  |.  6A 66         push 66
00401659  |.  8D8D ACFEFFFF lea ecx, dword ptr ss:[ebp-154]
0040165F  |.  E8 02070000   call <jmp.&MFC42.#4160_?LoadStringA@CStr>
00401664  |.  B9 07000000   mov ecx, 7
00401669  |.  BE 58404000   mov esi, chap204.00404058                ;  ASCII "Correct!!
                    "
............................................................................

标签1

第一次循环。                               第二次循环。

ecx=0                                      ecx=1

edx=44('D')                                edx=61('a')

ebp-10=81276345                            ebp-10=7ED89C77

eax=81276345                               eax=7ED89C77

eax=81276345+44=81276389                   eax=7ED89C77+61=7ED89CD8

ebp-10=81276389                            ebp-10=7ED89CD8
         
ecx=0                                      ecx=100

edx=812276389 xor 0 =81276389              edx=7ED89CD8  xor 100 =7ED89DD8

ebp-10=812276389                           ebp-10=7ED89DD8

eax=1                                      eax=2

ecx=5                                      ecx=5
           
ecx=0*5=000                                ecx=1*5=5

ecx=not 0=-1                               ecx=not 5=FFFFFFFA

eax=-1*1=-1                                eax=FFFFFFA*2=FFFFFFF4

edx=812276389*-1=7ED89C77                  edx=7ED89CD8*FFFFFFF4=0DD899E0

ebp-10=7ED89C77                            ebp-10=0DD899E0
  

第三次循环。                               第四次循环。

ecx=2                                      ecx=3

edx=76('V')                                edx=69('i')

ebp-10=0DD899E0                            ebp-10=37145CEA   

eax=0DD899E0                               eax=37145CEA   

eax=0DD899E0+76=0DD89A56                   eax=37145CEA+69=37145d53

ebp-10=0DD89A56                            ebp-10=37145d53
         
ecx=200                                    ecx=300

edx=0DD89A56 xor 200 =0DD89856             edx=37145d53  xor 300 =37145E53

ebp-10=0DD89856                            ebp-10=37145E53

eax=3                                      eax=4

ecx=5                                      ecx=5
           
ecx=2*5=A                                  ecx=3*5=F

ecx=not A=FFFFFFF5                         ecx=not F=FFFFFFF0

eax=FFFFFF5*3=FFFFFFDF                     eax=FFFFFFA*2=FFFFFF4

edx=0DD89856 *FFFFFFDF=37145CEA            edx=37145E53*FFFFFFF4=3AE86B40

ebp-10=37145CEA                            ebp-10=3AE86B40

第五次循环。

ecx=4

edx=64('d')

ebp-10=3AE86B40

eax=3AE86B40  

eax=3AE86B40+64=3AE86BA4

ebp-10=3AE86BA4
         
ecx=400

edx=3AE86BA4  xor 400 =3AE86FA4

ebp-10=3AE86FA4

eax=5

ecx=5
           
ecx=4*5=14

ecx=not 14=FFFFFFEB

eax=FFFFFEB*5=FFFFFF97

edx=3AE86FA4*FFFFFF97=D6AA35BC

ebp-10=D6AA35BC

算法总结,我都弄糊涂了。

N=0

{812276345(基值)+用户名第一位(16进制)} Xor (第N位*100)  //A部分

Not[(第N位)*总位数]*(第N位+1)   //B部分

A*B=C

循环累加结果C,N=4循环结束,算得真心烦。

【内存注册机】

中断地址

0040163B

中断次数 1

第一字节 E8

指令长度 5

内存方式寄存器 EAX

最后请看胜利截图

到这就不明白了

用W32Dasm查找字符参考。

于是为OD的动态跟踪找到下面一段代码。

* Reference To: MFC42.Ordinal:0C19, Ord:0C19h

我找到的和他不一样啊,请大家帮帮我附件:chap204.rar 附件:chap204.rar

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

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
是个很好的教程,具体算法没仔细看,用Ollydbg跟了下,找了个注册码。
Bistoury
2643289096
2005-1-18 00:51
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
能告诉我为什么吗?

用W32Dasm查找字符参考。

于是为OD的动态跟踪找到下面一段代码。

* Reference To: MFC42.Ordinal:0C19, Ord:0C19h

我不知道为什么能找到这个地方啊。

唉,明天要上班,睡觉先
2005-1-18 01:27
0
雪    币: 313
活跃值: (440)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
4
最初由 fallenmote 发布
能告诉我为什么吗?

用W32Dasm查找字符参考。

于是为OD的动态跟踪找到下面一段代码。
........


跟了下,不错的。有利于学习。。
一般我们就是看到错误提示的地方,看前面有跳走或者跳来,这样再进行跟踪阿,所以到OD里看前面的代码。
一般代码也有段落的,* Reference To: MFC42.Ordinal:0C19, Ord:0C19h相当于一个验证段落的开始。。。

俺是菜鸟。飞啊飞。。。
2005-1-18 11:19
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
楼上说的正解!!!

不过本例可以这样思考,用W32Dasm查找得到字符参考:
String Resource ID=00101: "&About Crack2..."
String Resource ID=00102: "Correct!!, Way To Go."
String Resource ID=00103: "Incorrect!!, Try Again."
"%lu"
"<BrD-SoB>                    "
"Correct way to go, You Got It."
"Correct!!                     "
"CrackMe"
"Incorrect!!, Try Again."
"User Name must have at least 5 "
看最后这句吧,按照正常的程序思路,如果用户名少于5个字符,给出这条提示,否则,根据用户名生成注册码,所以在这附近下中断应该可以在生成注册码之前拦截。

:00401575 837DE405                cmp dword ptr [ebp-1C], 00000005
:00401579 7D43                    jge 004015BE
:0040157B 6A40                    push 00000040

* Possible StringData Ref from Data Obj ->"CrackMe"
                                  |
:0040157D 6820404000              push 00404020

* Possible StringData Ref from Data Obj ->"User Name must have at least 5 "
                                        ->"characters."
                                  |
:00401582 6828404000              push 00404028
:00401587 8B8D40FEFFFF            mov ecx, dword ptr [ebp+FFFFFE40]

看到了吗
:00401579 7D43                    jge 004015BE
如果想看具体的注册算法,就仔细的从004015BE开始慢慢跟吧!!!:)
2005-1-18 12:13
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
谢谢指点,晚上回家再看看。
2005-1-18 13:02
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
请教【4nil】 & 【bistoury】,是不是有必要抱着书好好分析一下反汇编后的源码?熟悉一下16位汇编?
2005-1-18 20:30
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
需要什么知识就学什么知识,当然基础打的越牢越好!:p
2005-1-19 08:03
0
雪    币: 219
活跃值: (56)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
hcbajiao
26476880
没错,好文~~:D :D :D
2005-1-19 10:59
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
我的是PEDIY
3279041215我是用SMARTCHECK做的
2005-1-22 23:51
0
游客
登录 | 注册 方可回帖
返回
//