软件名称:Virtual Drive 2000 网络版
整理日期:2000.8.12
最新版本:5.1c
文件大小:4824KB
软件授权:共享软件
使用平台:Win95/98
发布公司:http://www.farstone.com/
下载地址:http://www.newhua.com.cn/down/virtdnet.zip
软件简介:一个非常不错WIN95/98下的CD-ROM模拟程序,可以把CD-ROM复制为硬盘的一个文件,这个版本连CD音轨、保护都可以模拟,最多模拟出二十部光驱。此版为多语言版,包括:中文版、英文版、和日文版,安装时会自动检测操作系统的语言版本并自动安装。
破解工具:W32Dasm,exescope 6.0
说明:这是我将近一年前破解的软件,当时由于工作需要,想找一个网络版的虚拟光驱,找是找到了,但为评估版,上网搜索也没有找到关于网络版的完整破解,于是只好自力更生。在破解过程中,我还发现了在番外地里介绍的修改setup.sys后试用版变正式版的过程,而且还发现,如果使用该网络版的是中国的用户,则需要软件狗,我全给他解了。这个软件的全部破解过程很长,有50多K,这里仅介绍注册码的计算过程。另外,网络版与单机版的序列号计算过程基本一样,其中,网络版的序列号为15位,而单机版为11位,就差在最后4位数字,最后的4位数字表示的是允许使用的用户数。
这个软件可以自动判别操作系统的类型,根据操作系统的类型自动选择用繁体、简体、日语、法语、德语及英语来显示安装界面,虽然这给用户的使用上简便了,但用pwdasm反汇编时,却出现了很多一些看不懂的字符串――因为缺省是显示繁体中文,虽然不影响程序流程,但这给破解造成了麻烦,为了更好地破解这个软件,我对该软件做一下处理,让w32dasm能够识别字符串,方法是用exescope对程序进行处理,将繁体中文和简体中文均改为英文字符显示,嘿嘿,本来用作汉化的常用工具,反其道而行之,可以称为反汉化,反汉化的相应字符串提示不用担心,软件公司已经给做好了,用exescope改好后,用w32dasm进行反汇编,竟取得了很好的效果,这回,w32dasm将字符全部显示出来了,当然是英文的,现在我们开始破解吧。
目标程序:SerSetup.exe,大小331776 Bytes
运行SerSetup.exe,安装程序要求输入公司名称和序列号等,下面为序列号的计算部分的流程
* Referenced by a CALL at Address:
|:00401F5C
|
:00402890 64A100000000 mov eax, dword
ptr fs:[00000000]
:00402896 6AFF
push FFFFFFFF
:00402898 68F8834100 push 004183F8
:0040289D 50
push eax
:0040289E 64892500000000 mov dword ptr fs:[00000000],
esp
:004028A5 81EC00010000 sub esp, 00000100
:004028AB 53
push ebx
:004028AC 55
push ebp
:004028AD 56
push esi
:004028AE 57
push edi
:004028AF 8BD9
mov ebx, ecx
:004028B1 8BBC2420010000 mov edi, dword ptr
[esp+00000120] ====> 指向注册码
:004028B8 83CDFF
or ebp, FFFFFFFF
:004028BB 8BCD
mov ecx, ebp
:004028BD 33C0
xor eax, eax
:004028BF F2
repnz
:004028C0 AE
scasb ====> 检测注册码的字符串长度
:004028C1 F7D1
not ecx
:004028C3 2BF9
sub edi, ecx
:004028C5 8D542410 lea
edx, dword ptr [esp+10]
:004028C9 8BC1
mov eax, ecx
:004028CB 8BF7
mov esi, edi
:004028CD 8BFA
mov edi, edx
:004028CF C1E902
shr ecx, 02
:004028D2 F3
repz
:004028D3 A5
movsd ====> 将注册码中的字符串送入[esp+10],为后面计算做准备
:004028D4 8BC8
mov ecx, eax
:004028D6 33C0
xor eax, eax
:004028D8 83E103
and ecx, 00000003
:004028DB F3
repz
:004028DC A4
movsb
:004028DD 8D7C2410 lea
edi, dword ptr [esp+10]
:004028E1 8BCD
mov ecx, ebp
:004028E3 F2
repnz
:004028E4 AE
scasb ====> 再次检测新的字符串长度
:004028E5 F7D1
not ecx
:004028E7 49
dec ecx
:004028E8 83F90F
cmp ecx, 0000000F ====> 字符串长度是否为15个
:004028EB 7515
jne 00402902 ====> 不是,则序列号错误
:004028ED 8D4C2410 lea
ecx, dword ptr [esp+10]
:004028F1 8844241B mov
byte ptr [esp+1B], al ====> [esp+1B]处置0,对注册码进行截取到11位,为后面的计算做准备
:004028F5 51
push ecx
:004028F6 E8B5EFFFFF call 004018B0
====> 关键的CALL
:004028FB 83C404
add esp, 00000004
:004028FE 85C0
test eax, eax
====> EAX作为旗标
:00402900 751A
jne 0040291C ====>
如果EAX=0则序列号错误
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004028EB(C), :0040294D(C), :00402953(C)
|
:00402902 8D8C2420010000 lea ecx, dword ptr
[esp+00000120]
:00402909 89AC2418010000 mov dword ptr [esp+00000118],
ebp
:00402910 E81EDB0000 call 00410433
:00402915 33C0
xor eax, eax ====> 失败旗标
:00402917 E9B1000000 jmp 004029CD
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402900(C)
|
:0040291C 8BBC2420010000 mov edi, dword ptr
[esp+00000120] ====> 指向原始的字符串
:00402923 8BCD
mov ecx, ebp
:00402925 33C0
xor eax, eax
:00402927 8D542410 lea
edx, dword ptr [esp+10] ====> 指向刚才合成的字符串
:0040292B F2
repnz
:0040292C AE
scasb
:0040292D F7D1
not ecx
:0040292F 2BF9
sub edi, ecx
:00402931 8BC1
mov eax, ecx
:00402933 8BF7
mov esi, edi
:00402935 8BFA
mov edi, edx
:00402937 B230
mov dl, 30
:00402939 C1E902
shr ecx, 02
:0040293C F3
repz
:0040293D A5
movsd
====> 向[ESP+10]处复制"0"
:0040293E 8BC8
mov ecx, eax
:00402940 83E103
and ecx, 00000003
:00402943 F3
repz
:00402944 A4
movsb
:00402945 33C9
xor ecx, ecx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0040295F(C)
|
:00402947 8A440C1B mov
al, byte ptr [esp+ecx+1B] ====> 将最后的4个数字分别置入al中
:0040294B 3C39
cmp al, 39
====> 是否大于"9"
:0040294D 7FB3
jg 00402902
====> 大于则完蛋
:0040294F 38540C10 cmp
byte ptr [esp+ecx+10], dl ====> 注册码的第1加ecx位字符是否小于"0"
:00402953 7CAD
jl 00402902
====> 小于则完蛋
:00402955 2AC2
sub al, dl
====> 将最后的4个数字的ascii取"0"改为相应的机器码
:00402957 88440C1B mov
byte ptr [esp+ecx+1B], al ====> 结果送回[esp+ecx+1B]中
:0040295B 41
inc ecx
====> +1
:0040295C 83F904
cmp ecx, 00000004
====> 是否转换了4个
:0040295F 7CE6
jl 00402947
====> 不是则继续
:00402961 0FBE4C241B movsx ecx,
byte ptr [esp+1B] \
:00402966 0FBE44241E movsx eax,
byte ptr [esp+1E] \ ====> 将刚才的结果分别送入这四个中
:0040296B 0FBE7C241C movsx edi,
byte ptr [esp+1C] /
:00402970 0FBE74241D movsx esi,
byte ptr [esp+1D] /
:00402975 03C1
add eax, ecx
====> 累加起来
:00402977 BD0A000000 mov ebp,
0000000A
:0040297C 03C7
add eax, edi
:0040297E 03C6
add eax, esi
:00402980 99
cdq
====> mod 0Ah
:00402981 F7FD
idiv ebp
:00402983 85D2
test edx, edx
====> 余数是否为0
:00402985 741B
je 004029A2
====> 是,则走,否则等死吧
:00402987 8D8C2420010000 lea ecx, dword ptr
[esp+00000120]
:0040298E C7842418010000FFFFFFFF mov dword ptr [esp+00000118], FFFFFFFF
:00402999 E895DA0000 call 00410433
:0040299E 33C0
xor eax, eax
====> 置失败标志
:004029A0 EB2B
jmp 004029CD
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00402985(C)
|
:004029A2 8D0C89
lea ecx, dword ptr [ecx+4*ecx] ====>
第12位数字乘以5
:004029A5 C7842418010000FFFFFFFF mov dword ptr [esp+00000118], FFFFFFFF
====> 这也应该是与setup.sys某个特殊标志
:004029B0 8D044F
lea eax, dword ptr [edi+2*ecx] ====>
再乘以2加上第13位数字
:004029B3 8D8C2420010000 lea ecx, dword ptr
[esp+00000120]
:004029BA 8D1480
lea edx, dword ptr [eax+4*eax] ====>
再乘以5
:004029BD 8D0456
lea eax, dword ptr [esi+2*edx] ====>
再乘以2加上第14位数字
:004029C0 894360
mov dword ptr [ebx+60], eax
====> 结果放到[ebx+60]中,应该也是在setup.sys中,经试验发现,最后4位数字表示授权使用的人数
:004029C3 E86BDA0000 call 00410433
:004029C8 B801000000 mov eax,
00000001
====> 置成功标志
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00402917(U), :004029A0(U)
|
:004029CD 8B8C2410010000 mov ecx, dword ptr
[esp+00000110]
:004029D4 5F
pop edi
:004029D5 5E
pop esi
:004029D6 5D
pop ebp
:004029D7 5B
pop ebx
:004029D8 64890D00000000 mov dword ptr fs:[00000000],
ecx
:004029DF 81C40C010000 add esp, 0000010C
:004029E5 C20400
ret 0004
* Referenced by a CALL at Address:
|:004028F6
|
:004018B0 81EC00010000 sub esp, 00000100
:004018B6 83C9FF
or ecx, FFFFFFFF
:004018B9 33C0
xor eax, eax
:004018BB 53
push ebx
:004018BC 8B9C2408010000 mov ebx, dword ptr
[esp+00000108]
:004018C3 55
push ebp
:004018C4 56
push esi
:004018C5 57
push edi
:004018C6 8BFB
mov edi, ebx ====> [esp+00000108]指向输入的注册码
:004018C8 F2
repnz ====> 检测注册码的字符串长度
:004018C9 AE
scasb
:004018CA F7D1
not ecx
:004018CC 49
dec ecx
:004018CD 8BFB
mov edi, ebx
:004018CF 8BD1
mov edx, ecx ====> edx为字符串长度
:004018D1 83C9FF
or ecx, FFFFFFFF
:004018D4 F2
repnz
:004018D5 AE
scasb
:004018D6 F7D1
not ecx
:004018D8 2BF9
sub edi, ecx
:004018DA 8D6C2410 lea
ebp, dword ptr [esp+10]
:004018DE 8BC1
mov eax, ecx
:004018E0 8BF7
mov esi, edi
:004018E2 8BFD
mov edi, ebp
:004018E4 C1E902
shr ecx, 02
:004018E7 F3
repz
:004018E8 A5
movsd
:004018E9 8BC8
mov ecx, eax
:004018EB 83E103
and ecx, 00000003
:004018EE 83FA0B
cmp edx, 0000000B ====> 比较字符串长度是否为11
:004018F1 F3
repz
:004018F2 A4
movsb
:004018F3 0F85A5000000 jne 0040199E
====> 不相等,那么就等死吧
:004018F9 B803000000 mov eax,
00000003
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401922(C)
|
:004018FE 8A0C18
mov cl, byte ptr [eax+ebx] \
:00401901 80F939
cmp cl, 39
\
:00401904 0F8794000000 ja 0040199E
|
:0040190A 80F930
cmp cl, 30
|
:0040190D 0F828B000000 jb 0040199E
|
:00401913 8A4C0410 mov
cl, byte ptr [esp+eax+10] | ====> 是否为数字,如果是,则转换为机器码数字,否则完蛋
:00401917 80C1D0
add cl, D0
|
:0040191A 884C0410 mov
byte ptr [esp+eax+10], cl |
:0040191E 40
inc eax
|
:0040191F 83F80B
cmp eax, 0000000B /
:00401922 7CDA
jl 004018FE
/
:00401924 8B4C2418 mov
ecx, dword ptr [esp+18] ====> 第9位数字置入ecx
:00401928 81E1FF000000 and ecx, 000000FF
:0040192E 41
inc ecx
====> +1
:0040192F 8BC1
mov eax, ecx
:00401931 C1E005
shl eax, 05
====> 乘以32
:00401934 2BC1
sub eax, ecx
====> 减去原数,相当于乘以31
:00401936 8B4C241A mov
ecx, dword ptr [esp+1A] ====> 第11位数字置入ecx
:0040193A 81E1FF000000 and ecx, 000000FF
:00401940 8BD1
mov edx, ecx
:00401942 C1E204
shl edx, 04
====> 乘以16
:00401945 03D1
add edx, ecx
====> 加上原数,相当于乘以17
:00401947 8B4C2419 mov
ecx, dword ptr [esp+19] ====> 第10位数字置入ecx
:0040194B 81E1FF000000 and ecx, 000000FF
:00401951 03C2
add eax, edx
====> 加入到eax中
:00401953 8D1449
lea edx, dword ptr [ecx+2*ecx]
:00401956 C1E203
shl edx, 03
:00401959 2BD1
sub edx, ecx
====> 乘以7
:0040195B B963000000 mov ecx,
00000063
:00401960 03C2
add eax, edx
====> 加入到eax中,这样我们可以算出,eax的值=([esp+18]+1)*31+[esp+1A]*17+[esp+19]*7
:00401962 99
cdq
:00401963 F7F9
idiv ecx
====> mod 63h,十进制为99
:00401965 8B442413 mov
eax, dword ptr [esp+13] ====> 将第4位数字置入eax中
:00401969 8B4C2414 mov
ecx, dword ptr [esp+14] ====> 将第5位数字置入ecx中
:0040196D 25FF000000 and eax,
000000FF
:00401972 81E1FF000000 and ecx, 000000FF
:00401978 8D0480
lea eax, dword ptr [eax+4*eax] ====> 第4位数字乘以5
:0040197B 8D0441
lea eax, dword ptr [ecx+2*eax] ====> 得到的结果乘以2再加上第5位数字的值
:0040197E 3BC2
cmp eax, edx
====> 余数是否等于eax的值
:00401980 751C
jne 0040199E
====> 不等,注册码错误
:00401982 8A442412 mov
al, byte ptr [esp+12]
:00401986 3C58
cmp al, 58
====> 序列号中的第3个字母是否为X
:00401988 7404
je 0040198E
:0040198A 3C78
cmp al, 78
====> 或者x
:0040198C 7510
jne 0040199E
====> 二者都不等,去死吧
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401988(C)
|
:0040198E 5F
pop edi
:0040198F 5E
pop esi
:00401990 5D
pop ebp
:00401991 B802000000 mov eax,
00000002
:00401996 5B
pop ebx
:00401997 81C400010000 add esp, 00000100
:0040199D C3
ret
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:004018F3(C), :00401904(C), :0040190D(C), :00401980(C), :0040198C(C)
|
:0040199E 5F
pop edi
:0040199F 5E
pop esi
:004019A0 5D
pop ebp
:004019A1 33C0
xor eax, eax
:004019A3 5B
pop ebx
:004019A4 81C400010000 add esp, 00000100
:004019AA C3
ret
从上面的程序中,我们可以知道网络版注册码的情况:
1. 注册码必须为15位(单机版前11位),第3个字符必须为x或X,从第4位开始,必须全是数字
2. 第1、2个字符必须大于等于"0"(即ascii中的30)
3. ((第9位数字+1)*31+第10位*7+第11位*17) mod 63h=第4位乘以10+第5位数字
4. 最后4位数字相加应等于10或者0,其中,前3个数字表示授权使用的人数
根据上面的结果我们可以给出一个注册码:FSX310000009993(网上常见的) 或 FSX000000045555,其他的自己去造吧