今天来说说ClassExplorer的破解。
这是个非常好的Delphi工具,有点类似VB中各个sub之间切换的味道,当然还有其他功能,对Delphi感兴趣的网友记得看看。
以前它是收费软件,而今它已经是free了,只是不那么彻底,下载的时候需要提供给站台自己的信息,它才会给你寄上注册码。说是一个工作日完成,结果我等了n个工作日也没有等到。
这是我为什么要破解这个free软件的其中一个原因。另外一个原因是,2年前我用过它,只是自己没有追出注册码,是在BBS上认识的一个朋友给的。而今我想看看自己到底有没有长进。
破解完这个软件,以后恐怕很难再有时间破解了。算是对自己破解的一段总结吧。
用trw2000 bpx hmemcpy断下,F12大约14次看到进入ClassExplorer领空就使用F10跟。
015F:021CE428 PUSH EBX
015F:021CE429 PUSH ESI
015F:021CE42A PUSH EDI
015F:021CE42B PUSH EBP
015F:021CE42C MOV EBP,ECX
015F:021CE42E MOV EDI,EDX
015F:021CE430 MOV EBX,EAX
015F:021CE432 MOV ESI,00C1B362
015F:021CE437 MOV EAX,EBX
015F:021CE439 CALL 021CE350
015F:021CE43E TEST AL,AL
015F:021CE440 JNZ 021CE456
015F:021CE442 MOV ECX,EBP
015F:021CE444 MOV EDX,EDI
015F:021CE446 MOV EAX,EBX
015F:021CE448 CALL 021CE1B8 《-- 这个Call需要跟进去看。
015F:021CE44D TEST AL,AL
015F:021CE44F JZ 021CE456
015F:021CE451 MOV ESI,0040D3DA
015F:021CE456 MOV EAX,ESI
015F:021CE458 POP EBP
015F:021CE459 POP EDI
015F:021CE45A POP ESI
015F:021CE45B POP EBX
015F:021CE45C RET
程序会带你到这里来,这是一张黑名单,凡是不幸榜上有名者不能注册。举个例子:Markus, NAMESergy等等。
内存21CE330处是张表,程序根据它来产生黑名单。也就是黑名单的变相加密解密。
015F:021CE372 MOV EBX,021CE330
015F:021CE377 MOV AL,[EBX]
015F:021CE379 XOR AL,35
015F:021CE37B AND EAX,FF
015F:021CE380 MOV [EBP-08],EAX
015F:021CE383 MOV DWORD [EBP-0C],01
015F:021CE38A XOR EDI,EDI
015F:021CE38C CMP EDI,[EBP-08]
015F:021CE38F JNL 021CE3E2
015F:021CE391 LEA EAX,[EBP-10]
015F:021CE394 CALL `VCL50!@System@@LStrClr$qqrr17System@AnsiString`
015F:021CE399 INC EBX
015F:021CE39A MOV AL,[EBX]
015F:021CE39C XOR AL,35
015F:021CE39E AND EAX,FF
015F:021CE3A3 LEA EDX,[EAX+01]
015F:021CE3A6 ADD [EBP-0C],EDX
015F:021CE3A9 MOV ESI,EAX
015F:021CE3AB DEC ESI
015F:021CE3AC TEST ESI,ESI
015F:021CE3AE JL 021CE3CD
015F:021CE3B0 INC ESI
015F:021CE3B1 INC EBX
015F:021CE3B2 LEA EAX,[EBP-14]
015F:021CE3B5 MOV DL,[EBX]
015F:021CE3B7 XOR DL,35
015F:021CE3BA CALL `VCL50!@System@@LStrFromChar$qqrr17System@AnsiStringc`
015F:021CE3BF MOV EDX,[EBP-14]
015F:021CE3C2 LEA EAX,[EBP-10]
015F:021CE3C5 CALL `VCL50!@System@@LStrCat$qqrv`
015F:021CE3CA DEC ESI
015F:021CE3CB JNZ 021CE3B1
015F:021CE3CD MOV EDX,[EBP-10] //程序在这里准备比对黑名单。
015F:021CE3D0 MOV EAX,[EBP-04] //
015F:021CE3D3 CALL `VCL50!@Sysutils@CompareText$qqrx17System@AnsiStringt1`
015F:021CE3D8 TEST EAX,EAX
015F:021CE3DA JZ 021CE3E2
015F:021CE3DC INC EDI
015F:021CE3DD CMP EDI,[EBP-08]
015F:021CE3E0 JL 021CE391
015F:021CE3E2 CMP EDI,[EBP-08]
015F:021CE3E5 JL 021CE3F9
015F:021CE3E7 SUB EBX,021CE330
015F:021CE3ED MOV EAX,[EBP-0C]
015F:021CE3F0 DEC EAX
015F:021CE3F1 CMP EBX,EAX
015F:021CE3F3 JNZ 021CE3F9
015F:021CE3F5 XOR EAX,EAX
015F:021CE3F7 JMP SHORT 021CE3FB
015F:021CE3F9 MOV AL,01
015F:021CE3FB MOV EBX,EAX
015F:021CE3FD XOR EAX,EAX
015F:021CE3FF POP EDX
015F:021CE400 POP ECX
015F:021CE401 POP ECX
015F:021CE402 MOV [FS:EAX],EDX
015F:021CE405 PUSH DWORD 021CE41F
015F:021CE40A LEA EAX,[EBP-14]
015F:021CE40D MOV EDX,02
015F:021CE412 CALL `VCL50!@System@@LStrArrayClr$qqrv`
015F:021CE417 RET
如此我们进入了第二段,从21CE448进去,进入21Ce115 Call 21CDFBC看看。
这里程序将对你的名字进行变形换位。
015F:021CDFD5 PUSH DWORD 021CE066
015F:021CDFDA PUSH DWORD [FS:EAX]
015F:021CDFDD MOV [FS:EAX],ESP
015F:021CDFE0 MOV EAX,EBX
015F:021CDFE2 MOV EDX,[EBP-04]
015F:021CDFE5 CALL `VCL50!@System@@LStrAsg$qqrv`
015F:021CDFEA MOV EAX,[EBX]
015F:021CDFEC CALL `VCL50!@System@@LStrLen$qqrv`
015F:021CDFF1 MOV EDI,EAX
015F:021CDFF3 SAR EDI,1
015F:021CDFF5 JNS 021CDFFA
015F:021CDFF7 ADC EDI,BYTE +00
015F:021CDFFA TEST EDI,EDI
015F:021CDFFC JNG 021CE050
015F:021CDFFE MOV ESI,01
015F:021CE003 MOV EAX,[EBX]
<-- [EBX],名字的地址。
015F:021CE005 MOV AL,[EAX+ESI-01]
015F:021CE009 XOR EDX,EDX
015F:021CE00B MOV DL,AL
015F:021CE00D AND EDX,BYTE +01
015F:021CE010 CMP EDX,BYTE +01
015F:021CE013 JNZ 021CE04C
015F:021CE015 MOV EDX,[EBX]
015F:021CE017 MOV [EBP-05],AL
015F:021CE01A MOV EAX,[EBX]
015F:021CE01C CALL `VCL50!@System@@LStrLen$qqrv`
015F:021CE021 SUB EAX,ESI
015F:021CE023 MOV EDX,[EBX]
015F:021CE025 PUSH DWORD [EDX+EAX]
015F:021CE028 MOV EAX,EBX
015F:021CE02A CALL `VCL50!@System@UniqueString$qqrr17System@AnsiString`
015F:021CE02F POP EDX
015F:021CE030 MOV [EAX+ESI-01],DL
015F:021CE034 MOV EAX,[EBX]
015F:021CE036 CALL `VCL50!@System@@LStrLen$qqrv`
015F:021CE03B SUB EAX,ESI
015F:021CE03D PUSH EAX
015F:021CE03E MOV EAX,EBX
015F:021CE040 CALL `VCL50!@System@UniqueString$qqrr17System@AnsiString`
015F:021CE045 POP EDX
015F:021CE046 MOV CL,[EBP-05]
015F:021CE049 MOV [EAX+EDX],CL
015F:021CE04C INC ESI
015F:021CE04D DEC EDI
015F:021CE04E JNZ 021CE003
015F:021CE050 XOR EAX,EAX
015F:021CE052 POP EDX
015F:021CE053 POP ECX
015F:021CE054 POP ECX
015F:021CE055 MOV [FS:EAX],EDX
015F:021CE058 PUSH DWORD 021CE06D
015F:021CE05D LEA EAX,[EBP-04]
015F:021CE060 CALL `VCL50!@System@@LStrClr$qqrr17System@AnsiString`
015F:021CE065 RET
过了这段,下一段程序将产生两个数字序列,为
一、01 02 03 04 ... 0F 10
二、01 23 45 67 89 AB CD EF FE DC ...32 10
在21CE120处的Call要进去看看,会发现生成第一个数字序列。
当运行Call 21CD4C0的时候,生成第二个序列。就像这样:
015F:021CD4D1 MOV DWORD [EBX],67452301
015F:021CD4D7 MOV DWORD [EBX+04],EFCDAB89
015F:021CD4DE MOV DWORD [EBX+08],98BADCFE
015F:021CD4E5 MOV DWORD [EBX+0C],10325476
015F:021CD4EC POP EBX
015F:021CD4ED RET
程序在这里将变形的姓名和上述的数字序列生成一个新的字串:
015F:021CDCF4 PUSH EBX
015F:021CDCF5 PUSH ESI
015F:021CDCF6 PUSH EDI
015F:021CDCF7 PUSH EBP
015F:021CDCF8 PUSH ECX
015F:021CDCF9 MOV ESI,ECX
ECX= 变形姓名长度
015F:021CDCFB MOV [ESP],EDX EDX=
变形姓名地址
015F:021CDCFE MOV EBX,EAX
015F:021CDD00 MOV EBP,[EBX+10]
015F:021CDD03 MOV EAX,ESI
015F:021CDD05 SHL EAX,03
015F:021CDD08 ADD [EBX+10],EAX [EBX]=01
23 45 67 89 AB CD EF FE DC BA 98 76 54 32 10
015F:021CDD0B CMP EBP,[EBX+10]
015F:021CDD0E JNG 021CDD13
015F:021CDD10 INC DWORD [EBX+14]
015F:021CDD13 MOV EAX,ESI
015F:021CDD15 SHR EAX,1D
015F:021CDD18 ADD [EBX+14],EAX
015F:021CDD1B SHR EBP,03
015F:021CDD1E AND EBP,BYTE +3F
015F:021CDD21 XOR EDI,EDI
015F:021CDD23 TEST EBP,EBP
015F:021CDD25 JZ 021CDD6D
015F:021CDD27 MOV EDI,EBP
015F:021CDD29 MOV EAX,40
015F:021CDD2E SUB EAX,EBP
015F:021CDD30 MOV EBP,EAX
015F:021CDD32 CMP EBP,ESI
015F:021CDD34 JNG 021CDD49
015F:021CDD36 MOVZX EAX,DI
015F:021CDD39 LEA EDX,[EBX+EAX+18]
015F:021CDD3D MOV EAX,[ESP]
015F:021CDD40 MOV ECX,ESI
015F:021CDD42 CALL `VCL50!@System@Move$qqrpxvpvi`
015F:021CDD47 JMP SHORT 021CDDB8
015F:021CDD49 MOVZX EAX,DI
015F:021CDD4C LEA EDX,[EBX+EAX+18]
015F:021CDD50 MOV EAX,[ESP]
015F:021CDD53 MOV ECX,EBP
015F:021CDD55 CALL `VCL50!@System@Move$qqrpxvpvi`
015F:021CDD5A PUSH BYTE +0F
015F:021CDD5C LEA ECX,[EBX+18]
015F:021CDD5F MOV EAX,EBX
015F:021CDD61 MOV EDX,03
015F:021CDD66 CALL 021CD5D8
015F:021CDD6B SUB ESI,EBP
015F:021CDD6D CMP ESI,BYTE +40
015F:021CDD70 JL 021CDDA5
015F:021CDD72 MOVZX EAX,DI
015F:021CDD75 MOV EDX,[ESP]
015F:021CDD78 LEA EAX,[EDX+EAX]
015F:021CDD7B LEA EDX,[EBX+18]
015F:021CDD7E MOV ECX,40
015F:021CDD83 CALL `VCL50!@System@Move$qqrpxvpvi`
015F:021CDD88 PUSH BYTE +0F
015F:021CDD8A LEA ECX,[EBX+18]
015F:021CDD8D MOV EAX,EBX
015F:021CDD8F MOV EDX,03
015F:021CDD94 CALL 021CD5D8
015F:021CDD99 ADD DI,BYTE +40
015F:021CDD9D SUB ESI,BYTE +40
015F:021CDDA0 CMP ESI,BYTE +40
015F:021CDDA3 JNL 021CDD72
015F:021CDDA5 MOVZX EAX,DI
015F:021CDDA8 MOV EDX,[ESP]
015F:021CDDAB LEA EAX,[EDX+EAX]
015F:021CDDAE LEA EDX,[EBX+18]
015F:021CDDB1 MOV ECX,ESI
015F:021CDDB3 CALL `VCL50!@System@Move$qqrpxvpvi` 把变形名字接到后面。
015F:021CDDB8 POP EDX
015F:021CDDB9 POP EBP
015F:021CDDBA POP EDI
015F:021CDDBB POP ESI
015F:021CDDBC POP EBX
015F:021CDDBD RET
015F:021CDDC0 PUSH EBX
015F:021CDDC1 PUSH ESI
015F:021CDDC2 MOV EBX,EDX
015F:021CDDC4 MOV ESI,EAX
015F:021CDDC6 MOV EAX,[EBX+10]
015F:021CDDC9 SHR EAX,03
015F:021CDDCC AND AX,BYTE +3F
015F:021CDDD0 MOV EDX,EAX
015F:021CDDD2 XOR ECX,ECX
015F:021CDDD4 MOV CL,DL
015F:021CDDD6 MOV BYTE [EBX+ECX+18],80
<-- 变形名字所在位置后。
015F:021CDDDB INC EDX
015F:021CDDDC MOV CX,3F
015F:021CDDE0 SUB CX,AX
015F:021CDDE3 MOV EAX,ECX
015F:021CDDE5 CMP AX,BYTE +08
015F:021CDDE9 JNC 021CDE22
015F:021CDDEB AND EDX,FF
015F:021CDDF1 LEA EDX,[EBX+EDX+18]
015F:021CDDF5 MOVZX EAX,AX
015F:021CDDF8 XOR ECX,ECX
015F:021CDDFA XCHG EAX,EDX
015F:021CDDFB CALL `VCL50!@System@@FillChar$qqrv`
015F:021CDE00 PUSH BYTE +0F
015F:021CDE02 LEA ECX,[EBX+18]
015F:021CDE05 MOV EAX,EBX
015F:021CDE07 MOV EDX,03
015F:021CDE0C CALL 021CD5D8
015F:021CDE11 LEA EAX,[EBX+18]
015F:021CDE14 XOR ECX,ECX
015F:021CDE16 MOV EDX,38
015F:021CDE1B CALL `VCL50!@System@@FillChar$qqrv`
015F:021CDE20 JMP SHORT 021CDE3A
015F:021CDE22 AND EDX,FF
015F:021CDE28 LEA EDX,[EBX+EDX+18]
015F:021CDE2C MOVZX EAX,AX
015F:021CDE2F SUB EAX,BYTE +08
015F:021CDE32 XOR ECX,ECX
015F:021CDE34 XCHG EAX,EDX
015F:021CDE35 CALL `VCL50!@System@@FillChar$qqrv`
015F:021CDE3A MOV EAX,[EBX+10]
015F:021CDE3D MOV [EBX+50],EAX
015F:021CDE40 MOV EAX,[EBX+14]
015F:021CDE43 MOV [EBX+54],EAX
015F:021CDE46 PUSH BYTE +0F
015F:021CDE48 LEA ECX,[EBX+18]
015F:021CDE4B MOV EAX,EBX
015F:021CDE4D MOV EDX,03
015F:021CDE52 CALL 021CD5D8 〈--------
关键Call进去看看。
015F:021CDE57 MOV EDX,ESI
015F:021CDE59 MOV EAX,EBX
015F:021CDE5B MOV ECX,10
015F:021CDE60 CALL `VCL50!@System@Move$qqrpxvpvi`
015F:021CDE65 MOV EAX,EBX
015F:021CDE67 XOR ECX,ECX
015F:021CDE69 MOV EDX,58
015F:021CDE6E CALL `VCL50!@System@@FillChar$qqrv`
015F:021CDE73 POP ESI
015F:021CDE74 POP EBX
015F:021CDE75 RET
程序的准备工作做完,下面开始注册第一步。21CDE52 Call 21CD5D8,这个Call有600多行。
进行一系列运算后生成一个16位的数字。然后将这个16位数字转成一个32位的字串。
最后从这个32位字串中取出8位作ID,另外24位作为注册码。
这是最后的程序:
015F:021CE125 MOV EAX,[EBP-10]
<-- EAX中就是32位的字串地址。
015F:021CE128 CALL `VCL50!@System@@LStrLen$qqrv`
015F:021CE12D MOV ESI,EAX
015F:021CE12F TEST ESI,ESI
015F:021CE131 JNG 021CE186
015F:021CE133 MOV EBX,01
015F:021CE138 MOV EAX,EBX
015F:021CE13A AND EAX,80000003
015F:021CE13F JNS 021CE146
015F:021CE141 DEC EAX
015F:021CE142 OR EAX,BYTE -04
015F:021CE145 INC EAX
015F:021CE146 TEST EAX,EAX
015F:021CE148 JNZ 021CE165
015F:021CE14A LEA EAX,[EBP-14]
015F:021CE14D MOV EDX,[EBP-10]
015F:021CE150 MOV DL,[EDX+EBX-01]
015F:021CE154 CALL `VCL50!@System@@LStrFromChar$qqrr17System@AnsiStringc`
015F:021CE159 MOV EDX,[EBP-14]
015F:021CE15C MOV EAX,EDI
015F:021CE15E CALL `VCL50!@System@@LStrCat$qqrv` <---
ID连接
015F:021CE163 JMP SHORT 021CE182
015F:021CE165 LEA EAX,[EBP-18]
015F:021CE168 MOV EDX,[EBP-10]
015F:021CE16B MOV DL,[EDX+EBX-01]
015F:021CE16F CALL `VCL50!@System@@LStrFromChar$qqrr17System@AnsiStringc`
015F:021CE174 MOV EDX,[EBP-18]
015F:021CE177 MOV EAX,[EBP-08]
015F:021CE17A CALL `VCL50!@System@@LStrCat$qqrv` <---
注册码连接
015F:021CE17F MOV EAX,[EBP-08]
015F:021CE182 INC EBX
015F:021CE183 DEC ESI
015F:021CE184 JNZ 021CE138
015F:021CE186 XOR EAX,EAX
015F:021CE188 POP EDX
015F:021CE189 POP ECX
015F:021CE18A POP ECX
015F:021CE18B MOV [FS:EAX],EDX
015F:021CE18E PUSH DWORD 021CE1B0
015F:021CE193 LEA EAX,[EBP-18]
015F:021CE196 MOV EDX,04
015F:021CE19B CALL `VCL50!@System@@LStrArrayClr$qqrv`
015F:021CE1A0 LEA EAX,[EBP-04]
015F:021CE1A3 CALL `VCL50!@System@@LStrClr$qqrr17System@AnsiString`
015F:021CE1A8 RET
以下就是比较ID和注册码了,不贴了。
对于那个600多行的Call,没看懂,只是写注册机干脆就把它贴上,注意传入的参数位置就可以了。反正传出的结果是正确的。其实我写这个注册机所学到的东西远比破解这个软件要多。
注册机代码太长,不贴了。
感谢大家看完。
- 标 题:ClassExplorer的破解 (13千字)
- 作 者:henryw
- 时 间:2001-7-29 16:55:35
- 链 接:http://bbs.pediy.com