• 标 题:汉字通破解手记 (19千字)
  • 作 者:浪子沈七
  • 时 间:2000-9-6 1:54:41
  • 链 接:http://bbs.pediy.com

汉字通破解手记
软件下载: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日.