• 标 题:ClassExplorer的破解 (13千字)
  • 作 者:henryw
  • 时 间:2001-7-29 16:55:35
  • 链 接:http://bbs.pediy.com

今天来说说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,没看懂,只是写注册机干脆就把它贴上,注意传入的参数位置就可以了。反正传出的结果是正确的。其实我写这个注册机所学到的东西远比破解这个软件要多。

注册机代码太长,不贴了。

感谢大家看完。