汉字通破解手记
软件下载:http://kanjiweb.com/anonftp/pub/kanjiweb.exe
***********
写一篇破解过程,错误不少,还望包涵,贻笑大方了.
***********
运行Multword.exe,按X,出现注册窗口,告诉你序列号,我这里是34936378,以此为例.
按register注册,输入注册码7878,ctrl+d到sice,下bpx hmemcpy,g回到程序.
按ok后,sice很听话的跳出来了.按f12到跳出错误窗口,记住按的次数.
然后重复来一下,现在按的次数比刚才少1.然后开始按f10.
现在一步步跟吧.
……以下略去若干行.
:0001.37BF 8D8658FE lea ax,
[bp+FE58]
:0001.37C3 8CD2
mov dx, ss
:0001.37C5 52
push dx
………
:0001.37F7 9A907A8537 call 0001.7A90
:0001.37FC 83C40A add
sp, 000A
:0001.37FF 23C0
and ax, ax
:0001.3801 7403
je 3806
:0001.3806 8D8630FE lea ax,
[bp+FE30]
:0001.380A 8CD2
mov dx, ss
:0001.380C 52
push dx
………
:0001.3894 9ABA716038 call 0001.71BA
:0001.3899 83C408 add
sp, 0008
:0001.389C 8A861EFE mov al ,
[bp+FE1E]
:0001.38A0 98
cbw
:0001.38A1 05FBFF add
ax, FFFB
:0001.38A4 50
push ax
:0001.38A5 8D86BCFE lea ax,
[bp+FEBC]
:0001.38A9 8CD2
mov dx, ss
:0001.38AB 52
push dx
:0001.38AC 50
push ax
:0001.38AD FF76E8 push
word ptr [bp-18]
:0001.38B0 9A8E729738 call 0001.728E
:0001.38B5 83C408 add
sp, 0008
:0001.38B8 C78638FE0000 mov word ptr [bp-01C8],
0000
:0001.38BE EB11
jmp 38D1
:0001.38C0 8B8638FE mov ax,
[bp+FE38]
:0001.38C4 8D9EBCFE lea bx,
[bp+FEBC]
:0001.38C8 03D8
add bx, ax
:0001.38CA 803786 xor
byte ptr [bx], 86
:0001.38CD FF8638FE inc word
ptr [bp+FE38]
:0001.38D1 83BE38FE09 cmp word ptr
[bp+FE38], 0009
:0001.38D6 7CE8
jl 38C0
:0001.38D8 8D86BCFE lea ax,
[bp+FEBC]
:0001.38DC 8CD2
mov dx, ss
:0001.38DE 52
push dx
:0001.38DF 50
push ax
:0001.38E0 8D863AFE lea ax,
[bp+FE3A]
:0001.38E4 8CD2
mov dx, ss
:0001.38E6 52
push dx
:0001.38E7 50
push ax
:0001.38E8 9A7C77B338 call 0001.777C
:0001.38ED 83C408 add
sp, 0008
:0001.38F0 23C0
and ax, ax
:0001.38F2 7403
je 38F7
:0001.38F4 E94D00 jmp
3944
:0001.3954 B8EC08 mov
ax, 08EC
:0001.3957 8CDA
mov dx, ds
:0001.3959 52
push dx
:0001.395A 50
push ax
:0001.395B 6A00
push 0000
:0001.395D 9AD7020000 call USER.MESSAGEBOX
到这里按f10后跳出错误窗口.
是什么让程序跳到这里的?能不能避开?
向上看看,哦.0001.38E8这里有点问题.如果38f2跳转会怎么样?
从38f7一路下来会有个0001.3942 EB1E jmp 3962,跳到3962就避开了会跳出错误窗口的395d了.
可以在38f0处下r ax 0或者38f2处下a命令,然后输入jnz 38f7或者jmp 38f7,
按g回到程序后,没有注册窗口,重新运行软件,register那里不可按了,注册成功.
***********
如果你要改软件注册的话到这里可以了.
可以用ultra edit/winhex/hiew等软件找83C40823C07403,改74为75或者eb.这样就做出了修改版.
如果要找注册码的继续向下看了:
***********
现在不可注册了.软件写了什么注册标记呢用?用fileopen/regopen等软件来看看软件运行,或者用w32dasm分析一下,注册标记是在Multfont.dll文件中.重新装一下软件.可以先复制一下Multfont.dll.
38f2在38E8 call 0001.777C后面,这777c里面是什么?会让38f2的ax为0(注册成功)或者1(注册失败)?
我们再来一遍,在38e8按f8进入这个call看看.
:0001.777C 55
push bp
:0001.777D 8BEC
mov bp, sp
:0001.777F 8BD7
mov dx, di
:0001.7781 8BDE
mov bx, si
:0001.7783 1E
push ds
:0001.7784 C57606 lds
si, [bp+06]
:0001.7787 C47E0A les
di, [bp+0A]
:0001.778A 33C0
xor ax, ax
:0001.778C B9FFFF mov
cx, FFFF
:0001.778F F2
repnz
:0001.7790 AE
scasb
:0001.7791 F7D1
not cx
:0001.7793 2BF9
sub di, cx
:0001.7795 F3
repz
:0001.7796 A6
cmpsb
:0001.7797 7405
je 779E
:0001.7799 1BC0
sbb ax, ax
:0001.779B 83D8FF sbb
ax, FFFF
:0001.779E 1F
pop ds
:0001.779F 8BF3
mov si, bx
:0001.77A1 8BFA
mov di, dx
:0001.77A3 5D
pop bp
:0001.77A4 CB
retf
按字节比较串指令,数据段由si寻址存储单元和di寻址存储单元比较.带有前缀repe,相等继续比较.比较后cx寄存器为0,两者相等,不为0,两者不相等.如两者不相等.7790带借位相减ax=0,779b相减ax=1.
在7796下d ds:si,看到输入的7878.
d es:di看到真正的注册码1CMPSU4Yb.
***********
如果你要注册码的话到这里可以了.
但注册码1CMPSU4Yb对应的序列号是34936378,别的机器并不能用.
如果要找别的机子也可以用方法继续向下看了:
***********
注册标记是放在Multfont.dll中,我们可以用winhex来比较一下注册后的和注册前的有什么不同.
在19140h处未注册版是0409d007.注册版是15026619.
15026619->19660215.熟悉吧.这是个日期.
可能是作者的生日,也可能是作者的MM的生日.我们就不用管它了.你可以写信给作者问问看.^-^
那0409d007->07d00904是什么?07d0转换成十进制数字是2000.09转换成十进制是09,04转换成十进制是04,
20000904?怎么这么熟悉?哦.这不就是昨天装软件的日期嘛.
这个软件有十五天的试用期,第一次使用的日期就放在这里.
现在我们用最开始未使用过的Multfont.dll复制注册文件.
运行软件注册窗口出现不同的序列号.
用ultra edit等软件来改Multfont.dll文件从19140h开始改为15026619.
重新运行软件,register不可按,注册成功.
***********
如果你要找别的机子也能用的注册方法到这里可以了.
如果要找注册算法继续向下看了:
***********
现在我们想找注册算法以做出注册器,7796处真正的注册码是从哪里来的?
0001.7787有个les di, [bp+0A],但我们还是不知道的.^-^
现在向上看看,再想想,我们这一路跟踪下来有什么值得怀疑的地方吗?
:0001.38C0 8B8638FE mov ax,
[bp+FE38]
:0001.38C4 8D9EBCFE lea bx,
[bp+FEBC]
:0001.38C8 03D8
add bx, ax
:0001.38CA 803786 xor
byte ptr [bx], 86
:0001.38CD FF8638FE inc word
ptr [bp+FE38]
:0001.38D1 83BE38FE09 cmp word ptr
[bp+FE38], 0009
:0001.38D6 7CE8
jl 38C0
38d1这里没事比较[bp+fe39]和9的值做什么?吃饱了撑的?^-^当然不是了.
在这里的循环做什么呢?看38ca.目的是[bx]中值xor 86.
也就是[bp+FEBC]中开始9个字节xor 86.[bp+FEBC]是什么东东?
在38c4我们这里下d bx看看,是b7,c5,cb,d6,d5,d3,b2,df,e4.
这几个数依次xor 86后成了31,43,4d,50,53,55,34,59,62.
就是我们要找的注册码1CMPSU4Yb.
b7,c5,cb,d6,d5,d3,b2,df,e4,这几个数字又是从哪里来的呢?
往上找吧.0001.37F7 call 0001.7A90这里进去看看,
:0001.7A90 8CD8
mov ax, ds
:0001.7A92 90
nop
:0001.7A93 45
inc bp
:0001.7A94 55
push bp
:0001.7A95 8BEC
mov bp, sp
:0001.7A97 1E
push ds
:0001.7A98 8ED8
mov ds, ax
:0001.7A9A 1E
push ds
:0001.7A9B C55606 lds
dx, [bp+06]
:0001.7A9E 8B460A mov
ax, [bp+0A]
:0001.7AA1 B43D
mov ah, 3D
:0001.7AA3 2EF706B06A0100 test word ptr cs:[6AB0],
0001
:0001.7AAA 7407
je 7AB3
:0001.7AAC 9A767A0000 call KERNEL.DOS3CALL
dos3call?
这是做什么?哦.dos功能调用.
7aa1处ah=3d.功能号为3d的dos功能调用是打开一个文件.
ds:dx为文件名地址.所以我们在7aac这里下ds:dx看看,程序打开的是Multfont.dll文件.
再下来
3894 call 0001.71BA
进入后
……
:0001.71F7 8BD1
mov dx, cx
:0001.71F9 B80142 mov
ax, 4201
:0001.71FC 2EF706B06A0100 test word ptr cs:[6AB0],
0001
:0001.7203 7407
je 720C
:0001.7205 9A446D0000 call KERNEL.DOS3CALL
71f9处ax=4201.ah=42.al=01
功能号为42的dos功能调用是移动文件指针.al为移动方式,al=0表示指针从文件开始位置移动.
在7205处看dx值为9145,这是移动字节数低有效16位,cx值为1,这是移动字节数高有效16位.
所以指针移动19145h字节.
Multfont.dll的19145h字节开始是什么?
b7,c5,cb,d6,d5,d3,b2,df,e4.
这就是我们找的数.
移动到这里要读吧.是的.然后程序在38B0处开始读这些数.
进入call 0001.728E
:0001.72DF B43F
mov ah, 3F
:0001.72E1 2EF706B06A0100 test word ptr cs:[6AB0],
0001
:0001.72E8 7407
je 72F1
:0001.72EA 9A7C720000 call KERNEL.DOS3CALL
:0001.72EF EB02
jmp 72F3
功能号为3f的dos功能调用是读文件,
cx的值是读取的字节数,这里是19.
ds:dx是文件数据缓冲区地址.
我们看看是什么东东.哦.就是b7,c5,cb,d6,d5,d3,b2,df,e4,……19个字节数值.
但只有前面9个对我们有用.
现在我们可以来写注册器了.
读取Multfont.dll中从19145h开始9个字节,然后每一个xor 86.
结果就是注册码了.
啊.这就算注册器啊?
怎么不是,还很自动呢.不用输入序列号.:)
虽然这是非常正确的,但有些观众耐心听我的废话看到这里,本来想写个注册器让MM开心一下,没想到却是看到这样的注册器.唉,大家不要着急嘛.其实给MM用自动的多好.漂亮的女人是比较懒吧.:)
***********
如果你要找注册算法写出注册器的话到这里可以了.
如果要找完整的注册算法写出真正的注册器继续向下看了:
***********
这要找序列号和注册码的关系了.
我们来看看序列号是什么.34936378.
还记得38b0处程序读了19个字节吧.如果你比较未运行前和运行后的Multfont.dll也可以看到,
在1914fh开始4个字节是02,15,10,3a.
0215103a?我们拿出windows设计得最好最有用途的工具计算器来看看.^-^
0215103ah转换成十进制就是34936378.
现在思路进一步清楚了.
程序读取Multfont.dll文件中1914fh开始4个字节,转换成十六进制的数做为注册窗口中出现的序列号.
当输入的注册码xor 86后与19145h开始9个字节相等的话,注册成功.
Multfont.dll文件是什么时候开始写进这些与序列号注册码有关的数值的?
比较我们以前复制的未第一次运行和运行后的Multfont.dll文件,
未第一次运行前19140h开始是:
ff,ff,ff,ff,ff,31,43,4b,4e,52,53,32,54,54,00,00
00,00,00,00,00,00,00,00,00,41,4e,44,59,1e
其中19145h开始9个字节是1CKNRS2TT.
运行后19140h开始是:
04,09,d0,07,ff,b7,c5,cb,d6,d5,d3,b2,df,e4,00,02
15,16,3a,00,00,00,00,00,00,41,4e,44,59,1e
我们可以看出,程序运行第一次的时候,写进了第一次运行日期,写进了与序列号有关的数值,写进了与注册码有关的数值.这样来看,我们要找出序列号和注册码的关系是要在程序第一次运行的时候.
这就是关键所在了.
我们把未运行的Multfont.dll文件覆盖运行后文件,让程序以为是第一次运行.
这样,它会开始写进这些数值.
它什么时候写?用什么些?
我们想到了软件一直使用的dos功能调用call KERNEL.DOS3CALL.
写文件的功能号是40.
我们在softice中下bpx dos3call if ah==40,
运行软件后softice中断.
按f10到这里
:0001.7587 B440
mov ah, 40
:0001.7589 2EF706B06A0100 test word ptr cs:[6AB0],
0001
:0001.7590 7407
je 7599
:0001.7592 9A13750000 call KERNEL.DOS3CALL
下d dx,看到写进的是0409d007.ax=4,写进4个字节.
这个7587在:0001.041A call 0001.7406这个call里面.
:0001.041A 9A06740904 call 0001.7406
:0001.041F 83C408 add
sp, 0008
:0001.0422 6A00
push 0000
:0001.0424 8B860EFF mov ax,
[bp+FF0E]
:0001.0428 8B9610FF mov dx,
[bp+FF10]
:0001.042C 050500 add
ax, 0005
:0001.042F 83D200 adc
dx, 0000
:0001.0432 52
push dx
:0001.0433 50
push ax
:0001.0434 FF7684 push
word ptr [bp-7C]
:0001.0437 9ABA711D04 call 0001.71BA
:0001.043C 83C408 add
sp, 0008
:0001.043F 6A09
push 0009
:0001.0441 8D86F2FE lea ax,
[bp+FEF2]
:0001.0445 8CD2
mov dx, ss
:0001.0447 52
push dx
:0001.0448 50
push ax
:0001.0449 FF7684 push
word ptr [bp-7C]
:0001.044C 9A8E723A04 call 0001.728E
:0001.0451 83C408 add
sp, 0008
:0001.0454 8D86ECFE lea ax,
[bp+FEEC]
:0001.0458 8CD2
mov dx, ss
:0001.045A 52
push dx
:0001.045B 50
push ax
:0001.045C 9A287B4F04 call 0001.7B28
:0001.0461 83C404 add
sp, 0004
:0001.0464 8A86EFFE mov al ,
[bp+FEEF]
:0001.0468 25FF00 and
ax, 00FF
:0001.046B B90A00 mov
cx, 000A
:0001.046E 99
cwd
:0001.046F F7F9
idiv cx
:0001.0471 0086F3FE add [bp+FEF3],
al
:0001.0475 8A86EFFE mov al ,
[bp+FEEF]
:0001.0479 25FF00 and
ax, 00FF
:0001.047C B90A00 mov
cx, 000A
:0001.047F 99
cwd
:0001.0480 F7F9
idiv cx
:0001.0482 0096F4FE add [bp+FEF4],
dl
:0001.0486 8A86ECFE mov al ,
[bp+FEEC]
:0001.048A 25FF00 and
ax, 00FF
:0001.048D B90A00 mov
cx, 000A
:0001.0490 99
cwd
:0001.0491 F7F9
idiv cx
:0001.0493 0086F5FE add [bp+FEF5],
al
:0001.0497 8A86ECFE mov al ,
[bp+FEEC]
:0001.049B 25FF00 and
ax, 00FF
:0001.049E B90A00 mov
cx, 000A
:0001.04A1 99
cwd
:0001.04A2 F7F9
idiv cx
:0001.04A4 0096F6FE add [bp+FEF6],
dl
:0001.04A8 8A86EDFE mov al ,
[bp+FEED]
:0001.04AC 25FF00 and
ax, 00FF
:0001.04AF B90A00 mov
cx, 000A
:0001.04B2 99
cwd
:0001.04B3 F7F9
idiv cx
:0001.04B5 0086F7FE add [bp+FEF7],
al
:0001.04B9 8A86EDFE mov al ,
[bp+FEED]
:0001.04BD 25FF00 and
ax, 00FF
:0001.04C0 B90A00 mov
cx, 000A
:0001.04C3 99
cwd
:0001.04C4 F7F9
idiv cx
:0001.04C6 0096F8FE add [bp+FEF8],
dl
:0001.04CA 8A86EEFE mov al ,
[bp+FEEE]
:0001.04CE 25FF00 and
ax, 00FF
:0001.04D1 B90A00 mov
cx, 000A
:0001.04D4 99
cwd
:0001.04D5 F7F9
idiv cx
:0001.04D7 0086F9FE add [bp+FEF9],
al
:0001.04DB 8A86EEFE mov al ,
[bp+FEEE]
:0001.04DF 25FF00 and
ax, 00FF
:0001.04E2 B90A00 mov
cx, 000A
:0001.04E5 99
cwd
:0001.04E6 F7F9
idiv cx
:0001.04E8 0096FAFE add [bp+FEFA],
dl
先停一下,以免看多了头晕.
注意0464这里: mov al , [bp+FEEF]
引进了一个[bp+feef].
进入上面的045c call 0001.7B28可看到:
……
:0001.7B32 B42C
mov ah, 2C
:0001.7B34 2EF706B06A0100 test word ptr cs:[6AB0],
0001
:0001.7B3B 7407
je 7B44
:0001.7B3D 9A047B0000 call KERNEL.DOS3CALL
功能号是2c的dos功能调用是读系统时间.
ch是小时数,cl是分钟数,dh是秒数,dl是百分之一秒数.
这个call不看也可以,看了就会明白序列号是怎么来的了.原来是读系统时间的结果.
为了解释方便,这里还是以02,15,16,3a为例.
(第一次运行软件时间是在15点16分钟58.02秒,啊,在softice作用下我的系统时间又改变了,这里不是早上2点15分哦,第一个和第四个变换一下,但是这与注册算法无关就是了,不必看.^-^)
0464处al为02,046f处al(02)除以cx(常量a),
0471处[bp+fef3]数值加上2/a商0,[bp+fef3]值为常量1CKNRS2TT(1没有算)中的'C'.'C'+0='C',
0475处al仍为02,0480处al(02)除以cx(常量a),
0482处[bp+FEF4]数值加上2/a余数2,[bp+fef4]值为常量1CKNRS2TT中的'K'.'C'+2='M',
接下来分别用15,16,3a除以a,商及余数加到常量1CKNRS2TT对应的数值中.
[bp+fef3]开始数值是CMPSU4Y\,加上前面的1,[bp+fef2]开始数值是1CMPSU4Y\,
这个和注册码有点象了.但还不是真正的注册码,继续往下看:
:0001.04EC 8A86F3FE mov al ,
[bp+FEF3]
:0001.04F0 98
cbw
:0001.04F1 3D5A00 cmp
ax, 005A
:0001.04F4 7E05
jle 04FB
:0001.04F6 8086F3FE06 add byte ptr
[bp+FEF3], 06
比较[bp+fef3]数值与5a大小,若小于就跳,继续比较下一个字节,如大于数值加6,以下同.
:0001.04FB 8A86F4FE mov al ,
[bp+FEF4]
:0001.04FF 98
cbw
:0001.0500 3D5A00 cmp
ax, 005A
:0001.0503 7E05
jle 050A
:0001.0505 8086F4FE06 add byte ptr
[bp+FEF4], 06
:0001.050A 8A86F5FE mov al ,
[bp+FEF5]
:0001.050E 98
cbw
:0001.050F 3D5A00 cmp
ax, 005A
:0001.0512 7E05
jle 0519
:0001.0514 8086F5FE06 add byte ptr
[bp+FEF5], 06
:0001.0519 8A86F6FE mov al ,
[bp+FEF6]
:0001.051D 98
cbw
:0001.051E 3D5A00 cmp
ax, 005A
:0001.0521 7E05
jle 0528
:0001.0523 8086F6FE06 add byte ptr
[bp+FEF6], 06
:0001.0528 8A86F7FE mov al ,
[bp+FEF7]
:0001.052C 98
cbw
:0001.052D 3D5A00 cmp
ax, 005A
:0001.0530 7E05
jle 0537
:0001.0532 8086F7FE06 add byte ptr
[bp+FEF7], 06
:0001.0537 8A86F8FE mov al ,
[bp+FEF8]
:0001.053B 98
cbw
:0001.053C 3D5A00 cmp
ax, 005A
:0001.053F 7E05
jle 0546
:0001.0541 8086F8FE06 add byte ptr
[bp+FEF8], 06
:0001.0546 8A86F8FE mov al ,
[bp+FEF8]
:0001.054A 98
cbw
:0001.054B 3D3900 cmp
ax, 0039
:0001.054E 7E0F
jle 055F
:0001.0550 8A86F8FE mov al ,
[bp+FEF8]
:0001.0554 98
cbw
:0001.0555 3D4100 cmp
ax, 0041
:0001.0558 7D05
jge 055F
:0001.055A 8086F8FE07 add byte ptr
[bp+FEF8], 07
这里比较奇怪点,如果[bp+FEF8]数值大于39同时小于41,加上7.
:0001.055F 8A86F9FE mov al ,
[bp+FEF9]
:0001.0563 98
cbw
:0001.0564 3D5A00 cmp
ax, 005A
:0001.0567 7E05
jle 056E
:0001.0569 8086F9FE06 add byte ptr
[bp+FEF9], 06
:0001.056E 8A86FAFE mov al ,
[bp+FEFA]
:0001.0572 98
cbw
:0001.0573 3D5A00 cmp
ax, 005A
:0001.0576 7E05
jle 057D
:0001.0578 8086FAFE06 add byte ptr
[bp+FEFA], 06
一路下来,我们的1CMPSU4Y\总算在这里加上了一次.'\'是5c,大于5a,'\'+6='b',
:0001.057D 6A00
push 0000
:0001.057F 8B860EFF mov ax,
[bp+FF0E]
:0001.0583 8B9610FF mov dx,
[bp+FF10]
:0001.0587 050500 add
ax, 0005
:0001.058A 83D200 adc
dx, 0000
:0001.058D 52
push dx
:0001.058E 50
push ax
:0001.058F FF7684 push
word ptr [bp-7C]
:0001.0592 9ABA715F04 call 0001.71BA
:0001.0597 83C408 add
sp, 0008
:0001.059A C786F0FE0000 mov word ptr [bp-0110],
0000
:0001.05A0 EB11
jmp 05B3
:0001.05A2 8B86F0FE mov ax,
[bp+FEF0]
:0001.05A6 8D9EF2FE lea bx,
[bp+FEF2]
:0001.05AA 03D8
add bx, ax
:0001.05AC 803786 xor
byte ptr [bx], 86
:0001.05AF FF86F0FE inc word
ptr [bp+FEF0]
:0001.05B3 83BEF0FE09 cmp word ptr
[bp+FEF0], 0009
:0001.05B8 7CE8
jl 05A2
这个循环是把注册码1CMPSU4Yb xor 86,变成了b7,c5,cb,d6,d5,d3,b2,df,e4.
还记得38c0的循环吧.
下面应该开始写文件了吧.是的.
:0001.05C7 9A06749505 call 0001.7406
把与注册码相关的b7,c5,cb,d6,d5,d3,b2,df,e4.写入Multfont.dll文件.
:0001.05F9 9A0674E705 call 0001.7406
:0001.060E 9A0674FC05 call 0001.7406
:0001.0623 9A06741106 call 0001.7406
:0001.0638 9A06742606 call 0001.7406
分四次把与序列号相关也是与程序第一次运行时间相关的02,15,16,3a写入Multfont.dll文件.
现在整个完整算法都出来了.
啊.我要睡觉了.
2000年9月6日.
- 标 题:汉字通破解手记 (19千字)
- 作 者:浪子沈七
- 时 间:2000-9-6 1:54:41
- 链 接:http://bbs.pediy.com