老文章档案 · 2003 年

中文编辑排版专家—DreamEdit破解手记

网络学院 · 破解文章 · 2003-09-05 · 作者:newlaos[DFCG] · 出处:赢政天下整理收藏

***************************************************

软件名称:DreamEdit 2.3.1

大 小:1.87MB

加密方式:Aspack 2.001 + 注册码

使用工具:TRW2000 1.22汉化注册版,w32Dasm黄金中文版,fi2.49

pj日期:爆破于2003年2月25日,算法分析于2003年3月25

***************************************************

PJ说明:本软件是readbook的一个免费组件,但也有注册码,注册后就不会出现未注册的字样。之所之要破解,主要是学习手动脱壳和巩固爆破。

作者newlaos申明:只是学习,请不用于商业用途或是将本文方法制作的注册机任意传播,造成后果,本人一概不负。

一、爆破

1、首先用fi2.49侦测,知道是用Aspack 2.001加了壳,通过各种脱壳软件都可以很快搞定。手动脱壳出不难,用TRW2000载入DreamEdit 2.3.1,后通过F10步进,F8跟入关键CALL,F7跳开循环,就可以找到关键的领空跳转,再用PEDUMP,就生成了一个可执行的脱壳文件(用makepe生成的文件,运行时会出错)。

2、用w32Dasm黄金中文版静态反汇编,再用“串式数据参考”,找"中文编辑排版专家—DreamEdit(未注册)",来到下面这个段。

:0054C3C0 683AC65400 push 0054C63A

:0054C3C5 64FF30 push dword ptr fs:[eax]

:0054C3C8 648920 mov dword ptr fs:[eax], esp

:0054C3CB E8FC67EBFF call 00402BCC

:0054C3D0 E8CF09FAFF call 004ECDA4

:0054C3D5 84C0 test al, al <======关键对比

:0054C3D7 740E je 0054C3E7 <======跳则,显示“未注册”,所以把740E改为750E可爆破

* Possible StringData Ref from Code Obj ->"中文编辑排版专家—DreamEdit"

|

:0054C3D9 BA50C65400 mov edx, 0054C650

:0054C3DE 8BC3 mov eax, ebx

:0054C3E0 E8C3CEEEFF call 004392A8

:0054C3E5 EB0C jmp 0054C3F3 <=======跳转到程序正式运行部分。

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:0054C3D7(C)

|

* Possible StringData Ref from Code Obj ->"中文编辑排版专家—DreamEdit(未注册)"

|

:0054C3E7 BA74C65400 mov edx, 0054C674

:0054C3EC 8BC3 mov eax, ebx

:0054C3EE E8B5CEEEFF call 004392A8

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:0054C3E5(U)

|

:0054C3F3 C6830808000000 mov byte ptr [ebx+00000808], 00 <=======程序正式运行部分

:0054C3FA 8D55F8 lea edx, dword ptr [ebp-08]

:0054C3FD A120025900 mov eax, dword ptr [00590220]

:0054C402 8B00 mov eax, dword ptr [eax]

3、上面解决了“未注册显示部分”,下面再来看看序列号注册部分,还是用“串式数据参考”,找到"注册成功!感谢您对DreamEdit的支持!",太经典的句子呀,来到下面这个段代码:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00548536(C)

|

:005485AC 55 push ebp

:005485AD 68BE865400 push 005486BE

:005485B2 64FF30 push dword ptr fs:[eax]

:005485B5 648920 mov dword ptr fs:[eax], esp

:005485B8 8D55FC lea edx, dword ptr [ebp-04]

:005485BB 8B8300030000 mov eax, dword ptr [ebx+00000300]

:005485C1 E8B20CEFFF call 00439278

:005485C6 8B45FC mov eax, dword ptr [ebp-04]

:005485C9 E85247FAFF call 004ECD20

:005485CE 84C0 test al, al <========关键对比

:005485D0 0F84B4000000 je 0054868A <========关键跳转,过去就变成“错误注册号了”,就改这里了

:005485D6 8D55F8 lea edx, dword ptr [ebp-08]

:005485D9 8B8300030000 mov eax, dword ptr [ebx+00000300]

:005485DF E8940CEFFF call 00439278

:005485E4 8B45F8 mov eax, dword ptr [ebp-08]

:005485E7 50 push eax

:005485E8 8D55F4 lea edx, dword ptr [ebp-0C]

:005485EB 8B83F4020000 mov eax, dword ptr [ebx+000002F4]

:005485F1 E8820CEFFF call 00439278

:005485F6 8B45F4 mov eax, dword ptr [ebp-0C]

:005485F9 5A pop edx

:005485FA E8FDBEEBFF call 004044FC

:005485FF 85C0 test eax, eax <=========关键对比

:00548601 0F8E83000000 jle 0054868A <=========第二个关键跳转,过去就变成“错误注册号了”,改这里

:00548607 8D55F0 lea edx, dword ptr [ebp-10]

:0054860A 8B8300030000 mov eax, dword ptr [ebx+00000300]

:00548610 E8630CEFFF call 00439278

:00548615 8B45F0 mov eax, dword ptr [ebp-10]

:00548618 50 push eax

:00548619 A17C005900 mov eax, dword ptr [0059007C]

:0054861E 8B00 mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->"code"

|

:00548620 B9D4865400 mov ecx, 005486D4

* Possible StringData Ref from Code Obj ->"User"

|

:00548625 BAE4865400 mov edx, 005486E4

:0054862A 8B30 mov esi, dword ptr [eax]

:0054862C FF5604 call [esi+04]

:0054862F 8D55EC lea edx, dword ptr [ebp-14]

:00548632 8B83F4020000 mov eax, dword ptr [ebx+000002F4]

:00548638 E83B0CEFFF call 00439278

:0054863D 8B45EC mov eax, dword ptr [ebp-14]

:00548640 50 push eax

:00548641 A17C005900 mov eax, dword ptr [0059007C]

:00548646 8B00 mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->"Name"

|

:00548648 B9F4865400 mov ecx, 005486F4

* Possible StringData Ref from Code Obj ->"User"

|

:0054864D BAE4865400 mov edx, 005486E4

:00548652 8B30 mov esi, dword ptr [eax]

:00548654 FF5604 call [esi+04]

:00548657 6A40 push 00000040

* Possible StringData Ref from Code Obj ->"注册成功"

|

:00548659 68FC865400 push 005486FC

* Possible StringData Ref from Code Obj ->"注册成功!感谢您对DreamEdit的支持!"

|

:0054865E 6808875400 push 00548708

:00548663 8BC3 mov eax, ebx

:00548665 E8326EEFFF call 0043F49C

:0054866A 50 push eax

:0054866B E8B401ECFF call 00408824

:00548670 A1A0005900 mov eax, dword ptr [005900A0]

:00548675 8B00 mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->"中文编辑排版专家—DreamEdit"

|

:00548677 BA34875400 mov edx, 00548734

:0054867C E8270CEFFF call 004392A8

:00548681 8BC3 mov eax, ebx

:00548683 E864D0F0FF call 004556EC

:00548688 EB19 jmp 005486A3 <=====跳入程序正式部分

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:

|:005485D0(C), :00548601(C)

|

:0054868A 6A10 push 00000010

* Possible StringData Ref from Code Obj ->"错误"

|

:0054868C 6850875400 push 00548750

* Possible StringData Ref from Code Obj ->"用户名或注册码错误(请注意区分大小写)!"

|

:00548691 6858875400 push 00548758

:00548696 8BC3 mov eax, ebx

:00548698 E8FF6DEFFF call 0043F49C

:0054869D 50 push eax

:0054869E E88101ECFF call 00408824

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00548688(U)

|

:005486A3 33C0 xor eax, eax <======程序正式部分

:005486A5 5A pop edx

:005486A6 59 pop ecx

:005486A7 59 pop ecx

:005486A8 648910 mov dword ptr fs:[eax], edx

:005486AB 68C5865400 push 005486C5

4、到这里,程序算是爆破完成,但与算注册号的方法还是有差距,因为程序每次启动,都会在DreamEdit.ini文件里读取用户名和注册号,进行运算,不对就会显示“未注册”,当然我爆破了(在上面),也不会显示。

二、算法分析(简单,建议初学者以此为开始)

1、开始步骤同上

.......

.......

:005485AC 55 push ebp

:005485AD 68BE865400 push 005486BE

:005485B2 64FF30 push dword ptr fs:[eax]

:005485B5 648920 mov dword ptr fs:[eax], esp

:005485B8 8D55FC lea edx, dword ptr [ebp-04]

:005485BB 8B8300030000 mov eax, dword ptr [ebx+00000300]

:005485C1 E8B20CEFFF call 00439278 <===这里EAX=8,注册码长度

:005485C6 8B45FC mov eax, dword ptr [ebp-04]<===EAX=78787878

:005485C9 E85247FAFF call 004ECD20 <===这里是个关键的CALL,要正确则这里EAX返回时不能为0

:005485CE 84C0 test al, al <===我们将注册码改为78787876后,重新来

:005485D0 0F84B4000000 je 0054868A <===呵呵,从这里跳过去,就OVER

:005485D6 8D55F8 lea edx, dword ptr [ebp-08]

:005485D9 8B8300030000 mov eax, dword ptr [ebx+00000300]

:005485DF E8940CEFFF call 00439278

:005485E4 8B45F8 mov eax, dword ptr [ebp-08]

:005485E7 50 push eax

:005485E8 8D55F4 lea edx, dword ptr [ebp-0C]

:005485EB 8B83F4020000 mov eax, dword ptr [ebx+000002F4]

:005485F1 E8820CEFFF call 00439278

:005485F6 8B45F4 mov eax, dword ptr [ebp-0C]

:005485F9 5A pop edx <===EDX=78787876,EAX=newlaos

:005485FA E8FDBEEBFF call 004044FC <===关键的CALL,F8跟进看看,要正确则EAX不能为0

:005485FF 85C0 test eax, eax

:00548601 0F8E83000000 jle 0054868A <===呵呵,从这里跳过去,就OVER。

:00548607 8D55F0 lea edx, dword ptr [ebp-10]

:0054860A 8B8300030000 mov eax, dword ptr [ebx+00000300]

:00548610 E8630CEFFF call 00439278

:00548615 8B45F0 mov eax, dword ptr [ebp-10]

:00548618 50 push eax

:00548619 A17C005900 mov eax, dword ptr [0059007C]

:0054861E 8B00 mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->"code"

|

:00548620 B9D4865400 mov ecx, 005486D4

* Possible StringData Ref from Code Obj ->"User"

|

:00548625 BAE4865400 mov edx, 005486E4

:0054862A 8B30 mov esi, dword ptr [eax]

:0054862C FF5604 call [esi+04]

:0054862F 8D55EC lea edx, dword ptr [ebp-14]

:00548632 8B83F4020000 mov eax, dword ptr [ebx+000002F4]

:00548638 E83B0CEFFF call 00439278

:0054863D 8B45EC mov eax, dword ptr [ebp-14]

:00548640 50 push eax

:00548641 A17C005900 mov eax, dword ptr [0059007C]

:00548646 8B00 mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->"Name"

|

:00548648 B9F4865400 mov ecx, 005486F4

* Possible StringData Ref from Code Obj ->"User"

|

:0054864D BAE4865400 mov edx, 005486E4

:00548652 8B30 mov esi, dword ptr [eax]

:00548654 FF5604 call [esi+04]

:00548657 6A40 push 00000040

* Possible StringData Ref from Code Obj ->"注册成功"

|

:00548659 68FC865400 push 005486FC

* Possible StringData Ref from Code Obj ->"注册成功!感谢您对DreamEdit的支持!"

|

:0054865E 6808875400 push 00548708

:00548663 8BC3 mov eax, ebx

:00548665 E8326EEFFF call 0043F49C

:0054866A 50 push eax

:0054866B E8B401ECFF call 00408824

:00548670 A1A0005900 mov eax, dword ptr [005900A0]

:00548675 8B00 mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->"中文编辑排版专家—DreamEdit"

|

:00548677 BA34875400 mov edx, 00548734

:0054867C E8270CEFFF call 004392A8

:00548681 8BC3 mov eax, ebx

:00548683 E864D0F0FF call 004556EC

:00548688 EB19 jmp 005486A3

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:

|:005485D0(C), :00548601(C) <===有两处会跳到错误的地方来,向上看

|

:0054868A 6A10 push 00000010

* Possible StringData Ref from Code Obj ->"错误"

|

:0054868C 6850875400 push 00548750

* Possible StringData Ref from Code Obj ->"用户名或注册码错误(请注意区分大小写)!"

|

:00548691 6858875400 push 00548758

:00548696 8BC3 mov eax, ebx

:00548698 E8FF6DEFFF call 0043F49C

:0054869D 50 push eax

:0054869E E88101ECFF call 00408824

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00548688(U)

|

:005486A3 33C0 xor eax, eax

:005486A5 5A pop edx

:005486A6 59 pop ecx

:005486A7 59 pop ecx

:005486A8 648910 mov dword ptr fs:[eax], edx

:005486AB 68C5865400 push 005486C5

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:005486C3(U)

|

:005486B0 8D45EC lea eax, dword ptr [ebp-14]

:005486B3 BA05000000 mov edx, 00000005

:005486B8 E8F7B8EBFF call 00403FB4

:005486BD C3 ret

:005486BE E9C5B2EBFF jmp 00403988

:005486C3 EBEB jmp 005486B0

:005486C5 5E pop esi

:005486C6 5B pop ebx

:005486C7 8BE5 mov esp, ebp

:005486C9 5D pop ebp

:005486CA C3 ret

----------005485C9 call 004ECD20 关键的CALL,F8跟进来到这列代码段-----------------

功能:要正确则这里EAX返回时不能为0,要求注册码每个字符的ASC码相加能够整除D,就正解过关。

* Referenced by a CALL at Addresses:

|:004ECDD4 , :005485C9

|

:004ECD20 55 push ebp

:004ECD21 8BEC mov ebp, esp

:004ECD23 51 push ecx

:004ECD24 53 push ebx

:004ECD25 8945FC mov dword ptr [ebp-04], eax

:004ECD28 8B45FC mov eax, dword ptr [ebp-04]

:004ECD2B E89476F1FF call 004043C4

:004ECD30 33C0 xor eax, eax

:004ECD32 55 push ebp

:004ECD33 6897CD4E00 push 004ECD97

:004ECD38 64FF30 push dword ptr fs:[eax]

:004ECD3B 648920 mov dword ptr fs:[eax], esp

:004ECD3E 8B45FC mov eax, dword ptr [ebp-04]

:004ECD41 E8CA74F1FF call 00404210

:004ECD46 83F805 cmp eax, 00000005 <===如果注册码小于等于5,就OVER

:004ECD49 7D04 jge 004ECD4F

:004ECD4B 33DB xor ebx, ebx

:004ECD4D EB32 jmp 004ECD81

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004ECD49(C)

|

:004ECD4F 33DB xor ebx, ebx

:004ECD51 8B45FC mov eax, dword ptr [ebp-04]

:004ECD54 E8B774F1FF call 00404210

:004ECD59 85C0 test eax, eax

:004ECD5B 7E13 jle 004ECD70

:004ECD5D BA01000000 mov edx, 00000001 <===计数器,初始化为1

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004ECD6E(C)

|

:004ECD62 8B4DFC mov ecx, dword ptr [ebp-04]

:004ECD65 0FB64C11FF movzx ecx, byte ptr [ecx+edx-01]

:004ECD6A 03D9 add ebx, ecx

:004ECD6C 42 inc edx

:004ECD6D 48 dec eax

:004ECD6E 75F2 jne 004ECD62 <===这里构成一个小循环,就是将输入的注册码的ASC码的十六进制相加。

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004ECD5B(C)

|

:004ECD70 8BC3 mov eax, ebx <===将相加之和放入EAX

:004ECD72 B90D000000 mov ecx, 0000000D <===ECX=D

:004ECD77 99 cdq

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004ECD11(C)

|

:004ECD78 F7F9 idiv ecx <===EAX除以ECX,商回EAX,余数回EDX

:004ECD7A 85D2 test edx, edx <===如果EDX=0,即能整除,则标志ZF=1,才能正确

:004ECD7C 0F94C0 sete al <===这里是用标志位来设置AL,关键的关键!

:004ECD7F 8BD8 mov ebx, eax <===又将EAX的值放入EBX

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004ECD4D(U)

|

:004ECD81 33C0 xor eax, eax

:004ECD83 5A pop edx

:004ECD84 59 pop ecx

:004ECD85 59 pop ecx

:004ECD86 648910 mov dword ptr fs:[eax], edx

:004ECD89 689ECD4E00 push 004ECD9E

:004ECD8E 8D45FC lea eax, dword ptr [ebp-04]

:004ECD91 E8FA71F1FF call 00403F90

:004ECD96 C3 ret

:004ECD97 E9EC6BF1FF jmp 00403988

:004ECD9C EBF0 jmp 004ECD8E

:004ECD9E 8BC3 mov eax, ebx <===注意EBX的值不能为0

:004ECDA0 5B pop ebx

:004ECDA1 59 pop ecx

:004ECDA2 5D pop ebp

:004ECDA3 C3 ret

<===为能通过第一关,我们将注册码改为78787876,重新来。

-------005485FA call 004044FC 关键的CALL,F8跟进,来到下面代码段-------------------

要正确,则EAX不能为0----------------------------------------------

初始值:EDX=78787876,EAX=newlaos

:004044FC 85C0 test eax, eax

:004044FE 7440 je 00404540 <===不跳

:00404500 85D2 test edx, edx

:00404502 7431 je 00404535 <===不跳

:00404504 53 push ebx

:00404505 56 push esi

:00404506 57 push edi

:00404507 89C6 mov esi, eax <===EAX=newlaos

:00404509 89D7 mov edi, edx <===EDX=78787876

:0040450B 8B4FFC mov ecx, dword ptr [edi-04] <===ECX等于8,注册码长度

:0040450E 57 push edi

:0040450F 8B56FC mov edx, dword ptr [esi-04] <===EDX等于7,姓名长度

:00404512 4A dec edx <===EDX=EDX-1=6

:00404513 781B js 00404530 <===不跳

:00404515 8A06 mov al, byte ptr [esi] <===将newlaos的第一个字符放入EAX的低位6E

:00404517 46 inc esi

:00404518 29D1 sub ecx, edx <===ECX=ECX-EDX=8-6=2

:0040451A 7E14 jle 00404530 <===不跳,跳了就OVER了,说明注册码至少与姓名等长,而不能短于姓名

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:0040452E(U)

|

:0040451C F2 repnz

:0040451D AE scasb <===这里十分关键,主要是看在你的注册码里包含有你的输入的姓名

:0040451E 7510 jne 00404530 <===不相等就跳向OVER

:00404520 89CB mov ebx, ecx

:00404522 56 push esi

:00404523 57 push edi

:00404524 89D1 mov ecx, edx

:00404526 F3 repz

:00404527 A6 cmpsb

:00404528 5F pop edi

:00404529 5E pop esi

:0040452A 740C je 00404538 <===只有相等,才从这里跳走是正确的

:0040452C 89D9 mov ecx, ebx

:0040452E EBEC jmp 0040451C <===呵呵,这里构成一个小循环

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:

|:00404513(C), :0040451A(C), :0040451E(C)

|

:00404530 5A pop edx

:00404531 31C0 xor eax, eax

:00404533 EB08 jmp 0040453D

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00404502(C)

|

:00404535 31C0 xor eax, eax

:00404537 C3 ret

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:0040452A(C)

|

:00404538 5A pop edx

:00404539 89F8 mov eax, edi

:0040453B 29D0 sub eax, edx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00404533(U)

|

:0040453D 5F pop edi

:0040453E 5E pop esi

:0040453F 5B pop ebx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004044FE(C)

|

:00404540 C3 ret

---------------------------------------------------------------------------------------------------

2、算法总结:

a、就是将输入的注册码的ASC码的十六进制相加,能整除D

b、注册码一定要比注册名长,且其中必须包含有注册名。

3、注册信息放在文件DreamEdit.ini里的

[User]

code=newlaosa

Name=newlaos

相关资讯:

·语音界面2.0算法分析及注册机源码!

·侠客系统修改器1.21破解手记--算法分析

·中文拨号上网计时计费器 V4.12注册算法分析

·ClockWise 3.22e注册码算法分析

·CoolClock V1.02注册算法分析

·Directory Scanner v1.5 注册算法分析

·Disk Chief 1.2 简单注册算法分析

·EffeTech HTTP Sniffer 3.2注册算法分析

·eLib2.01算法分析

·EZ MP3 Recorder 1.15 注册算法分析

相关软件:

→ 特别推荐

→ 热点TOP10

我为人人《《==》》人人为我

关于我们 |

帮助(?)|

广告服务 |

版权声明 |

商业合作 |

发展历程 |

加盟我们 |

联系我们

Copyright (C) 1998-2004 winzheng.com All Rights Reserved.

特别感谢 蓝芒科技 提供下载站及论坛服务器

2003-2004 年,宽带刚刚普及,下载站的文章区是许多人学电脑的第一课堂。
🕰 → 🤖 从那时到现在

当年一篇教程能让一台电脑焕然一新;今天的效率工具换成了 AI。 想知道当下最可靠的 AI 模型怎么选?看 赢政指数——我们用了 28 年的选软件严谨,现在用来评测大模型。

档案性质声明:本页为赢政天下(1998-2011)老文章的历史档案复原, 内容反映当年发表时的原貌——包括当年的技术表述、软件版本与观点,部分方法在今天已不适用或不合规,仅作互联网历史记录与研究用途, 不提供任何形式的下载。原始数据经由公共网络存档(Internet Archive)复原。发现问题请联系我们
← 返回老文章档案 · 软件史档案馆 · 赢政天下站史