问题比较多,第2个是如何用自己的加密框给exe文件加密

如题!
[3 byte] By [rocxu007] at [2008-1-9]
# 1
你先建一个输入密码框(点击exe文件会弹出这个对话框) 输入不正确不能运行exe 这称之为外部加密!
先定义一个单元:
unit UnitLockConst;

interface

const
MaxBufferSize = 32768; {磁盘缓冲区的大小}
PassSize = 15; {密码的最大长度}
CFlag = 'PROTECT'; {文件名,可以自定义}

{文件加锁记录}
type
TLockedFile = record
{加壳标志,由用户自定义}
Flag: string[Length(CFlag)];
{文件名}
Name: ShortString;
{标题}
Caption: string[63];
{密码}
PassWord: string[PassSize];
{附加代码的长度}
AdditionalCodeLen :integer;
end;

implementation

end.

再创建输入密码对话框,窗体上放上edit和button
在private下定义:
TempFileName: string; {临时文件}
iTempFileName: Integer; {临时文件的句柄}
TryTimes: Byte; {尝试密码次数}
procedure LockFile;
function StringEncrypt(S: string): string;
创建函数
{运行文件,并防止拷贝该可执行文件}
function WinExecAndWait32(CommandLine: string; Visibility: Integer): Cardinal;
var
WorkDir: string;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
{应用程序的工作目录}
WorkDir := ExtractFileDir(Application.ExeName);
FillChar(StartupInfo, Sizeof(StartupInfo), #0);
StartupInfo.cb := Sizeof(StartupInfo);
{设置进程显示标志}
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := Visibility;
{创建进程,执行该文件}
if not CreateProcess(nil,
PChar(CommandLine), {指向命令行字符串}
nil, {指向进程安全属性}
nil, {指向线程安全属性}
True, {句柄继承标志}
CREATE_NEW_CONSOLE or {创建标志}
NORMAL_PRIORITY_CLASS,
nil, {指向环境块}
PChar(WorkDir), {指向当前目录}
StartupInfo, {指向结构STARTUPINFO }
ProcessInfo) {指向结构PROCESS_INFO }
then Result := INFINITE {-1} else
begin
FormPassDialog.Hide;{隐藏输入密码的窗口}
{防止拷贝该临时文件}
FormPassDialog.iTempFileName := FileOpen(FormPassDialog.TempFileName, fmShareExclusive);
{设置应用程序的风格}
SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
{提交系统控制权}
Application.ProcessMessages;
{等待刚才创建的进程运行结束}
WaitforSingleObject(ProcessInfo.hProcess, INFINITE);
{获取进程的退出代码}
GetExitCodeProcess(ProcessInfo.hProcess, Result);
{关闭进程}
CloseHandle(ProcessInfo.hProcess);
{关闭进程}
CloseHandle(ProcessInfo.hThread);
{退出本应用程序}
FormPassDialog.Close;
end;
end;

{自定义的加密运算,对密码进行简单的加密}
function TFormPassDialog.StringEncrypt(S: string): string;
var
i: Byte;
begin
for i := 1 to Length(S) do
S[i] := Char(i or $75 xor ord(S[i]));
Result := S;
end;

{还原加壳前的程序,并执行它}
procedure TFormPassDialog.LockFile;
var
I,iSourceFile, iTargetFile: Integer;
NumRead, NumWritten: Integer;
MyBuf: array[0..MaxBufferSize - 1] of Char;
LockedFile: TLockedFile;
s: string;
begin
{打开当前的EXE文件}
iSourceFile := FileOpen(Application.ExeName, fmOpenRead or fmShareDenyNone);
try
{定位到密码等信息}
FileSeek(iSourceFile, -SizeOf(LockedFile), soFromEnd);
{读取密码等信息}
FileRead(iSourceFile, LockedFile, SizeOf(LockedFile));
{如果是指定的标志}
if LockedFile.Flag = CFlag then
begin
{检测密码是否正确}
if LockedFile.PassWord = StringEncrypt(Edit1.Text) then
begin
{定位到被加壳程序的开始}
FileSeek(iSourceFile, LockedFile.AdditionalCodeLen,
soFromBeginning);
{临时文件是在原文件名之前加上"-"}
TempFileName := '_' + LockedFile.Name;
{建立临时文件}
iTargetFile := FileCreate(TempFileName);
try
repeat {把当前EXE文件内嵌的被加壳程序拷贝到临时文件中}
NumRead := FileRead(iSourceFile, MyBuf, SizeOf(MyBuf));
NumWritten := FileWrite(iTargetFile, MyBuf, NumRead);
until (NumRead = 0) or (NumWritten <> NumRead);
finally
{最后SizeOf(LockedFile)字节是密码等信息,不需要读取到临时文件中}
FileSeek(iTargetFile, -SizeOf(LockedFile), soFromEnd);
SetEndOfFile(iTargetFile);
FileClose(iTargetFile);
end;
{此时,临时文件实际上就是被加壳的原程序}
{设置文件为隐藏}
FileSetAttr(TempFileName, faHidden);
{当前EXE文件的参数作为临时文件的执行参数}
s := TempFileName;
for i:=1 to ParamCount do
s:=s+' '+Paramstr(i);
{执行临时文件,并等待其结束}
WinExecAndWait32(s, SW_SHOWNORMAL);
end else
begin
{检查尝试密码次数}
if TryTimes >= 3 then
begin
FileClose(iSourceFile);
Close;
end else
begin
inc(TryTimes);
Label1.Caption := Format('密码错误,还可以重试%d次', [4 - TryTimes]);
Edit1.Text := '';
end;
end;
end
else Label1.Caption := '没有发现加密记录';
finally
FileClose(iSourceFile);
end;
end;

在确认button的onclick事件上写
{判断密码是否正确,并脱壳后执行}
LockFile;

当然窗体创建和销毁时还需要完成这些工作
procedure TFormPassDialog.FormCreate(Sender: TObject);
begin
TryTimes := 1;
TempFileName := '_' + ExtractFileName(ParamStr(0));
end;
procedure TFormPassDialog.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{关闭文件句柄}
if iTempFileName > 0 then FileClose(iTempFileName);
{删除临时文件}
if FileExists(TempFileName) then DeleteFile(TempFileName);
end;
这是第一步,完成了密码验证壳!

接着我们要做的时如何加密:
winxkm-蹩脚的程序员 at 2007-10-19 > top of Msdn China Tech,Delphi,VCL组件开发及应用...
# 2
新建一个project,
在窗体上加上选择文件的edit和opendialog对话框。
在加上checkbox 用来确认加壳之前是否备份原文件为 *.TMP
还有2个密码框edit,用来输入密码和确认密码!
2个button 一个是加壳,另一个是解壳!

好了开始写代码:
在private下添加:
private
sExeFilename, sPassword: string;{被加壳的文件名,密码}
procedure LockFile;
procedure UnLockFile;
procedure BusyStatus;
procedure CopyFile(FromFile, ToFile: string);
procedure FileAddShellOrNot(FileName: string);
function StringEncrypt(S: string): string;

{设置控件无效,表示正忙}
procedure TForm1.BusyStatus;
begin
EditPassword1.Enabled := False;
EditPassword2.Visible := False;
LabelPassword2.Visible := False;
buttonEncrypt.Enabled := False;
ButtonUnEncrypt.Enabled:= False;
EditFileName.Enabled := False;
ButtonOpenFile.Enabled := False;
end;

{自定义的加密运算,对密码进行简单的加密}
function TForm1.StringEncrypt(S: string): string;
var
i: Byte;
begin
for i := 1 to Length(S) do
S[i] := Char(i or $75 xor ord(S[i]));
Result := S;
end;

{拷贝文件}
procedure TForm1.CopyFile(FromFile, ToFile: string);
var
OpStruc: TSHFileOpStruct;
FromBuf, ToBuf: packed array[0..MaxBufferSize - 1] of char;
begin
fillchar(frombuf, sizeof(frombuf), 0);
fillchar(tobuf, sizeof(tobuf), 0);
StrpCopy(frombuf, fromfile);
StrpCopy(tobuf, tofile);
with OpStruc do
begin
wnd := handle;
wFunc := FO_COPY;
pfrom := @frombuf;
pto := @tobuf;
fFlags := FOF_SILENT or FOF_NOCONFIRMATION;
fAnyOperationsAborted := false;
hNameMappings := nil;
lpszProgressTitle := nil;
end;
{拷贝文件Shell操作}
ShFileOperation(OpStruc);
end;

{取文件的大小}
function GetFileSize2(filename:string):integer;
var
sr:TSearchRec;
begin
if (findfirst(filename,faAnyfile and not faDirectory,sr)<>0) then result:=0
else result:=sr.size;
findclose(sr);
end;

{加壳}
procedure TForm1.LockFile;
var
FsName, FtName, FbName, FCode: string;
iTargetFile, iSourceFile: Integer;
MyBuf: array[0..MaxBufferSize - 1] of Char;
LockedFile: TLockedFile;
NumRead, NumWritten: Integer;
bSuccessed: Boolean;
begin
BusyStatus;{设置按钮无效,表示正忙}
FsName := sExeFilename;{被加壳的文件名}
FbName := FsName + '.TMP'; {被加壳文件的备份文件名}
{附加代码的文件名}
FCode := ExtractFilePath(paramstr(0))+'DialogPass.exe';
if not fileexists(FCode) then
raise exception.create(FCode+'文件没找到.');

{如果需要备份文件}
if CheckBox1.Checked then
begin
CopyFile(FsName, FbName);
end;
iSourceFile := FileOpen(FsName, fmOpenRead or fmShareDenyNone);
try
with LockedFile do
begin
Flag := CFlag;{自定义的标志}
Name := ExtractFileName(FsName);{文件名}
Caption := '';{标题,保留没有使用}
Password := StringEncrypt(sPassword);{密码}
AdditionalCodeLen := GetFileSize2(FCode);{附加代码的长度}
end;
{临时文件是在被加壳文件名前加"__"}
FtName := ExtractFilePath(FsName) + '__' + LockedFile.Name;
CopyFile(FCode, FtName);{先拷贝附加代码}

{在附加代码之后写被加壳文件}
bSuccessed := False;
iTargetFile := FileOpen(FtName, fmOpenReadWrite);
try
{定位至目标文件的末尾}
FileSeek(iTargetFile, 0, soFromEnd);
repeat
NumRead := FileRead(iSourceFile, MyBuf, SizeOf(MyBuf));
NumWritten := FileWrite(iTargetFile, MyBuf, NumRead);
until (NumRead = 0) or (NumWritten <> NumRead);
{最后写上密码等信息}
FileWrite(iTargetFile, LockedFile, SizeOf(LockedFile));
bSuccessed := True;
showmessage('文件加密完成');
finally
FileClose(iTargetFile);
end;
finally
FileClose(iSourceFile);
end;
if bSuccessed then
begin
{删除被加壳的文件}
DeleteFile(FsName);
{把临时文件重命名为被加壳的文件}
RenameFile(FtName, FsName);
end;
{重新检查文件是否已加壳}
FileAddShellOrNot(EditFileName.Text);
end;

{脱壳}
procedure TForm1.UnLockFile;
var
FsName, FtName: string;
iSourceFile, iTargetFile: Integer;
NumRead, NumWritten: Integer;
MyBuf: array[0..MaxBufferSize - 1] of Byte;
LockedFile: TLockedFile;
bSuccessed: Boolean;
begin
bSuccessed := False;
with Form1 do
begin
BusyStatus;
FsName := sExeFilename;{已加壳的文件名}
iSourceFile := FileOpen(FsName, fmOpenRead or fmShareDenyNone);
try
{定位到密码等信息的结构}
FileSeek(iSourceFile, -SizeOf(LockedFile), soFromEnd);
{读取密码等信息}
FileRead(iSourceFile, LockedFile, SizeOf(LockedFile));
{如果密码正确}
if LockedFile.Password = StringEncrypt(sPassword) then
begin
{临时文件是在已加壳文件名前加"__"}
FtName := ExtractFilePath(FsName) + '__' + LockedFile.Name;
iTargetFile := FileCreate(FtName);{创建临时文件}
try
{定位到加壳前原文件的起始位置}
FileSeek(iSourceFile, LockedFile.AdditionalCodeLen ,
soFromBeginning);
{把属于原文件的内容拷贝到临时文件中}
repeat
NumRead := FileRead(iSourceFile, MyBuf, SizeOf(MyBuf));
NumWritten := FileWrite(iTargetFile, MyBuf, NumRead);
until (NumRead = 0) or (NumWritten <> NumRead);
bSuccessed := True;
showmessage('文件解密完成');
finally
{最后SizeOf(LockedFile)字节是密码等信息,不需要读取到临时文件中}
FileSeek(iTargetFile, -SizeOf(LockedFile), soFromEnd);
SetEndOfFile(iTargetFile);
FileClose(iTargetFile);
end;
end else
begin
ShowMessage('密码不正确.');
end;
finally
FileClose(iSourceFile);
end;
if bSuccessed then
begin
{删除已加壳的文件}
DeleteFile(FsName);
{把临时文件改为已加壳}
RenameFile(FtName, FsName);
end;
{重新检查文件是否已加壳的文件}
FileAddShellOrNot(sExeFilename);
end;
end;

{检查文件是否已加壳}
procedure TForm1.FileAddShellOrNot(FileName: string);
var
iOpFile: Integer;
LockedFile: TLockedFile;
FileExt: string;
FileAttr: Integer;
begin
{恢复控件的状态}
EditPassword1.Enabled := True;
EditPassword2.Visible := True;
LabelPassword2.Visible := True;
buttonEncrypt.Enabled := True;
ButtonUnEncrypt.Enabled := True;
EditFileName.Enabled := True;
ButtonOpenFile.Enabled := True;
CheckBox1.Enabled := True;

FileExt := ExtractFileExt(FileName);
{如果不是可执行文件}
if StrUpper(PChar(FileExt)) <> '.EXE' then
begin
showmessage(FileName+'文件不是EXE文件');
EditFileName.Text := '';
exit;
end;
FileAttr := FileGetAttr(FileName);
{如果文件属性是只读属性}
if FileAttr and faReadOnly > 0 then
begin
{设置文件属性}
if FileSetAttr(FileName,faArchive)<>0 then
begin
showmessage('设置'+FileName+'文件的属性出错!');
EditFileName.Text := '';
exit;
end;
end;
{打开待加壳或脱壳的文件}
iOpFile := FileOpen(FileName, fmOpenRead);
try
{定位到加密结构}
FileSeek(iOpFile, -SizeOf(LockedFile), soFromEnd);
{读密码等信息}
FileRead(iOpFile, LockedFile, SizeOf(LockedFile));
{检查标志,判断是否已加壳}
if LockedFile.Flag = CFlag then
begin
{设置"脱壳"按钮等控件无效}
buttonEncrypt.Enabled := False;
EditPassword2.Visible := False;
LabelPassword2.Visible:= False;
CheckBox1.Enabled := False;
end
else
{设置"加壳"按钮无效}
ButtonUnEncrypt.Enabled := False;
finally
FileClose(iOpFile);
end;
end;
winxkm-蹩脚的程序员 at 2007-10-19 > top of Msdn China Tech,Delphi,VCL组件开发及应用...
# 3
如何调用:
先选择要加壳的文件EXE
点击打开对话框的button
代码:
if OpenDialog1.Execute then
begin
EditFileName.Text := OpenDialog1.FileName;
FileAddShellOrNot(EditFileName.Text);{检查是否已加壳}
end;

然后设置密码:

button的加壳代码调用:
if not FileExists(EditFileName.Text) then
begin
showmessage('文件不存在.');
exit;
end;
if EditPassword1.Text = '' then
begin
showmessage('密码不能为空.');
exit;
end;
if EditPassword1.Text <> EditPassword2.Text then
begin
showmessage('两次输入的密码不一致');
exit;
end;
sExeFilename := EditFileName.Text;
sPassword := EditPassword1.Text;
{加壳}
LockFile;

解壳是:
if not FileExists(EditFileName.Text) then
begin
showmessage('文件不存在.');
exit;
end;
if EditPassword1.Text = '' then
begin
showmessage('密码不能为空.');
exit;
end;
sExeFilename := EditFileName.Text;
sPassword := EditPassword1.Text;
{脱壳}
UnLockFile;
winxkm-蹩脚的程序员 at 2007-10-19 > top of Msdn China Tech,Delphi,VCL组件开发及应用...