软件凝聚的开发者的心血,几乎每个好用的共享软件都被破解过,保护软件免遭破解,是每个软件作者的心愿。无论你限制软件的使用次数还是天数,破解者只需要用反编译软件,直接把exe文件中的次数限制修改成无限,或修改跳转指令,使注册码码无效。 |
如何保护自己的软件免遭破解呢?程序运行时自我校验是比较好的办法。 |
一、原理如下: |
软件开发者要有两个可执行文件,一个是CRC.EXE,负责校验共享软件的EXE文件,获得其校验码,写入文件SYSTEM.DLL(故意取这个名字,迷惑破解者,校验码最好加密,本文未加密)。另一个是SELFCRC.EXE,即我们编写的共享软件,它具有自我进行校验的功能。共享软件发布时,至少要包含两个文件:SELFCRC.EXE和SYSTEM.DLL。 |
共享软件每次运行时,首先进行自我校验,结果跟SYSTEM.DLL中的校验码比较,正确则正常执行,错误则发出警告后删除自己。如果用户删除了SYSTEM.DLL文件,程序也会拒绝执行并删除自己。这样可以保证只要破解者修改了EXE文件,该文件就不能运行了。 |
二、CRC.EXE的界面以及源代码: |
CRC.EXE的设计界面 |
unit Unit1; |
interface |
uses |
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, |
StdCtrls; |
type |
TForm1 = class(TForm) |
Button1: TButton; |
Label1: TLabel; |
OpenDialog1: TOpenDialog; |
Edit1: TEdit; |
procedure Button1Click(Sender: TObject); |
private |
{ Private declarations } |
public |
{ Public de clarations } |
end; |
var |
Form1: TForm1; |
implementation |
{$R *.DFM} |
//定义校验函数 |
function GetCheckSum(FileName : string) : DWORD; |
var |
F : File of DWORD; |
P : Pointer; |
Fsize : DWORD; |
Buffer : Array [0..500] of DWORD; |
begin |
FileMode := 0; |
AssignFile(F,FileName); |
Reset(F); |
Seek(F,FileSize(F) div 2); |
Fsize := FileSize(F) -1 -FilePos(F); |
if Fsize > 500 then Fsize := 500; |
BlockRead(F,Buffer,Fsize); |
Close (F); |
P := @Buffer; |
asm |
xor eax,eax |
xor ecx,ecx |
mov edi,p |
@again: |
add eax,[edi + 4*ecx] |
inc ecx |
cmp ecx,fsize |
jl @again |
mov @result,eax |
end; |
end; |
procedure TForm1.Button1Click(Sender: TObject); |
var |
CRCResult :dword; |
begin |
//打开对话框选择文件 |
if OpenDialog1.Execute then |
begin |
CRCResult:=GetCheckSum(OpenDialog1.FileName); |
if CRCResult<>0 then Edit1.text:=IntToHex(CRCResult,8) |
else ShowMessage('The CRC check failed'); |
end; |
end; |
end. |
三、SELFCRC.EXE的界面以及源程序 |
SELFCRC.EXE的设计界面 |
unit Unit1; |
interface |
uses |
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, |
StdCtrls; |
type |
TForm1 = class(TForm) |
Button1: TButton; |
Label1: TLabel; |
Label2: TLabel; |
procedure FormCreate(Sender: TObject); |
procedure Button1Click(Sender: TObject); |
private |
{ Private declarations } |
public |
{ Public de clarations } |
end; |
var |
Form1: TForm1; |
implementation |
{$R *.DFM} |
//定义删除自己的过程,动态创建并执行批处理文件 |
procedure deleteme(filename:string); |
var |
batfile:textfile; |
begin |
assignfile(batfile,'./delme.bat'); |
rewrite(batfile); |
writeln(batfile,'@echo off'); |
writeln(batfile,':loop'); |
writeln(batfile,'del "'+filename+'"'); |
writeln(batfile,'if exist ./file.exe goto loop'); |
writeln(batfile,'del ./delme.bat'); |
closefile(batfile); |
winexec('./delme.bat',SW_HIDE); |
end; |
//定义校验函数 |
function GetCheckSum(FileName : string) : DWORD; |
//代码同上,省略。 |
procedure TForm1.FormCreate(Sender: TObject); |
var |
OutFile,batfile:Textfile; |
Fname,CRCTrue:string; |
CRCResult :dword; |
begin |
form1.Visible :=false; |
Fname:='System.dll'; |
if not fileexists(Fname) then begin |
application.messagebox('错误:因丢失DLL文件,软件将退出。','系统警告',16); |
//删除自己 |
deleteme(application.exename); |
application.Terminate; |
end |
else begin |
assignfile(outfile,fname); |
reset(outfile); |
//读取正确的校验码到CRCTrue |
readln(outfile,CRCTrue); |
closefile(outfile); |
CRCResult:=getchecksum(application.exename); |
if CRCResult<>0 then begin |
//在实际应用中,以下的提示对话框不要显示 |
showMessage('CRC校验结果是:'+IntToHex(CRCResult,8)); |
//破解后校验结果必然不正确.程序拒绝执行并删除自己 |
if IntToHex(CRCResult,8)<>CRCTrue then |
begin |
ShowMessage('CRC结果错误,程序将退出!'); |
application.Terminate ; |
deleteme(application.exename); |
end |
else begin |
ShowMessage('CRC结果正确!'); |
end; |
end; |
end; |
end; |
procedure TForm1.Button1Click(Sender: TObject); |
begin |
close; |
end; |
end. |
四、在实际应用中,通过文件校验结合限制用户的使用次数和天数,以及只能在一台机器上使用等办法,可以更好地保护你的共享软件免遭破解。以上代码在WIN98,Delphi 5.0中调试通过。 |