unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
ChxBackup: TCheckBox;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
SecData: integer;
arrText: array of Char;//自定义的区段实现
arrChar: array of Char;//自定义的区段拷贝
implementation
{$R *.dfm} function AttachStart: dword; stdcall; //我们定义的待填充数据
asm
push $12345678 //保存OEP地址
ret
end;
function AttachEnd: dword; stdcall;
begin
end;
{-------------------------增加区块--------------------------------}
procedure AddSection(lFileName,secname,secsize: string; lBackup: boolean); //打开exe文件,是否备份
var
hFile: THandle; //文件句柄
ImageDosHeader: IMAGE_DOS_HEADER; //DOS部首
ImageNtHeaders: IMAGE_NT_HEADERS; //映象头
ImageSectionHeader: IMAGE_SECTION_HEADER; //块表
lPointerToRawData: dword; //指向文件中的偏移
lVirtualAddress: dword; //指向内存中的偏移
i: integer; //循环变量
p: integer;//自定义区段的字符串的长
S: String;//除去自定义区段空格
BytesRead, ByteSWrite: Cardinal; //读写用参数
AttachSize: dword; //附加段大小
AttachData, ChangeData: integer; //附加段填充数据
OEP: integer; //使用过程中用到的OEP
lpBuffer: array[0..1024 * 400] of byte; {数据存储缓冲区}
StartEN, SizeEN, StartCr: dword; //PE修改后的物理地址和大小
ret: boolean;
begin
//定义附加段填充数据
AttachData := 0;
S := Trim(secname);//除去自定义区段空格
AttachSize := strtoint(secsize);//获取自定义的长度
p :=Length(S);//得到自定义区段名字长度
SetLength(arrText, p+2); //动态数组初始化
SetLength(arrChar,p);
arrText[0] :='.';
for i:=0 to p-1 do
begin
arrText[i+1] :=secname[i+1] //动态数组下标从0开始,String类数组下标从1开始
end;
arrText[p+1] := #0;
//打开文件
hFile := CreateFile(PChar(lFileName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
//校验
if hFile = INVALID_HANDLE_VALUE then
begin
ShowMessage('打开文件失败');
exit;
end;
//确认备份
if lBackup then CopyFile(PChar(lFileName), PChar(lFileName + '.bak'), False);
ret := False;
try
//读取DOS部首到ImageDosHeader
ReadFile(hFile, ImageDosHeader, SizeOf(ImageDosHeader), BytesRead, nil);
//校验
if ImageDosHeader.e_magic <> IMAGE_DOS_SIGNATURE then
begin
ShowMessage('不是有效的PE文件!');
exit;
end;
//指向映象头
SetFilePointer(hFile, ImageDosHeader._lfanew, nil, FILE_BEGIN);
//读取映向头到ImageNtHeaders
ReadFile(hFile, ImageNtHeaders, SizeOf(ImageNtHeaders), BytesRead, nil);
//校验
if ImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE then
begin
ShowMessage('不是有效的PE文件');
exit;
end;
{********************************}
{OEP=基址+原EP}
OEP := ImageNtHeaders.OptionalHeader.ImageBase + ImageNtHeaders.OptionalHeader.AddressOfEntryPoint;
{********************************}
//初始化文件中偏移和映象中偏移
lPointerToRawData := 0;
lVirtualAddress := 0;
for i := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
begin
//读取块表中信息
ReadFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), BytesRead, nil);
{********************************}
{查找原EP所在区段(原EP所在区段),记录物理偏移(初始地址),物理大小(长度)}
if ImageNtHeaders.OptionalHeader.AddressOfEntryPoint > ImageSectionHeader.VirtualAddress then;
begin
StartEN := ImageSectionHeader.PointerToRawData;
SecData := StartEN;
SizeEN := ImageSectionHeader.SizeOfRawData;
StartCr := ImageNtHeaders.OptionalHeader.ImageBase + ImageSectionHeader.VirtualAddress;
end;
{********************************}
//计算文件中偏移
if lPointerToRawData < ImageSectionHeader.PointerToRawData + ImageSectionHeader.SizeOfRawData then
lPointerToRawData := ImageSectionHeader.PointerToRawData + ImageSectionHeader.SizeOfRawData;
//计算映象中偏移
if lVirtualAddress < ImageSectionHeader.VirtualAddress + ImageSectionHeader.Misc.VirtualSize
then
lVirtualAddress := ImageSectionHeader.VirtualAddress + ImageSectionHeader.Misc.VirtualSize;
end;
{增加块,定义块各项属性}
Move(arrText, ImageSectionHeader.Name, p+2);
//设置初始属性
ImageSectionHeader.Misc.VirtualSize := AttachSize;
ImageSectionHeader.VirtualAddress := lVirtualAddress;
ImageSectionHeader.SizeOfRawData := AttachSize;
ImageSectionHeader.PointerToRawData := lPointerToRawData;
ImageSectionHeader.PointerToRelocations := 0;
ImageSectionHeader.PointerToLinenumbers := 0;
ImageSectionHeader.NumberOfRelocations := 0;
//校正新节物理偏移(物理区块对齐)
if ImageSectionHeader.VirtualAddress mod ImageNtHeaders.OptionalHeader.SectionAlignment > 0 then
ImageSectionHeader.VirtualAddress := (ImageSectionHeader.VirtualAddress div ImageNtHeaders.OptionalHeader.SectionAlignment + 1) * ImageNtHeaders.OptionalHeader.SectionAlignment;
//校正新节映象偏移(映象中区块对齐)
if ImageSectionHeader.Misc.VirtualSize mod ImageNtHeaders.OptionalHeader.SectionAlignment > 0 then
ImageSectionHeader.Misc.VirtualSize := (ImageSectionHeader.Misc.VirtualSize div ImageNtHeaders.OptionalHeader.SectionAlignment + 1) * ImageNtHeaders.OptionalHeader.SectionAlignment;
//设置区块属性
ImageSectionHeader.Characteristics := $E00000E0;
//保存区块信息
WriteFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), ByteSWrite, nil);
//校正内存映象大小
ImageNtHeaders.OptionalHeader.SizeOfImage := ImageNtHeaders.OptionalHeader.SizeOfImage + ImageSectionHeader.Misc.VirtualSize;
//更
//校正块数目
Inc(ImageNtHeaders.FileHeader.NumberOfSections);
//定位到映象头
SetFilePointer(hFile, ImageDosHeader._lfanew, nil, FILE_BEGIN);
//保存校正过的映象头
WriteFile(hFile, ImageNtHeaders, SizeOf(ImageNtHeaders), ByteSWrite, nil);
//定位到新节开始处
SetFilePointer(hFile, ImageSectionHeader.PointerToRawData, nil, FILE_BEGIN);
//用00数据填充满新节
for i := 1 to AttachSize do
begin
WriteFile(hFile, PByte(@AttachData)^, 1, ByteSWrite, nil);
end;
{填充自定义数据}
//指向新节开始处
SetFilePointer(hFile, ImageSectionHeader.PointerToRawData, nil, FILE_BEGIN);
WriteFile(hFile, OEP, 4, ByteSWrite, nil); //跳回OEP
//没有异常,显示增加区块成功!
ShowMessage('增加区块成功!');
finally
{8.退出}
//关闭文件
CloseHandle(hFile);
end;
end;
{*************************end*********************************}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//设置文件的新区段段的属性为;读+写+可执行
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
procedure SetSectionAttrib(strFileName: string; StartEN: integer);
var
dwBuffer: dword; {文件读取缓冲区}
pe_header: IMAGE_NT_HEADERS; {PE文件头指针}
iNumberOfSections: integer; {保存区块数目}
dwSecTableBase: dword; {保存区块头文件首址}
dwPEHeaderBase: dword; {保存PE文件头文件首址}
iLoop: integer; {循环变量}
pSectionTable: IMAGE_SECTION_HEADER; {保存各区块表指针}
dwSectionAttrib: dword; {保存段属性}
fsWrite: TFileStream; {写文件文件流}
begin
{以读写方式建立文件流}
fsWrite := TFileStream.Create(strFileName, fmOpenReadWrite);
{文件流指针移动到新EXE头部字段}
fsWrite.Seek($3C, soFromBeginning);
dwBuffer := 0;
{读取PE文件头文件地址}
fsWrite.ReadBuffer(dwBuffer, 4);
dwPEHeaderBase := dwBuffer;
{文件指针指向PE 文件头}
fsWrite.Seek(dwBuffer, soFromBeginning);
{读入pe文件头到内存}
fsWrite.ReadBuffer(pe_header, SizeOf(IMAGE_NT_HEADERS));
{取区块数目}
iNumberOfSections := pe_header.FileHeader.NumberOfSections;
{获取区块表头文件地址:}
dwSecTableBase := dwPEHeaderBase + SizeOf(IMAGE_NT_HEADERS);
{分别读取各个区块的信息到内存}
for iLoop := 0 to iNumberOfSections - 1 do
begin
{文件指针指向第iLoop区块表}
fsWrite.Seek(dwSecTableBase, soFromBeginning);
{读入区块表信息}
fsWrite.ReadBuffer(pSectionTable, SizeOf(IMAGE_SECTION_HEADER));
{读取区块数据文件地址}
if pSectionTable.PointerToRawData = StartEN then
begin
fsWrite.Seek(dwSecTableBase + 36, soFromBeginning);
dwSectionAttrib := $E00000E0;
fsWrite.WriteBuffer(dwSectionAttrib, SizeOf(dword));
fsWrite.Free;
ShowMessage('修改区段属性成功');
break;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
FileName,EdtASN,EdtASS :string;
Backup:Boolean;
begin
FileName:=Trim(edit1.Text);
EdtASN:=edit2.Text;
EdtASS:=edit3.Text;
Backup:=ChxBackup.Checked;
if not FileExists(FileName) then
MessageBox(Handle,'请输入有效的文件名!',PChar(Caption),MB_ICONERROR+MB_OK)
else if Length(edit2.Text)=0 then
MessageBox(Handle,'请输入新区段名称!',PChar(Caption),MB_ICONERROR+MB_OK)
else if Length(edit3.Text)=0 then
MessageBox(Handle,'请输入输入新区段大小!',PChar(Caption),MB_ICONERROR+MB_OK)
else
AddSection(Edit1.text,Edit2.text,Edit3.text,true); //增加区段头
SetSectionAttrib(Edit1.text, SecData); // 设置区段属性
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
with TOpenDialog.Create(Self) do
try
Filter := '可执行文件 (*.exe)|*.exe';
if Execute then
begin
Edit1.text := FileName;
end;
finally
Free;
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
close;
end;
end.