我找到一些资料,贴出来大家共享!
来自:mikedeakins, 时间:2001-11-8 22:11:00, ID:717728
我来灌水。
******************************************************************************
控件破解指南
Mike Deakins
注意:本文的转载必须获得作者同意(作者电子邮件地址: [email]MikeDeakins@ChinaRen.com[/email])。
不像可执行文件,Delphi / C++ Builder 的控件是不能利用 SoftIce 进行动
态跟踪的,但是,这并不意味着控件的破解比可执行文件的破解要困难。
要想破解一个控件,首先要弄明白它为什么能够产生限制。一般来讲,带有限
制的控件只能在 IDE 中运行。这就意味着,这个控件必须有一种既定的机制来判断当前执
行环境是否是在 IDE 内部。Delphi / C++ Builder 的 IDE 具有什么样的特征呢?自从
Delphi 1.0 开始,IDE 的主窗口的类名始终没有改变过,一直是 TAppBuilder,并且,这
个窗口没有子窗口。几乎所有限制控件都是用这个特征来判断当前是否是在 IDE 内部的。
虽然枚举系统中的所有进程,并且判断进程文件名是否是 Delphi32.exe 也似乎可行,但
是这会在程序执行的时候产生明显的延迟,所以目前为止,我还没有发现使用这种方法的
实例。
只要了解了这些,破解控件就成为了可能。实际进行破解的时候,需要两个重
要的工具软件:DeDe 2.50 和 Ultra Edit,前者用来分析 DCU 文件,后者用来对二进制
文件进行编辑。
下面,我将利用破解 JF Control Delphi 版本的实际例子来说明破解的方法。
JF Control 的未破解版本可以在
http://www.jfactivesoft.com/spindex.htm 下载。
安装好这套控件以后,我们首先来分析它所有的 DCU 之间的关系。判断限制
条件的部分必然要被所有其它单元所使用,这样才能保证不管在程序中引用了哪一个单元
都能够保证程序不能在 IDE 外执行。当然,寻找这个单元并不一定需要使用 DeDe 打开
所有 DCU。发现 Delphi\Lib\JFMain.dcu 了吗?这就是一个再明显不过的标志:这是一个
主单元,限制条件有很大可能就是在这里判断的。好,我们再使用另外一招:使用资源管
理器在 Delphi\Lib 目录中对文件进行搜索,条件是文件内容包含 TAppBuilder。如果在
程序中要查找 TAppBuilder 窗口类,就必须用到 FindWindow 函数,这个函数要求传递
窗口类的名字字符串,在 DCU 中应当有相应的字符串存在。查找的结果,符合条件的文
件只有两个:JFCtrls_d5.dcp 和 JFMain.dcu。DCP 是 Delphi Component Package 的缩
写,是在 Delphi IDE 内部使用的控件包,既然是内部使用的,根本不用去管它。但是,
另外一个文件则证明了我们刚才的判断,好,准备破解。
运行 DeDe 程序,在 Dumper 菜单中选择 DCU Dumper,在打开文件对话框中
选择 JFMain.dcu。处理完毕以后,在反编译的文本框中全选所有文本并且复制,然后粘
贴到记事本中。在记事本中查找字符串 TAppBuilder。寻找的结果好像并不太令人满意:
const
szTAppBuilder:System.AnsiString = 'О惫歼??? {@_NF_7E5+$8};
原来这个字符串是一个常量的名字。常量的内容是不可识别的字符串,显然,
加密了。但是不要着急,这个字符串的内容并不重要了。偶然向下翻了一屏,惊喜就会出
现:
function JfDelphiIDERunning: System.Boolean;
万万没想到这个程序编写的居然如此明显。现在看一看这个函数的内容,千万
别被骗了。这个函数内嵌一个函数:
function CnvString (AStr: System.AnsiString): System.AnsiString;
这就是负责把刚才我们看到的加密字符串解密的函数。继续向下看,函数的主
体调用了 FindWindow,GetWindowText,EnumChildWindows,功能确实符合这个函数的名
字。
下面,我们要做的并不是破解 CnvString 函数,因为要想理解这个函数的算
法还是有一些难度的,另外,这个函数是内嵌函数,也就是说,在这个单元的其他地方是
不需要这个函数的。实际上,我们只要修改 JfDelphiIDERunning 的代码,让它只返回
true 就可以了。
如果有汇编语言的基础,这段简单的程序很容易写出来。如果不会汇编语言,
也可以很容易解决这个问题:启动 Delphi,开始一个新的工程,创建一个单元,创建一
个如下的函数:
function CrackStub: Boolean;
begin
Result:= true;
end;
然后编译程序。用 DeDe 打开这个函数所在的 DCU 文件,获得汇编代码:
B0 01 C3。
下面,我们记录 JfDelphiIDERunning 入口点的代码,应当记录足够长的特征
代码,否则可能在后面的二进制查找中获得多个结果。我记录的入口点代码是:
55 8B EC 81 C4 E8 FE FF FF 53 56 57 33 C0 89 85 E8 FE FF FF 89 85 EC FE FF FF
89 85 F0 FE FF FF 89 85 F4 FE FF FF 89 85 F8 FE FF FF 89 85 FC FE FF FF。
启动 Ultra Edit,打开 JFMain.dcu,使用二进制 / 十六进制寻找功能,搜索
记录的特征代码。找到以后,在此搜索,确认特征代码唯一。下面,把入口点位置的代码
修改为我们的代码。后面的代码我们不需要修改,因为 CPU 执行完 B0 01 C3 就返回了,
根本不会继续执行。修改完毕,保存文件。我们可以使用 Delphi 打开它的 Demo 程序,
然后编译,退出 Delphi,运行 Demo 程序,程序正常启动。破解成功。
这种对 DCU 文件的破解其实还是有一些限制的:不能使用 BPL 动态程序包。
BPL 文件实际上是可执行文件的结构,破解方法和 DCU 文件有些区别,破解方法不在这里
讨论。
(待续)
来自:悲酥清风, 时间:2001-11-8 19:21:00, ID:717209
不知道文章里面的CJ是不是DFW里的CJ:)
*****************************************************************************
标 题:SDL suite 5.5 (11千字)
发信人:1212
时 间:2001-4-2 16:11:21
详细信息:
SDL控件组也是不错的,可以做化学分子结构图;信号FFT分析;画科学工程图等等。
和ABAKUS一样,其源码难以得到,极其困难!!!
有谁有的话请发送到testdog@sina.com谢谢。
这次是SDL Suite 5.5。
表现症状:编译生成的程序也要在Delphi正在运行的情况下才会运行,不然的话会弹出对话框,
按OK后有两种表现,一种是直接退出;一种是运行程序但在它的控件上显示一串文字。
但是不管delphi是不是运行,程序运行时鼠标放在它的控件上都会有hint,
无论你在编程的时候有没有关掉showhint属性,它都要显示!
从CJ那儿下载回来的有一个crack,但是并没有破掉hint。
工具:Dede250,UltraEdit。
作者:renamed to jkl
这次所有的DCU文件都要用Dede250的DCU Dumper去Dumpe一下,不像Abakus201只在一个文件中。
步骤是一样的,以rchart.dcu为例。
1。把dumpe得到的文本文件用Ultraedit打开,凭感觉先查run,delphi,running啥的,哈哈,果然!
function DelphiIsRunning: System.Boolean;
var
Result: System.Boolean;
H0: WinProcs.HWND;
H1: WinProcs.HWND;
H2: WinProcs.HWND;
H3: WinProcs.HWND;
H4: WinProcs.HWND;
H5: WinProcs.HWND;
H6: WinProcs.HWND;
H7: WinProcs.HWND;
H8: WinProcs.HWND;
H9: WinProcs.HWND;
const
A1:array[$0..$C] of System.Char = raw[$0..$C]at $1AF0
0: TApplication.[54 41 70 70 6C 69 63 61 74 69 6F 6E 00|K5 A1{0x1F6};
A2:array[$0..$D] of System.Char = raw[$0..$D]at $1AFD
0: TAlignPalette.[54 41 6C 69 67 6E 50 61 6C 65 74 74 65 00|K5 A2{0x1F7};
A3:array[$0..$12] of System.Char = raw[$0..$12]at $1B0B
00: TPropertyInspect[54 50 72 6F 70 65 72 74 79 49 6E 73 70 65 63 74|K5 A3{0x1F8}
10: or. |6F 72 00|;
A4:array[$0..$B] of System.Char = raw[$0..$B]at $1B1E
0: TAppBuilder.[54 41 70 70 42 75 69 6C 64 65 72 00|K5 A4{0x1F9};
T0:array[$0..$A] of System.Char = raw[$0..$A]at $1B2A
0: Delphi 2.0.[44 65 6C 70 68 69 20 32 2E 30 00|K5 T0{0x1FA};
T1:array[$0..$6] of System.Char = raw[$0..$6]at $1B35
0: Delphi.[44 65 6C 70 68 69 00|K5 T1{0x1FB};
T2:array[$0..$8] of System.Char = raw[$0..$8]at $1B3C
0: Delphi 3.[44 65 6C 70 68 69 20 33 00|K5 T2{0x1FC};
T3:array[$0..$A] of System.Char = raw[$0..$A]at $1B45
0: C++Builder.[43 2B 2B 42 75 69 6C 64 65 72 00|K5 T3{0x1FD};
T4:array[$0..$8] of System.Char = raw[$0..$8]at $1B50
0: Delphi 4.[44 65 6C 70 68 69 20 34 00|K5 T4{0x1FE};
T5:array[$0..$C] of System.Char = raw[$0..$C]at $1B59
0: C++Builder 4.[43 2B 2B 42 75 69 6C 64 65 72 20 34 00|K5 T5{0x1FF};
T6:array[$0..$8] of System.Char = raw[$0..$8]at $1B66
0: Delphi 5.[44 65 6C 70 68 69 20 35 00|K5 T6{0x200};
begin
00000000 : 53 PUSH EBX
00000001 : 56 PUSH ESI
00000002 : 57 PUSH EDI
00000003 : 55 PUSH EBP
00000004 : 83 C4 EC ADD ESP,-20
00000007 : 68(00 00 00 00 PUSH T0{0x1FA}
0000000C : 68(00 00 00 00 PUSH A1{0x1F6}
00000011 : E8(00 00 00 00 CALL FindWindow{0xA9}
00000016 : 8B D8 MOV EBX,EAX
00000018 : 68(00 00 00 00 PUSH T1{0x1FB}
0000001D : 68(00 00 00 00 PUSH A1{0x1F6}
00000022 : E8(00 00 00 00 CALL FindWindow{0xA9}
00000027 : 8B F0 MOV ESI,EAX
00000029 : 68(00 00 00 00 PUSH T2{0x1FC}
0000002E : 68(00 00 00 00 PUSH A1{0x1F6}
00000033 : E8(00 00 00 00 CALL FindWindow{0xA9}
00000038 : 89 44 24 04 MOV DWORD PTR [ESP+4],EAX
0000003C : 68(00 00 00 00 PUSH T3{0x1FD}
00000041 : 68(00 00 00 00 PUSH A1{0x1F6}
00000046 : E8(00 00 00 00 CALL FindWindow{0xA9}
0000004B : 89 04 24 MOV DWORD PTR [ESP],EAX
0000004E : 68(00 00 00 00 PUSH T4{0x1FE}
00000053 : 68(00 00 00 00 PUSH A1{0x1F6}
00000058 : E8(00 00 00 00 CALL FindWindow{0xA9}
0000005D : 89 44 24 08 MOV DWORD PTR [ESP+8],EAX
00000061 : 68(00 00 00 00 PUSH T5{0x1FF}
00000066 : 68(00 00 00 00 PUSH A1{0x1F6}
0000006B : E8(00 00 00 00 CALL FindWindow{0xA9}
00000070 : 89 44 24 0C MOV DWORD PTR [ESP+12],EAX
00000074 : 68(00 00 00 00 PUSH T6{0x200}
00000079 : 68(00 00 00 00 PUSH A1{0x1F6}
0000007E : E8(00 00 00 00 CALL FindWindow{0xA9}
00000083 : 89 44 24 10 MOV DWORD PTR [ESP+16],EAX
00000087 : 6A 00 PUSH $00
00000089 : 68(00 00 00 00 PUSH A2{0x1F7}
0000008E : E8(00 00 00 00 CALL FindWindow{0xA9}
00000093 : 8B F8 MOV EDI,EAX
00000095 : 6A 00 PUSH $00
00000097 : 68(00 00 00 00 PUSH A3{0x1F8}
0000009C : E8(00 00 00 00 CALL FindWindow{0xA9}
000000A1 : 8B E8 MOV EBP,EAX
000000A3 : 6A 00 PUSH $00
000000A5 : 68(00 00 00 00 PUSH A4{0x1F9}
000000AA : E8(00 00 00 00 CALL FindWindow{0xA9}
000000AF : 85 DB TEST EBX,EBX
000000B1 : 75 26 JNE +38; (0xD9)
000000B3 : 85 F6 TEST ESI,ESI
000000B5 : 75 22 JNE +34; (0xD9)
000000B7 : 83 3C 24 00 CMP DWORD PTR [ESP],0
000000BB : 75 1C JNE +28; (0xD9)
000000BD : 83 7C 24 04 00 CMP DWORD PTR [ESP+4],0
000000C2 : 75 15 JNE +21; (0xD9)
000000C4 : 83 7C 24 08 00 CMP DWORD PTR [ESP+8],0
000000C9 : 75 0E JNE +14; (0xD9)
000000CB : 83 7C 24 0C 00 CMP DWORD PTR [ESP+12],0
000000D0 : 75 07 JNE +7; (0xD9)
000000D2 : 83 7C 24 10 00 CMP DWORD PTR [ESP+16],0
000000D7 : 74 0C JE +12; (0xE5)
000000D9 : 85 FF TEST EDI,EDI
000000DB : 74 08 JE +8; (0xE5)
000000DD : 85 ED TEST EBP,EBP
000000DF : 74 04 JE +4; (0xE5)
000000E1 : 85 C0 TEST EAX,EAX
000000E3 : 75 04 JNE +4; (0xE9)
000000E5 : 33 C0 XOR EAX,EAX
000000E7 : EB 02 JMP +2; (0xEB)
000000E9 : B0 01 MOV AL,$01
000000EB : 83 C4 14 ADD ESP,20
000000EE : 5D POP EBP
000000EF : 5F POP EDI
000000F0 : 5E POP ESI
000000F1 : 5B POP EBX
000000F2 : C3 RET NEAR
end;
上面调用findwindow在找delphi或bcb的不同版本呢。要是找到一个的话就 MOV AL,$01
这样继续查找DelphiIsRunning,看它在那里调用:
00004377 : 8B 4D 10 MOV ECX,DWORD PTR [EBP+16]
0000437A : 8B 55 E8 MOV EDX,DWORD PTR [EBP-24]
0000437D : 8B 45 EC MOV EAX,DWORD PTR [EBP-20]
00004380 : E8(00 00 00 00 CALL TCanvas.LineTo{0x6F}
00004385 : E8(00 00 00 00 CALL DelphiIsRunning{0x201}
0000438A : 84 C0 TEST AL,AL
0000438C : 0F 85 B1 00 00 00 JNE +177; (0x4443)
00004392 : 8B 45 EC MOV EAX,DWORD PTR [EBP-20]
00004395 : 8B 40 0C MOV EAX,DWORD PTR [EAX+12]
00004398 : BA FF FF FF 00 MOV EDX,$00FFFFFF
调用 00004385 : E8(00 00 00 00 CALL DelphiIsRunning{0x201}
后有 test al,al
如果 al=1 的话,就表明delphi正在运行,那么我们就把这一句用 mov al,1代替好了(机器码B001)。
在DCU文件中这个call DelphiIsRunning是要由编译器来动态连接其地址的,所以没法nop掉这个调用。
在所有的dcu文件中用同样的方法查找并替换就可以了,当然 test al,al后的下一条语句有的DCU文件和这里的不同,
没关系,只改 test al,al。
2。还有一个问题,它的hint总是要出现,告诉人们您正在用的是SDL公司的未注册版本,整个世界都要为之改变呢。
改掉它!查找shareware,copyright,unregister之类的东西,查到与copyright有关的:
function getCopyRightStr: System.AnsiString;
var
result Result: System.AnsiString;
AuxStr: System.AnsiString;
i: System.Integer;
begin
00000000 : 55 PUSH EBP
00000001 : 8B EC MOV EBP,ESP
00000003 : 6A 00 PUSH $00
00000005 : 6A 00 PUSH $00
00000007 : 53 PUSH EBX
00000008 : 56 PUSH ESI
00000009 : 57 PUSH EDI
0000000A : 8B F8 MOV EDI,EAX
0000000C : 33 C0 XOR EAX,EAX
0000000E : 55 PUSH EBP
0000000F : 68(72 00 00 00 PUSH getCopyRightStr{0x1F2}+$00000072
00000014 : 64 FF 30 PUSH DWORD PTR FS:[EAX]
00000017 : 64 89 20 MOV DWORD PTR FS:[EAX],ESP
0000001A : 8D 45 FC LEA EAX,DWORD PTR [EBP-4]
0000001D : E8(00 00 00 00 CALL @LStrClr{0xE2}
00000022 : BE 87 FF FF FF MOV ESI,$FFFFFF87
00000027 : BB(78 00 00 00 MOV EBX,ShareW{0x1F1}+$00000078
0000002C : 8D 45 F8 LEA EAX,DWORD PTR [EBP-8]
0000002F : 33 D2 XOR EDX,EDX
00000031 : 8A 13 MOV DL,BYTE PTR [EBX]
00000033 : 8A 92(00 00 00 00 MOV DL,BYTE PTR [EDXCTDecode{0x1EF}]
00000039 : E8(00 00 00 00 CALL @LStrFromChar{0xE3}
0000003E : 8B 55 F8 MOV EDX,DWORD PTR [EBP-8]
00000041 : 8D 45 FC LEA EAX,DWORD PTR [EBP-4]
00000044 : E8(00 00 00 00 CALL @LStrCat{0xE4}----------这是在拼凑那个hint呢
00000049 : 4B DEC EBX
0000004A : 46 INC ESI
0000004B : 75 DF JNE -33; (0x2C)--------------在这里改!跳到call @LStrAsg{0xE5}后面的那句
0000004D : 8B C7 MOV EAX,EDI
0000004F : 8B 55 FC MOV EDX,DWORD PTR [EBP-4]
00000052 : E8(00 00 00 00 CALL @LStrAsg{0xE5}---------拼完了就显示,那么跳过它!
00000057 : 33 C0 XOR EAX,EAX
00000059 : 5A POP EDX
0000005A : 59 POP ECX
0000005B : 59 POP ECX
0000005C : 64 89 10 MOV DWORD PTR FS:[EAX],EDX
0000005F : 68(79 00 00 00 PUSH getCopyRightStr{0x1F2}+$00000079
00000064 : 8D 45 F8 LEA EAX,DWORD PTR [EBP-8]
00000067 : BA 02 00 00 00 MOV EDX,$00000002
0000006C : E8(00 00 00 00 CALL @LStrArrayClr{0xE6}
00000071 : C3 RET NEAR
00000072 : E9(00 00 00 00 JMP @HandleFinally{0xE7}
00000077 : EB EB JMP -21; (0x64)
00000079 : 5F POP EDI
0000007A : 5E POP ESI
0000007B : 5B POP EBX
0000007C : 59 POP ECX
0000007D : 59 POP ECX
0000007E : 5D POP EBP
0000007F : C3 RET NEAR
end;
数一数后知道 75 DF 改成 EB 0A
这样就没有hint了,如果您想要自己的hint,请用别的办法吧,可以做得到的。