注册 Mp3 Tag Clinic 1.50
by Fpc[CCG]/6767[BCG] @2001/08
tools: si, frogice
level: 1.5
[Begin]
这是在BCG论坛上请求破解的,难度不大,但我是在放弃又拣起才给破掉的。破解真是费力不讨好 :(
基本上这个软件是不利于cracker的:频繁S机。S了十几次之后终于把它的注册机制找到,下面是过程。
以下简称MTC,由aspack压缩,用craspr脱壳会有一个函数找不到。算了,追出注册码是目标。
如果运气好,MTC运行后没S掉,会出现一个带注册按纽的‘关于’窗口。单击‘注册’到注册窗口,有两个输入框:上面的一个是根据硬件算出来的(实际上是计算机名和Windows的序列号),下面的是要求你输入注册码。好了,输入:1236549870,^D到SI,设断点:bpx
hmemcpy。回来,点确定,被拦到,Good!
按几次F12直到你见到下面的代码:
:004B24B6 8D55F4
lea edx, dword ptr [ebp-0C]
:004B24B9 8B83D4020000 mov eax, dword
ptr [ebx+02D4]
:004B24BF E81833F8FF call 004357DC
<- 这个是读取输入的注册码(Irc)
:004B24C4 8B55F4
mov edx, dword ptr [ebp-0C] <-
返回处在此
:004B24C7 B83C565700 mov eax,
0057563C
:004B24CC E8FB18F5FF call 00403DCC
<- 复制到0x57563C处
:004B24D1 66837DFA01 cmp word
ptr [ebp-06], 0001
:004B24D6 0F85D1020000 jne 004B27AD
<- 不会跳
:004B24DC A1A4625700 mov eax,
dword ptr [005762A4]
:004B24E1 C70005000000 mov dword ptr
[eax], 00000005
:004B24E7 A13C565700 mov eax,
dword ptr [0057563C]
:004B24EC E8071BF5FF call 00403FF8
<- 取Irc长度
:004B24F1 83F810
cmp eax, 00000010
<- 不能大于16
:004B24F4 7D11
jge 004B2507
:004B24F6 B83C565700 mov eax,
0057563C <-
eax指向Irc
:004B24FB BA7CDE0000 mov edx,
0000DE7C <-
这个是常量
:004B2500 E813AFFAFF call 0045D418
<- **!!** 这个是核心了;若返回的eax值小于等于0或大于0x1fff则注册失败
:004B2505 8BF8
mov edi, eax
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004B24F4(C)
|
:004B2507 85FF
test edi, edi <-
检查返回值
:004B2509 0F8E55020000 jle 004B2764
<- 这里不能去
:004B250F 81FF00200000 cmp edi, 00002000
:004B2515 0F8D49020000 jnl 004B2764
... ...(不重要了,省略)
在:004B2500 换F8,追进 call 0045D418,看MTC是如何计算注册码。
* Referenced by a CALL at Addresses:
|... ...
|
:0045D418 55
push ebp
:0045D419 8BEC
mov ebp, esp
:0045D41B 83C4BC
add esp, FFFFFFBC
... ...(初始化)
:0045D453 8D0568D44500 lea eax, dword
ptr [0045D468]
:0045D459 83C00A
add eax, 0000000A
:0045D45C 8905A8785700 mov dword ptr
[005778A8], eax
:0045D462 EB04
jmp 0045D468 <-
**向下跳走
:0045D464 5F
pop edi
:0045D465 5E
pop esi
:0045D466 5B
pop ebx
:0045D467 C3
ret
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0045D462(U)
|
:0045D468 837DFCFF cmp
dword ptr [ebp-04], FFFFFFFF
:0045D46C 0F84D6010000 je 0045D648
:0045D472 E8159EFAFF call 0040728C
:0045D477 83C02D
add eax, 0000002D
:0045D47A A384785700 mov dword
ptr [00577884], eax
:0045D47F E8089EFAFF call 0040728C
:0045D484 3B0584785700 cmp eax, dword
ptr [00577884]
:0045D48A 0F87B8010000 ja 0045D648
<- 这里不跳,不重要
:0045D490 33F6
xor esi, esi
:0045D492 E891FCFFFF call 0045D128
<- 这里会生成机器号(Hwn),并以立即数的形式保存在eax中
<- 规则是:将在注册窗口看到的机器号的前8个字符(当然不包括‘-’)变为立即数
<- 比如:机器号=AC7D-680F-53,那么eax=0xAC7D680F
:0045D497 8945F8
mov dword ptr [ebp-08], eax
<- 将Hwn保存下来,以后用到
:0045D49A A114625700 mov eax,
dword ptr [00576214]
:0045D49F 8B55FC
mov edx, dword ptr [ebp-04]
:0045D4A2 8910
mov dword ptr [eax], edx
<- 保存常数0xDE7C
:0045D4A4 8D45E0
lea eax, dword ptr [ebp-20]
:0045D4A7 8B17
mov edx, dword ptr [edi]
:0045D4A9 E86269FAFF call 00403E10
<- 不重要
:0045D4AE 8D45E0
lea eax, dword ptr [ebp-20]
:0045D4B1 E85AEAFFFF call 0045BF10
<- 复制一份Irc,有一段代码是检查Irc中是否都为HEX字符
>>>>>>>>
:0045BF31 8B30
mov esi, dword ptr [eax]
:0045BF33 09F6
or esi, esi
:0045BF35 7436
je 0045BF6D
:0045BF37 8B4EFC
mov ecx, dword ptr [esi-04]
:0045BF3A 89F7
mov edi, esi
:0045BF3C E32F
jcxz 0045BF6D
:0045BF3E 89CB
mov ebx, ecx
:0045BF40 FC
cld
* Referenced by a (U)nconditional or (C)onditional Jump at
Address:
|:0045BF61(C)
|
:0045BF41 AC
lodsb
:0045BF42 80F830
cmp al, 30
:0045BF45 7219
jb 0045BF60
:0045BF47 80F839
cmp al, 39
:0045BF4A 7613
jbe 0045BF5F
:0045BF4C 80F841
cmp al, 41
:0045BF4F 720F
jb 0045BF60
:0045BF51 80F846
cmp al, 46
:0045BF54 7609
jbe 0045BF5F
:0045BF56 660FBAF0
btr ax, F0 <- 此处在内存里不是这样的
:0045BF5A 057303EBED
add eax, EDEB0373
* Referenced by a (U)nconditional or (C)onditional Jump at
Addresses:
|:0045BF4A(C), :0045BF54(C)
|
:0045BF5F AA
stosb
* Referenced by a (U)nconditional or (C)onditional Jump at
Addresses:
|:0045BF45(C), :0045BF4F(C)
|
:0045BF60 49
dec ecx
:0045BF61 75DE
jne 0045BF41
:0045BF63 B020
mov al, 20
* Referenced by a (U)nconditional or (C)onditional Jump at
Address:
|:0045BF6B(U)
|
:0045BF65 39FE
cmp esi, edi
:0045BF67 7404
je 0045BF6D
:0045BF69 AA
stosb
:0045BF6A 4B
dec ebx
:0045BF6B EBF8
jmp 0045BF65
<<<<<<<<
:0045D4B6 8BD8
mov ebx, eax
:0045D4B8 8D45E0
lea eax, dword ptr [ebp-20]
:0045D4BB 8BD3
mov edx, ebx
:0045D4BD E86A6EFAFF call 0040432C
:0045D4C2 83C8FF
or eax, FFFFFFFF
:0045D4C5 E88E58FAFF call 00402D58
:0045D4CA 8945E4
mov dword ptr [ebp-1C], eax
:0045D4CD E85AF6FFFF call 0045CB2C
<- 取Irc长度
:0045D4D2 DD5DE8
fstp qword ptr [ebp-18]
:0045D4D5 9B
wait
:0045D4D6 83FB10
cmp ebx, 00000010
<- 是否小于16
:0045D4D9 0F8EB4000000 jle 0045D593
<- 小于是正常的,跳走
:0045D4DF 8D4DDC
lea ecx, dword ptr [ebp-24]
:0045D4E2 8B07
mov eax, dword ptr [edi]
... ...
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0045D4D9(C)
|
:0045D593 83FB0A
cmp ebx, 0000000A
<- Irc的长度也不能小于10,正确值其实就是10
:0045D596 7C76
jl 0045D60E
:0045D598 8B0F
mov ecx, dword ptr [edi]
<- Irc
:0045D59A 8B55FC
mov edx, dword ptr [ebp-04] <-
常数0xDE7C
:0045D59D 8B45F8
mov eax, dword ptr [ebp-08] <-
Hwn
:0045D5A0 E88BF3FFFF call 0045C930
<- 算法主要是在这里,一定得追进去
:0045D5A5 8BD8
mov ebx, eax
:0045D5A7 85DB
test ebx, ebx
:0045D5A9 7E56
jle 0045D601 <-
通常的失败值会是0。怎么知道的?当然是试错
如剥洋葱,心都是在里面,:D 现在接触到算法的实质了,仔细看:
* Referenced by a CALL at Address:
|:0045D5A0
|
:0045C930 55
push ebp
:0045C931 8BEC
mov ebp, esp
:0045C933 83C4D4
add esp, FFFFFFD4
... ...
:0045C964 8B45F4
mov eax, dword ptr [ebp-0C]
:0045C967 E88C76FAFF call 00403FF8
:0045C96C 83F80A
cmp eax, 0000000A
<- Irc长度不能小于10
:0045C96F 0F8CE1000000 jl 0045CA56
<- 看这个跳转的距离,大致看不太难
:0045C975 8D45EC
lea eax, dword ptr [ebp-14]
:0045C978 8B55F4
mov edx, dword ptr [ebp-0C]
:0045C97B E89074FAFF call 00403E10
:0045C980 8D45EC
lea eax, dword ptr [ebp-14]
:0045C983 E888F5FFFF call 0045BF10
<- 复制一份Irc
:0045C988 8BD0
mov edx, eax
:0045C98A 83FA0A
cmp edx, 0000000A <-
这次是必须为10,因为在上面剔除了空格
:0045C98D 0F85C3000000 jne 0045CA56
:0045C993 8D45EC
lea eax, dword ptr [ebp-14]
:0045C996 E89179FAFF call 0040432C
:0045C99B 8D4DD4
lea ecx, dword ptr [ebp-2C] <- 目标缓冲区
:0045C99E BA02000000 mov edx,
00000002 <- 2是参数
:0045C9A3 8B45EC
mov eax, dword ptr [ebp-14] <- Irc
:0045C9A6 E8F5F5FFFF call 0045BFA0
<- 取最右的2 个字符到缓冲区
:0045C9AB 8B45D4
mov eax, dword ptr [ebp-2C]
:0045C9AE E829FAFFFF call 0045C3DC
<- 将其变为立即数放到eax中
:0045C9B3 8BD8
mov ebx, eax <-
保存在ebx
:0045C9B5 8D45EC
lea eax, dword ptr [ebp-14]
:0045C9B8 BA08000000 mov edx,
00000008
:0045C9BD E86A79FAFF call 0040432C
<- 取前面的的8个字符
:0045C9C2 8B45EC
mov eax, dword ptr [ebp-14] <- Irc的前8个字符
:0045C9C5 E8F6F4FFFF call 0045BEC0
<- 计算中间校验码,保存在al中
>>>>>>>>
* Referenced by a CALL at Addresses:
|... ...
|
:0045BEC0 53
push ebx
:0045BEC1 56
push esi
:0045BEC2 57
push edi
:0045BEC3 8BF8
mov edi, eax
:0045BEC5 33DB
xor ebx, ebx
:0045BEC7 8BC7
mov eax, edi
:0045BEC9 E82A81FAFF
call 00403FF8
:0045BECE 85C0
test eax, eax
:0045BED0 7438
je 0045BF0A
:0045BED2 0FB637
movzx esi, byte ptr [edi] <-
取得第一个字符
:0045BED5 8BC7
mov eax, edi
:0045BED7 E81C81FAFF
call 00403FF8 <- 取长度,得到eax=8
:0045BEDC 8BD0
mov edx, eax
:0045BEDE 83EA02
sub edx, 00000002
:0045BEE1 7C22
jl 0045BF05
<- 不会跳
:0045BEE3 42
inc edx
:0045BEE4 B802000000
mov eax, 00000002
* Referenced by a Jump at Address:
|:0045BF03(C)
<- 这个循环生成中间校验码到esi
|
:0045BEE9 A801
test al, 01
<- 对2取模
:0045BEEB 740C
je 0045BEF9
:0045BEED 33C9
xor ecx, ecx
:0045BEEF 8A4C07FF
mov cl, byte ptr [edi+eax-01] <- 取下一个字符
:0045BEF3 03C9
add ecx, ecx
<- cl*=2
:0045BEF5 33F1
xor esi, ecx
<- si^=cx
:0045BEF7 EB08
jmp 0045BF01
* Referenced by a Jump at Address:
|:0045BEEB(C)
|
:0045BEF9 33C9
xor ecx, ecx
:0045BEFB 8A4C07FF
mov cl, byte ptr [edi+eax-01] <- 取下一个字符
:0045BEFF 33F1
xor esi, ecx <-
si^cx
* Referenced by a Jump at Address:
|:0045BEF7(U)
|
:0045BF01 40
inc eax
:0045BF02 4A
dec edx
:0045BF03 75E4
jne 0045BEE9
<- 未完继续
|
:0045BF05 8BDE
mov ebx, esi
<- bx=si
:0045BF07 80E3FF
and bl, FF
* Referenced by a (U)nconditional or (C)onditional Jump at
Address:
|:0045BED0(C)
|
:0045BF0A 8BC3
mov eax, ebx
<- al=bl
:0045BF0C 5F
pop edi
:0045BF0D 5E
pop esi
:0045BF0E 5B
pop ebx
:0045BF0F C3
ret
嘿嘿,这一段变成C就是:
cCRCCheck='\0';
for(i=0; i<8; i++)
cCRCCheck^=(i>1 && i%2==0) ? cIrc[i]*2 :
cIrc[i];
<<<<<<<<
:0045C9CA E8C5F2FFFF call 0045BC94
<- 对上面Call产生的中间校验码作镜像翻转,说不明白,编小段程序就知道啦
>>>>>>>>
* Referenced by a CALL at Addresses:
|... ...
|
:0045BC94 D0E8
shr al, 1
:0045BC96 D0D4
rcl ah, 1
:0045BC98 D0E8
shr al, 1
:0045BC9A D0D4
rcl ah, 1
:0045BC9C D0E8
shr al, 1
:0045BC9E D0D4
rcl ah, 1
:0045BCA0 D0E8
shr al, 1
:0045BCA2 D0D4
rcl ah, 1
:0045BCA4 D0E8
shr al, 1
:0045BCA6 D0D4
rcl ah, 1
:0045BCA8 D0E8
shr al, 1
:0045BCAA D0D4
rcl ah, 1
:0045BCAC D0E8
shr al, 1
:0045BCAE D0D4
rcl ah, 1
:0045BCB0 D0E8
shr al, 1
:0045BCB2 D0D4
rcl ah, 1
:0045BCB4 86E0
xchg al, ah <-
校验码保存到al
:0045BCB6 C3
ret
<<<<<<<<
:0045C9CF 25FF000000 and eax,
000000FF
:0045C9D4 3BD8
cmp ebx, eax <-
bl放的是Irc的最后两个,比较。因此最后两位是校验码
:0045C9D6 757E
jne 0045CA56 <-
不是就去死
:0045C9D8 8B45EC
mov eax, dword ptr [ebp-14]
:0045C9DB E8FCF9FFFF call 0045C3DC
<- 将Irc变为立即数到eax
:0045C9E0 8945E8
mov dword ptr [ebp-18], eax <- 保存
:0045C9E3 8D45D8
lea eax, dword ptr [ebp-28] <- 缓冲区首址
:0045C9E6 50
push eax
:0045C9E7 E890A8FAFF call 0040727C
<- GetSystemTime
:0045C9EC 8B35682C5700 mov esi, dword
ptr [00572C68]
:0045C9F2 83E60F
and esi, 0000000F
:0045C9F5 83FE00
cmp esi, 00000000 <-
esi==5
:0045C9F8 7C54
jl 0045CA4E
<- 不跳
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0045CA4C(C)
|
:0045C9FA 0FB745D8 movzx
eax, word ptr [ebp-28] <- 年
:0045C9FE C1E00A
shl eax, 0A
:0045CA01 0FB755DA movzx
edx, word ptr [ebp-26] <- 月
:0045CA05 0BC2
or eax, edx
:0045CA07 C1E008
shl eax, 08
:0045CA0A 0FB755DE movzx
edx, word ptr [ebp-22] <- 日
:0045CA0E 0BC2
or eax, edx
比如 2001/08/27,则eax=0x1F44081B (0x1F44=2001*4)。时间参与运算是为增加得法的难度和随机性,也说明正确的注册码有许多
:0045CA10 8B55E8
mov edx, dword ptr [ebp-18] <- edx=Irc
:0045CA13 33D0
xor edx, eax <-
edx^=eax (Date)
:0045CA15 3355FC
xor edx, dword ptr [ebp-04] <- edx^=Hwn
:0045CA18 8B5DF8
mov ebx, dword ptr [ebp-08] <- ebx=0xDE7C
:0045CA1B F7D3
not ebx <-
ebx=~ebx=0xFFFF2183
:0045CA1D 33DA
xor ebx, edx <- ebx^=edx
:0045CA1F 8BD3
mov edx, ebx <- edx=ebx
:0045CA21 81E2FFFF0000 and edx, 0000FFFF
:0045CA27 C1EB12
shr ebx, 12
:0045CA2A B8FF1F0000 mov eax,
00001FFF <-
:0045CA2F 3BDA
cmp ebx, edx <-
两个值不等则失败
:0045CA31 750D
jne 0045CA40
:0045CA33 85D2
test edx, edx <-
这个值要大于0
:0045CA35 7E09
jle 0045CA40
:0045CA37 3BC2
cmp eax, edx <-
要小于0x1FFF
:0045CA39 7C05
jl 0045CA40
:0045CA3B 895DF0
mov dword ptr [ebp-10], ebx <- 保存结果
:0045CA3E EB0E
jmp 0045CA4E
... ...(不重要了)
:0045CA83 8B45F0
mov eax, dword ptr [ebp-10] <-
:0045CA86 5E
pop esi
:0045CA87 5B
pop ebx
:0045CA88 8BE5
mo
- 标 题:注册 Mp3 Tag Clinic 1.50 (16千字)
- 作 者:6767[BCG]
- 时 间:2001-8-27 20:47:09
- 链 接:http://bbs.pediy.com