学习 PE 可执行文件格式,用 delphi 实现给 EXE 文件增加区段
unit uStudyPE;

interface
uses
Classes, SysUtils, Windows, uPERec; type TImage_Section_headerList = class; TStudyPE = class
private
FFileStream: TFileStream;
FNewStream: TMemoryStream;
FImage_Dos_Header: PImage_DOS_Header;
FImage_NT_Headers: PImage_NT_Headers;
FImage_Section_HeaderList: TImage_Section_headerList;
public
constructor Create;
destructor Destroy; override;
public
procedure LoadPE(AFileName: string);
property Image_Dos_Header: PImage_DOS_Header read FImage_Dos_Header;
property Image_NT_Headers: PImage_NT_Headers read FImage_NT_Headers;
property Image_Section_HeaderList: TImage_Section_headerList read FImage_Section_HeaderList;
end; TImage_Section_headerList = class(TList)
public
procedure FreeAllItems();
destructor Destroy; override;
end; implementation
{ TStudyPE }
const
Image_Dos_Header_len = SizeOf(TImage_dos_header);
Image_NT_Headers_len = SizeOf(TImage_NT_Headers);
Image_Section_Header_len = SizeOf(TImage_Section_Header); constructor TStudyPE.Create;
begin
inherited Create;
New(FImage_Dos_Header);
New(FImage_NT_Headers);
FImage_Section_HeaderList := TImage_Section_headerList.Create;
FNewStream := TMemoryStream.Create;
end; destructor TStudyPE.Destroy;
begin
Dispose(FImage_Dos_Header);
Dispose(FImage_NT_Headers);
FImage_Section_HeaderList.Free;
FNewStream.Free;
inherited;
end; procedure TStudyPE.LoadPE(AFileName: string);
var e_lfanew: DWORD;
pSecHeader: PImage_Section_header;
nNumberOfSections: word;
i: integer;
nDosStubLen: integer;
nSizeOfImage: DWORD;
LImage_Section_header: TImage_Section_Header;
Rva: DWORD;
vaSize: DWORD; SizeOfHeaders: DWORD; // 一般是 $400
NewSectionSize: DWORD; // 新增区段大小 begin if Assigned(FFileStream) then
begin
FFileStream.Free;
end; NewSectionSize := $; FFileStream := TFileStream.Create(AFileName, fmOpenRead);
FFileStream.Read(FImage_Dos_Header^, Image_Dos_Header_len); // 读 DOS 头,64字节 FNewStream.Size := FFileStream.Size + NewSectionSize; // 新文件大小
FNewStream.Write(FImage_Dos_Header^, Image_Dos_Header_len); // 将 DOS 头写入新文件 e_lfanew := FImage_Dos_Header.e_lfanew; // 获取 Image_NT_Headers 的位置
nDosStubLen := e_lfanew - Image_Dos_Header_len; // DOS 汇编代码区域长度 // 将 DOS 汇编代码写入新文件,写完后 FFileStream.Position 正好在 Image_NT_Header 的位置上
FFileStream.Read((Pbyte(FNewStream.Memory) + Image_Dos_Header_len)^, nDosStubLen);
FNewStream.Position := Image_Dos_Header_len + nDosStubLen; FFileStream.Read(FImage_NT_Headers^, Image_NT_Headers_len); // 获取 Image_NT_Headers
SizeOfHeaders := FImage_NT_Headers.Image_Optional_Header32.SizeOfHeaders; nNumberOfSections := FImage_NT_Headers.Image_File_Header.NumberOfSections; // 区段数量
FImage_NT_Headers.Image_File_Header.NumberOfSections := nNumberOfSections + ; // 增加区段数量 nSizeOfImage := FImage_NT_Headers.Image_Optional_Header32.SizeOfImage;
FImage_NT_Headers.Image_Optional_Header32.SizeOfImage := nSizeOfImage + NewSectionSize; // 修改 EXE 所占内存大小
FNewStream.Write(FImage_NT_Headers^, Image_NT_Headers_len); // 将 Image_NT_Headers 写入新文件 FImage_Section_HeaderList.FreeAllItems; for i := to nNumberOfSections - do
begin
New(pSecHeader);
FImage_Section_HeaderList.Add(pSecHeader);
FFileStream.Read(pSecHeader^, Image_Section_Header_len);
FNewStream.Write(pSecHeader^, Image_Section_Header_len); // 将各个 Image_Section_Header 写入新文件
end; LImage_Section_header := pSecHeader^; // 给新区段命名
LImage_Section_header.Name[] := ord('.');
LImage_Section_header.Name[] := ord('N');
LImage_Section_header.Name[] := ord('E');
LImage_Section_header.Name[] := ord('W');
LImage_Section_header.Name[] := ord('T');
LImage_Section_header.Name[] := ord('E');
LImage_Section_header.Name[] := ord('S');
LImage_Section_header.Name[] := ord('T'); // 用最后一个区段作参考计算新增区段的 VirtualAddress,PointerToRawData 的值
// VirtualAddress 是在EXE中虚拟地址
// PointerToRawData 新区段在文件中的位置
Rva := pSecHeader.VirtualAddress;
vaSize := ((pSecHeader.Misc.VirtualSize + $FFF) div $) * $;
LImage_Section_header.VirtualAddress := Rva + vaSize; // 新区段的虚拟地址 Rva := pSecHeader.PointerToRawData;
vaSize := ((pSecHeader.Misc.VirtualSize + $1FF) div $) * $;
LImage_Section_header.PointerToRawData := Rva + vaSize; // 新区段的文件中的位置 LImage_Section_header.Misc.VirtualSize := NewSectionSize;
LImage_Section_header.SizeOfRawData := NewSectionSize;
LImage_Section_header.Characteristics := $; // 区段的属性(读,写,执行) // 要计算位置是否够放新 Section, 未完成,本例所改的 exe 是可以的。 if ((SizeOfHeaders - FFileStream.Position) < Image_Section_Header_len) then
begin
raise Exception.Create('区段位置不够,本Demo无法操作!');
// 为了简单,所以这样操作了。实际上是可以的,只是每个区段都得重新计算虚拟地址与在文件中的地址
end; FNewStream.Write(LImage_Section_header, Image_Section_Header_len); // 将新增 Image_Section_Header 写入新文件 // 将源文件剩下的数据写入新文件
FFileStream.Seek(SizeOfHeaders, soBeginning);
FFileStream.Read((Pbyte(FNewStream.Memory) + SizeOfHeaders)^, FFileStream.Size - SizeOfHeaders);
FNewStream.SaveToFile('new.exe'); end; { TImage_Section_headerList } destructor TImage_Section_headerList.Destroy;
begin
FreeAllItems;
inherited;
end; procedure TImage_Section_headerList.FreeAllItems;
var
p: PImage_Section_header;
begin
for p in self do
Dispose(p);
Clear;
end; end.

uStudyPE.pas

unit uPERec;

interface
uses
Classes, SysUtils, Windows; type
// Windows 单元中有这些结构,而我为了学习,从书上重新操作了一遍 PImage_DOS_Header = ^TImage_DOS_Header;
TImage_DOS_Header = packed record
e_magic: WORD; // DOS signature:4D5A ('MZ')
e_cblp: WORD;
e_cp: WORD;
e_crlc: WORD;
e_cparhdr: WORD;
e_minalloc: WORD;
e_maxalloc: WORD;
e_ss: WORD;
e_sp: WORD;
e_csum: WORD;
e_ip: WORD;
e_cs: WORD;
e_lfarlc: WORD;
e_ovno: WORD;
e_res: array [ .. ] of WORD;
e_oemid: WORD;
e_oeminfo: WORD;
e_res2: array [ .. ] of WORD;
e_lfanew: DWORD; // offset to NT hearder
end; TImage_Optional_Header32 = _Image_Optional_Header32;
TImage_File_Header = _Image_File_Header; PImage_NT_Headers = ^TImage_NT_Headers;
TImage_NT_Headers = packed record
Signature: DWORD; // PE Signature: 50450000 ('PE'00)
Image_File_Header: TImage_File_Header;
Image_Optional_Header32: TImage_Optional_Header32;
end; PImage_File_Header = ^TImage_File_Header;
_Image_File_Header = packed record
Machine: WORD;
NumberOfSections: WORD;
TimeDateStamp: DWORD;
PointerToSymbolTable: DWORD;
NumberOfSymbols: DWORD;
SizeOfOptionalHeader: WORD;
Characteristics: WORD;
end; const
Image_NumberOf_Directory_Entries = ; type TImage_Data_Directory = _Image_Data_Directory; PImage_Optional_Header32 = ^TImage_Optional_Header32;
_Image_Optional_Header32 = packed record
Magic: WORD;
MajorLinkerVersion: BYTE;
MinorLinkerVersion: BYTE;
SizeOfCode: DWORD;
SizeOfInitializedData: DWORD;
SizeOfUninitializedData: DWORD;
AddressOfEntryPoint: DWORD;
BaseOfCode: DWORD;
BaseOfData: DWORD;
ImageBase: DWORD;
SectionAlignment: DWORD;
fileAlignment: DWORD;
MajorOperatingSystemVersion: WORD;
MinorOperatingSystemVersion: WORD;
MajorImageVersion: WORD;
minorImageVersion: WORD;
MajorSubsystemVersion: WORD;
MinorSubsystemVersion: WORD;
Win32VersionValue: DWORD;
SizeOfImage: DWORD;
SizeOfHeaders: DWORD;
checkSum: DWORD;
Subsystem: WORD;
DllCharacteristics: WORD;
SizeOfStackReserve: DWORD;
SizeOfStackCommit: DWORD;
sizeOfHeapReserve: DWORD;
sizeofHeapcommit: DWORD;
LoaderFlags: DWORD;
NumberOfRvaAndSizes: DWORD;
Image_Data_Directory: array [ .. Image_NumberOf_Directory_Entries - ] of TImage_Data_Directory;
end; _Image_Data_Directory = packed record
VirtualAddress: DWORD;
Size: DWORD;
end;
const
Image_SizeOf_Short_Name = ; type TMisc = packed record
case integer of
:(PhysicalAddress: DWORD);
:(VirtualSize: DWORD);
end;
// 此为 C 语言 union 格式 改写而成
//
// union {
// DWORD PhysicalAddress;
// DWORD VirtualSize;
// } Misc;
//
// PImage_Section_Header = ^TImage_Section_Header;
TImage_Section_Header = packed record
Name: array [ .. Image_SizeOf_Short_Name - ] of BYTE;
Misc: TMisc;
VirtualAddress: DWORD;
SizeOfRawData: DWORD;
PointerToRawData: DWORD;
PointerToRelocations: DWORD;
PointerToLineNumbers: DWORD;
NumberOfRelocations: WORD;
NumberofLineNumbers: WORD;
Characteristics: DWORD;
end; implementation
end.

uPERec.pas

delphi 给EXE文件增加区段的更多相关文章

  1. 在delphi的exe文件中嵌入另外一个exe文件

    http://www.cnblogs.com/dabiao/archive/2009/11/28/delphi.html 1.创建rc文件.可以用任意文本编辑器来写.文件格式为:"资源名 资 ...

  2. 如何用DELPHI编程修改外部EXE文件的版本信

    右击里面有修改 点开直接修改就可以了吧. DELPHI 里程序的版本信息怎么是灰色的,无法更改 耐心读以下说明,应该能解决你的问题,如果不能解决,请Hi我~ 如何给自己的dll文件添加版本信息呢? 首 ...

  3. delphi编写提取exe文件的ICO图标

    http://www.duote.com/tech/4/11797.html delphi编写提取exe文件的ICO图标 7.0分 出处:天下网吧 时间:2011-08-05 人气:2390 核心提示 ...

  4. 常用EXE文件反编译工具

    PE Explorer V1.99 R5 绿色汉化特别版_强大的可视化汉化集成工具 功能极为强大的可视化汉化集成工具,可直接浏览.修改软件资源,包括菜单.对话框.字符串表等: 另外,还具备有 W32D ...

  5. 转载:常见EXE文件反编译工具

    PE Explorer V1.99 R5 绿色汉化特别版_强大的可视化汉化集成工具 功能极为强大的可视化汉化集成工具,可直接浏览.修改软件资源,包括菜单.对话框.字符串表等: 另外,还具备有 W32D ...

  6. 减小Delphi的Exe文件大小(11种方法)

    一般来说,由Delphi生成的EXE文件,要比其由它编程语言生成的体积大一些.这主要是由于使用VCL的原因(当然,VCL是有许多优点的!) 以下是减小EXE文件大小的几种途径: 01) 使用加壳工具( ...

  7. WinExec打开exe文件

    1,WinExec():   WinExec主要运行EXE文件,不能运行其他类型的文件.不用引用特别单元.   原型:UINT WinExec(exePath,ShowCmd)   示例,我想要用记事 ...

  8. 常用EXE文件反编译工具【转】

    http://www.cnblogs.com/happyday56/p/3740108.html PE Explorer V1.99 R5 绿色汉化特别版_强大的可视化汉化集成工具 功能极为强大的可视 ...

  9. Delphi 使用CHM文件制作系统帮助文档(上下文感知帮助的制作)

    一.基础知识简介         使用帮助提示窗口或状态栏只能提供简单.单一的帮助,无法对某一模块或应用程序整体提供系统的 帮助,因此运行Windows应用程序,需要帮助时一般都可以通过执行帮助菜单获 ...

随机推荐

  1. java集合小知识的复习

    *Map接口 Map<k,v>接口中接收两个泛型,key和value的两个数据类型 Map中的集合中的元素都是成对存在的每个元素由键与值两部分组成,通过键可以找对所对应的值.值可以重复,键 ...

  2. iOS HTML图片本地预览

    引言 相信用过苹果手机的童鞋,会发现很多新闻类的应用,都可以实现HTML图片本地预览,那么这是如何实现的呢?本文将深入阐述其中的原理. 关于此功能,我还实现了一个DEMO,大家可以点击此访问更详细内容 ...

  3. 复习上学期的HTML+CSS(1)

    自己跟着网上教程复习上学期的HTML+CSS,因为已经忘得差不多了,而且现在学的js也要以HTML+CSS为基础,坚持每天持续更新. n  B/S 网络结构   Browser/Server 浏览器/ ...

  4. [转]XHR简介

      在XHR诞生前,网页要获取客户端和服务器的任何状态更新,都需要刷新一次,在XHR诞生后就可以完全通过JS代码异步实现这一过程.XHR的诞生也使最初的网页制作转换为开发交互应用,拉开了WEB2.0的 ...

  5. requests-证书验证

    import requests #response = requests.get('https://www.12306.cn') #print(response.status_code) #以上会显示 ...

  6. php+MySql实现登录系统与输出浏览者信息功能

    这篇文章主要介绍了php+MySql实现登录系统与输出浏览者信息功能 的相关资料,需要的朋友可以参考下   本系统,与之前在<ASP 连接Access数据库的登陆系统>(点击打开链接)一文 ...

  7. DOM 节点

    <html> <head> <title>DOM 教程</title> </head> <body> <h1>DOM ...

  8. 谁说深入浅出虚拟机难?现在我让他通俗易懂(JVM)

    1:什么是JVM大家可以想想,JVM 是什么?JVM是用来干什么的?在这里我列出了三个概念,第一个是JVM,第二个是JDK,第三个是JRE.相信大家对这三个不会很陌生,相信你们都用过,但是,你们对这三 ...

  9. (hdu-4280)Island Transport~测试网络流模板速度~要加挂才能过啊

    Problem Description In the vast waters far far away, there are many islands. People are living on th ...

  10. jqgrid表格插件总结

    jqgrid整了好多天,最重要得是理清思路,故做下记录,让大家少走弯路 1  配置环境,下载几个包导入(自行百度),从官网上下载一个案例导入,可以简单显示一个静态的画面(注意json包之间的兼容性) ...