破解者:tieji
破解时间:2001-11-28
破解工具:TRW2000 V1.23 W32dasm黄金版
作者主页:http://www.wjmshome.com
启动软件,弹出注册框,填入注册信息:
注册名:caoxinyu
注册码:5432112345 <----随便填
打开TRW2000,下断点bpx hmemcpy,点确定,被拦下。
按F10来到:
:00413887 E816540000 Call 00418CA2
:0041388C 8D8E001B0000 lea ecx, dword
ptr [esi+00001B00]
:00413892 E817C2FFFF call 0040FAAE
<=====关键的call,分析比较注册码,跟进
:00413897 85C0
test eax, eax <=====eax是否为零
:00413899 751E
jne 004138B9 <=====不为零,正确就跳[多经典!]
:0041389B 6A40
push 00000040
* Possible StringData Ref from Data Obj ->"warning"
|
:0041389D 68C4614200 push 004261C4
* Possible StringData Ref from Data Obj ->"注册码错误,请重新输入"
|
:004138A2 6820784200 push 00427820
:004138A7 8BCB
mov ecx, ebx
=============================================================================================
关键的cal:
* Referenced by a CALL at Addresses:
|:0040702B , :00413892
|
:0040FAAE B820B64100 mov eax,
0041B620
* Reference To: MSVCRT._EH_prolog, Ord:0042h
|
:0040FAB3 E858960000 Call 00419110
:0040FAB8 83EC2C
sub esp, 0000002C <==== esp-0x2c
:0040FABB 56
push esi <==== 保存esi
:0040FABC 57
push edi <==== 保存edi
:0040FABD 8B7D08
mov edi, dword ptr [ebp+08] <==== 将ebp+08的内容传给edi,即将
用户名caoxinyu所在的地址传给edi
:0040FAC0 33F6
xor esi, esi <====esi清零
:0040FAC2 8975EC
mov dword ptr [ebp-14], esi <====ebp-14处的内容清零
:0040FAC5 8B4FF8
mov ecx, dword ptr [edi-08] <====将用户名长度(本例为8)传给ecx
:0040FAC8 3BCE
cmp ecx, esi <====比较用户名长度是否为零
:0040FACA 0F84AD000000 je 0040FB7D
<====为零跳到0040FB7D (本例不为零不跳)
:0040FAD0 83F920
cmp ecx, 00000020 <====比较用户名长度是否为32位
:0040FAD3 7E03
jle 0040FAD8 <====小于32位就跳到0040FAD8
:0040FAD5 6A20
push 00000020 <====大于32位就将32给ecx
:0040FAD7 59
pop ecx <====既用户名长度截取前32位
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FAD3(C)
|
:0040FAD8 3BCE
cmp ecx, esi <====用户名长度与零比较
:0040FADA 7E13
jle 0040FAEF <====小于等于零就跳
:0040FADC 8D45C8
lea eax, dword ptr [ebp-38] <====eax装入ebp-38的地址
:0040FADF 2BF8
sub edi, eax <====edi-eax-->edi
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FAED(C)
|
:0040FAE1 8D4435C8 lea
eax, dword ptr [ebp+esi-38] <====eax装入ebp+esi-38的地址
:0040FAE5 46
inc esi <====esi加1
:0040FAE6 3BF1
cmp esi, ecx <====esi与ecx用户名长度比较
:0040FAE8 8A1407
mov dl, byte ptr [edi+eax] <====将用户名的一个字母传给dl
:0040FAEB 8810
mov byte ptr [eax], dl <====将用户名的一个字母放入eax所
在的地址中
:0040FAED 7CF2
jl 0040FAE1 <====循环将用户名caoxinyu依次放到eax所指的地址中
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FADA(C)
<====用户名长度小于等于零跳到这里
|
:0040FAEF 83F920
cmp ecx, 00000020 <==== 比较用户名长度是否为32位
:0040FAF2 53
push ebx <==== 保存ebx
:0040FAF3 7D2C
jge 0040FB21 <==== 大于等于32位跳
:0040FAF5 8D7DC8
lea edi, dword ptr [ebp-38] <====edi装入ebp-38所指的内容
:0040FAF8 8D45C8
lea eax, dword ptr [ebp-38] <====eax装入ebp-38所指的内容
即将放有caoxinyu处的地址-->edi,eax
:0040FAFB 4F
dec edi <====edi-1
:0040FAFC 2BC7
sub eax, edi <====eax-edi--->eax 即eax=0x1
:0040FAFE 8945F0
mov dword ptr [ebp-10], eax <====eax-->[ebp-10]
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FB1F(C)
|
:0040FB01 8A1C0F
mov bl, byte ptr [edi+ecx] <====将用户名的最后一个字母(本例为u)-->bl
:0040FB04 8D340F
lea esi, dword ptr [edi+ecx]<====esi装入u所在的地址
:0040FB07 0FB6C3
movzx eax, bl <====将u放入eax
:0040FB0A 99
cdq <====双字节扩展 edx为00000000
:0040FB0B F7F9
idiv ecx <====除ecx 即0x75/0x8 即eax中为0xE,edx中为0x5
:0040FB0D 8BD0
mov edx, eax <====eax-->edx 即edx为0xE
:0040FB0F 8AC3
mov al, bl <====bl--->al 即al=0x75
:0040FB11 F6E9
imul cl <====乘cl 即0x75*0x8=0x3A8
--->eax
:0040FB13 02D0
add dl, al <====dl+al-->dl 即0xE+0xA8=0xB6-->dl
:0040FB15 8B45F0
mov eax, dword ptr [ebp-10] <====[ebp-10]--->eax=0x1
:0040FB18 41
inc ecx <====ecx+1
:0040FB19 83F920
cmp ecx, 00000020 <====ecx与32比较,即用户名长度是否到了32位
:0040FB1C 881430
mov byte ptr [eax+esi], dl <====将0xB6放到用户名的最后一个字母
"u"的后面
:0040FB1F 7CE0
jl 0040FB01 <====用户名长度是不到32位就循环
注:上面这个循环是将用户名不到32位的补齐到32位,以用户名为caoxinyu为例计算如下:
第一次循环:
0x75/0x8=0xE
0x75*0x8=0xA8 因用al寄存器计算,故0x3A8-->0xA8
0xE+0xA8=0xB6
将计算所得的0xB6接到用户名caoxinyu的后面,变为:63616F78696E7975B6
第二次循环:
0xB6/0x9=0x14
0xB6*0x9=0x66
0x14+0x66=0x7A
将计算所得的0x7A再接到用户名的后面,变为:63616F78696E7975B67A
如此经过32-8次循环,补齐到32位的用户名为:
63616F78696E7975B67AD0021839220000000000000000000000000000000000
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FAF3(C)
<===========用户名长度大于等于32位跳到这里
|
:0040FB21 33F6
xor esi, esi
<====esi清零
:0040FB23 8975F0
mov dword ptr [ebp-10], esi <====ebp-10处内容清零
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FB59(C)
|
<======四次循环开始,为何是四次循环,见下面说明:
:0040FB26 8B45F0
mov eax, dword ptr [ebp-10] <====将ebp-10的内容-->eax
:0040FB29 806435E800 and byte
ptr [ebp+esi-18], 00 <====和0x00与
:0040FB2E 8D4C35E8 lea
ecx, dword ptr [ebp+esi-18]<====ebp+esi-18的地址-->ecx
:0040FB32 6A04
push 00000004 <====
:0040FB34 99
cdq
<====双字节扩展
:0040FB35 5B
pop ebx <====将0x4放入ebx
:0040FB36 33FF
xor edi, edi <====edi清零
:0040FB38 F7FB
idiv ebx <====eax/0x4
:0040FB3A 8A19
mov bl, byte ptr [ecx] <====bl=0
:0040FB3C 8D4405C8 lea
eax, dword ptr [ebp+eax-38] <====将ebp+eax-38的地址-->eax
即ebp-38为用户名所在的地方,ebp+eax-38 就是用户名所在的地址+eax
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FB49(C)
|
:0040FB40 8A1438
mov dl, byte ptr [eax+edi] <====将eax+edi所在的内容-->dl
:0040FB43 32DA
xor bl, dl
<====bl^dl-->bl
:0040FB45 47
inc edi
<====edi+1
:0040FB46 83FF08
cmp edi, 00000008 <====循环8次
:0040FB49 7CF5
jl 0040FB40
:0040FB4B 8345F020 add
dword ptr [ebp-10], 00000020 <====加20
:0040FB4F 46
inc esi
<====esi+1
:0040FB50 817DF080000000 cmp dword ptr [ebp-10],
00000080 <====与0x80比较
:0040FB57 8819
mov byte ptr [ecx], bl <====bl-->[ecx]
:0040FB59 7CCB
jl 0040FB26 <====循环,因每次加20,加到80,所以循环四次
注:上面有两个循环,循环中套循环
因已得到32位的用户名16进制为:63616F78696E7975B67AD0021839220000000000000000000000000000000000
第一次循环:(第一个字母c , 16进制为:63)
0x63^0x61=0x2
0x2^0x6F=0x6D
如此循环8次最后得到0x1E
第二次循环:(第九个字母16进制为:B6)
0xB6^0x7A=0xCC
0xCC^0xD0=0x1C
如此循环8次最后得到0x1D
第三次循环:同理最后得到00
第四次循环:同理最后得到00
将四次循环所得的结果反过来看00001D1E即为正确的注册码,不过要将他转换为十进制数.
:0040FB5B 8B45EC
mov eax, dword ptr [ebp-14] <====[ebp-14]-->eax
:0040FB5E 6A03
push 00000003
<====
:0040FB60 59
pop ecx
<====3放入ecx
:0040FB61 5B
pop ebx
<====还原ebx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FB71(C)
|
:0040FB62 0FB6540DE8 movzx edx,
byte ptr [ebp+ecx-18]
:0040FB67 03C2
add eax, edx <=====eax+edx-->eax
:0040FB69 85C9
test ecx, ecx
:0040FB6B 7406
je 0040FB73 <====ecx为零跳
:0040FB6D C1E008
shl eax, 08 <====左移8位
:0040FB70 49
dec ecx <====ecx-1
:0040FB71 79EF
jns 0040FB62
<=====上面的循环将正确的注册码放入eax中
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FB6B(C)
|
:0040FB73 2B450C
sub eax, dword ptr [ebp+0C] <====将eax中正确的注册码与输入的假
注册码相减
:0040FB76 F7D8
neg eax <====取eax二补码
:0040FB78 1BC0
sbb eax, eax <====借位减
:0040FB7A 40
inc eax <====eax+1 若为0表示注册码错误,0x1表示正确
:0040FB7B 8BF0
mov esi, eax <====eax-->esi 注册标记保存
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040FACA(C)
<====用户名长度为零跳到这里
|
:0040FB7D 834DFCFF or
dword ptr [ebp-04], FFFFFFFF
:0040FB81 8D4D08
lea ecx, dword ptr [ebp+08]
* Reference To: MFC42.Ordinal:0320, Ord:0320h
|
:0040FB84 E8E78F0000 Call 00418B70
:0040FB89 8B4DF4
mov ecx, dword ptr [ebp-0C]
:0040FB8C 8BC6
mov eax, esi <====esi--->eax 注册标记传给eax
:0040FB8E 5F
pop edi
:0040FB8F 5E
pop esi
:0040FB90 64890D00000000 mov dword ptr fs:[00000000],
ecx
:0040FB97 C9
leave
:0040FB98 C20800
ret 0008
写得真累,希望能给初学者有帮助,也望各位大侠指教........
- 标 题:文件密使2.6注册码分析详解 (11千字)
- 作 者:[tieji]
- 时 间:2001-11-30 8:52:49
- 链 接:http://bbs.pediy.com