線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:4637
推到 Plurk!
推到 Facebook!

利用流製作EXE檔加密器、捆綁、自解壓檔及安裝程式

答題得分者是:jow
jean2004
初階會員


發表:69
回覆:80
積分:39
註冊:2004-12-18

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-12-08 08:01:27 IP:222.135.xxx.xxx 訂閱
利用流製作EXE檔加密器、捆綁、自解壓檔及安裝程式
我們先來說一下如何製作一個EXE檔加密器吧。
EXE檔加密器的原理:建立兩個檔,一個用來添加資源到另外一個EXE檔裏面,稱為添加程式。另外一個被添加的EXE檔稱為頭檔。該程式的功能是把添加到自己裏面的檔讀出來。Windows下的EXE檔結構比較複雜,有的程式還有校驗和,當發現自己被改變後會認為自己被病毒感染而拒絕執行。所以我們把檔添加到自己的程式裏面,這樣就不會改變原來的檔結構了。我們先寫一個添加函數,該函數的功能是把一個檔當作一個流添加到另外一個檔的尾部。函數如下:
Function Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;
var
Target,Source:TFileStream;
MyFileSize:integer;
begin
try
Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareExclusive);
Target:=TFileStream.Create(TargetFile,fmOpenWrite or fmShareExclusive);
try
Target.Seek(0,soFromEnd);//往尾部添加資源
Target.CopyFrom(Source,0);
MyFileSize:=Source.Size Sizeof(MyFileSize);//計算資源大小,並寫入輔程尾部
Target.WriteBuffer(MyFileSize,sizeof(MyFileSize));
finally
Target.Free;
Source.Free;
end;
except
Result:=False;
Exit;
end;
Result:=True;
end;
有了上面的基礎,我們應該很容易看得懂這個函數。其中參數SourceFile是要添加的檔,參數TargetFile是被添加到的目標檔。
比如說把a.exe添加到b.exe裏面可以:Cjt_AddtoFile('a.exe',b.exe');如果添加成功就返回True否則返回假。
根據上面的函數我們可以寫出相反的讀出函數:
Function Cjt_LoadFromFile(SourceFile,TargetFile :string):Boolean;
var
Source:TFileStream;
Target:TMemoryStream;
MyFileSize:integer;
begin
try
Target:=TMemoryStream.Create;
Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareDenyNone);
try
Source.Seek(-sizeof(MyFileSize),soFromEnd);
Source.ReadBuffer(MyFileSize,sizeof(MyFileSize));//讀出資源大小
Source.Seek(-MyFileSize,soFromEnd);//定位到資源位置
Target.CopyFrom(Source,MyFileSize-sizeof(MyFileSize));//取出資源
Target.SaveToFile(TargetFile);//存放到文件
finally
Target.Free;
Source.Free;
end;
except
Result:=false;
Exit;
end;
Result:=true;
end;
其中參數SourceFile是已經添加了檔的檔案名稱,參數TargetFile是取出檔後保存的目標檔案名。比如說
Cjt_LoadFromFile('b.exe','a.txt');在b.exe中取出檔保存為a.txt。如果取出成功就返回True否則返回假。
打開Delphi,新建一個工程,在視窗上放上一個Edit控制項Edit1和兩個Button:Button1和Button2。Button的Caption屬性分別設置為
"確定"和"取消"。在Button1的Click事件中寫代碼:
var S:string;
begin
S:=ChangeFileExt(Application.ExeName,'.Cjt');
if Edit1.Text='790617' then
begin
Cjt_LoadFromFile(Application.ExeName,S);
{取出檔保存在當前路徑下並命名"原文件.Cjt"}
Winexec(pchar(S),SW_Show);{運行"原文件.Cjt"}
Application.Terminate;{退出程式}
end
else
Application.MessageBox('密碼不對,請重新輸入!','密碼錯誤',MB_ICONERROR MB_OK);
編譯這個程式,並把EXE檔改名為head.exe。新建一個文字檔案head.rc,內容為: head exefile head.exe,然後把它們拷貝到
Delphi的BIN目錄下,執行Dos命令Brcc32.exe head.rc,將產生一個head.res的檔,這個檔就是我們要的資源檔案,先留著。
我們的頭檔已經建立了,下面我們來建立添加程式。
新建一個工程,放上以下控制項:一個Edit,一個Opendialog,兩個Button1的Caption屬性分別設置為"選擇檔"和"加密"。在根源程式中添加一句:{$R head.res}並把head.res檔拷貝到程式當前目錄下。這樣一來就把剛才的head.exe跟程式一起編譯了。
在Button1的Cilck事件裏面寫下代碼:
if OpenDialog1.Execute then Edit1.Text:=OpenDialog1.FileName;
在Button2的Cilck事件裏面寫下代碼:
var S:String;
begin
S:=ExtractFilePath(Edit1.Text);
if ExtractRes('exefile','head',S 'head.exe') then
if Cjt_AddtoFile(Edit1.Text,S 'head.exe') then
if DeleteFile(Edit1.Text) then
if RenameFile(S 'head.exe',Edit1.Text) then
Application.MessageBox('檔加密成功!','信息',MB_ICONINFORMATION MB_OK)
else
begin
if FileExists(S 'head.exe') then DeleteFile(S 'head.exe');
Application.MessageBox('檔加密失敗!','信息',MB_ICONINFORMATION MB_OK)
end;
end;
其中ExtractRes為自定義函數,它的作用是把head.exe從資源檔案中取出來。
Function ExtractRes(ResType, ResName, ResNewName : String):boolean;
var
Res : TResourceStream;
begin
try
Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
try
Res.SavetoFile(ResNewName);
Result:=true;
finally
Res.Free;
end;
except
Result:=false;
end;
end;
注意:我們上面的函數只不過是簡單的把一個檔添加到另一個檔的尾部。實際應用中可以改成可以添加多個檔,只要根據
實際大小和個數定義好偏移位址就可以了。比如說檔捆綁機就是把兩個或者多個程式添加到一個頭檔裏面。那些自解壓程式和安裝程式的原理也是一樣的,不過多了壓縮而已。比如說我們可以引用一個LAH單元,把流壓縮後再添加,這樣檔就會變的很小。讀出來時先解壓就可以了。另外,文中EXE加密器的例子還有很多不完善的地方,比如說密碼固定為"790617",取出EXE運行後應該等它運行完畢後刪除等等,讀者可以自行修改。
jean2004
初階會員


發表:69
回覆:80
積分:39
註冊:2004-12-18

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-12-08 08:04:47 IP:222.135.xxx.xxx 訂閱
各位先進,上面的代碼實現的功能正是小弟要的,那位先進能幫忙轉成BCB的
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-12-10 14:36:43 IP:210.66.xxx.xxx 訂閱
幫你轉兩個function, 供你參考, 其他請自行改寫...

[code cpp]
//---------------------------------------------------------------------------
#ifndef fMainH
#define fMainH
//---------------------------------------------------------------------------
#include
#include
#include
#include <Forms.hpp><br />#include
//---------------------------------------------------------------------------
bool Cjt_AddtoFile(String SourceFile, String TargetFile);
bool Cjt_LoadFromFile(String SourceFile, String TargetFile);

class TForm1 : public TForm
{
__published:
TPanel *Panel1;
TButton *Button1;
public:
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
[/code]


[code cpp]
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "fMain.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
bool Cjt_AddtoFile(String SourceFile, String TargetFile)
{
if(!FileExists(SourceFile)) return false;
if(!FileExists(SourceFile)) return false;

TFileStream* Source = new TFileStream(SourceFile, fmOpenRead|fmShareExclusive);
try{
TFileStream* Target = new TFileStream(TargetFile, fmOpenRead|fmShareExclusive);
try{
Target->Seek(0, soFromEnd); //往尾部添加資源
Target->CopyFrom(Source, 0);
int MyFileSize = Source->Size sizeof(MyFileSize);//計算資源大小,並寫入輔程尾部
Target->WriteBuffer(&MyFileSize, sizeof(MyFileSize));
}
__finally{
delete Target;
}
}
__finally{
delete Source;
}
return true;
}
//---------------------------------------------------------------------------
bool Cjt_LoadFromFile(String SourceFile, String TargetFile)
{
if(!FileExists(SourceFile))return false;

TFileStream* Source = new TFileStream(SourceFile, fmOpenRead|fmShareDenyNone);
try{
int MyFileSize = 0;
Source->Seek(sizeof(MyFileSize), soFromEnd);
Source->ReadBuffer(&MyFileSize, sizeof(MyFileSize)); //讀出資源大小
Source->Seek(-MyFileSize, soFromEnd); //定位到資源位置
TMemoryStream* Target = new TMemoryStream();
try{
Target->CopyFrom(Source,MyFileSize-sizeof(MyFileSize)); //取出資源
Target->SaveToFile(TargetFile); //存放到文件
}
__finally{
delete Target;
}
}
__finally{
delete Source;
}
return true;
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner)
{
}
//---------------------------------------------------------------------------
[/code]

===================引 用 jean2004 文 章===================
各位先進,上面的代碼實現的功能正是小弟要的,那位先進能幫忙轉成BCB的
jean2004
初階會員


發表:69
回覆:80
積分:39
註冊:2004-12-18

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-12-11 14:20:46 IP:222.135.xxx.xxx 訂閱
啊,感谢jow先进的回复,结帖
系統時間:2024-04-24 3:37:11
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!