📄 exeimage.pas
字号:
{***********************************************************************
Copyright @2002-2003
Author: OuChengSong
Create Date: 2002-12-31
Descript: Exe文件映像的封装
提供Exe文件资源的读取与更改.
***********************************************************************}
unit ExeImage;
interface
uses
Windows,SysUtils,Classes,Variants,
{ 手工加入的 }
peTypes,FPSet;
type
EExeError = class(Exception);
TExeImage = class
private
FFileName:String; //文件名,为保存更改后的内存流输入到指定文件定名.
FPENTHeaderOffSet: Integer; //指向新的NT文件头的偏移值.
FExeStream: TMemoryStream; //内存流
{ PE文件结构的实例 }
FPEDosHead:TImageDosHeader; //DOS头
FPENTHead:TImageNTHeaders; //NT头
FPESectionHead:array of TImageSectionHeader; { 块表头的大小由NT头的NumberOfSections确定 }
{ 头部记录个数,由程序设计时定义 }
FPEDosHeadRecSize:Word;
FPECoffHeadRecSize:Word;
FPEOptionHeadRecSize:Word;
FPESectionHeadRecSize:Word;
{ 数据目录的一些项的存在性 }
FExportDirExists : Boolean;
FImportDirExists : Boolean;
FResourceDirExists: Boolean;
{ }
FSectionNum: Word; //节表的个数
FResDataNum: Word; //资源数据的个数
FResourceInSectionIndex: Word; //资源节表在节表目录的索引.
FGroupVarCount: Integer; //图标光标组中返回的变体长度
function IsResourceExists:Boolean;
function GetResDataNum: Word;
{ 判断文件运行所需的机器及文件与块表特性 }
function CheckFileMachine(Value: Cardinal): String;
function CheckFileCharacteristics(Value: Cardinal):String;
function CheckSectionCharacteristics(Value:Cardinal):String;
public
constructor CreateImage(AFileName:String);//创建映像
{ 私有变量以属性方式提供出去(只读) }
property ExportDirExists : Boolean read FExportDirExists;
property ImportDirExists : Boolean read FImportDirExists;
property ResourceDirExists: Boolean read FResourceDirExists;
property PENTHeaderOffSet:Integer read FPENTHeaderOffSet;
property PEDosHeadRecSize: Word read FPEDosHeadRecSize;
property PECoffHeadRecSize:Word read FPECoffHeadRecSize;
property PEOptionHeadRecSize:Word read FPEOptionHeadRecSize;
property PESectionHeadRecSize: Word read FPESectionHeadRecSize;
property FileName: String read FFileName;
property SectionNum:Word read FSectionNum;
property ResDataNum:Word read FResDataNum;
property GroupVarCount: Integer read FGroupVarCount;
{ 获取信息,返回较多内容 }
{
实际上以变体返回对于封装性不是很好,如果必要可以再将
其换为一个结构型的实例,但此实例是个数组,其长度需要
由一个属性值提供出去以告知。[是否可取变体的维度来确定?]
}
function GetSegStream(AOffset:Integer;ACount:Word): TMemoryStream;
function GetBitmapStream(AOffset:Integer;ACount:Word): TMemoryStream;
function GetCursorStream(AOffset, ACount, HeaderOffset,NameID: Integer): TMemoryStream;
function GetIconStream(AOffset, ACount, HeaderOffset,NameID: Integer): TMemoryStream;
function AnalysisDosHeader: Variant;
function AnalysisCoffHeader: Variant;
function AnalysisOptionHeader: Variant;
function AnalysisSectionHeader(AIndex:Word): Variant;
function AnalysisSectionDescript:Variant;
function GetResourceDataDir:Variant;
function AnalysisIconOrCursorGroupInfo(AOffset:Integer):Variant;
{ 获取简单信息 }
{
ICON -> ICON_ENTRY
CURSOR -> CURSOR_ENTRY
以后修改成不要传递参数的.
}
function GetIconResInfo(AOffset:Integer):TStringList;
function GetCursorResInfo(AOffset:Integer):TStringList;
function GetStringTable(AOffset,ASize:Integer):TStringList;
function GetAccelerator(AOffset,ASize:Integer):TStringList;
function GetExportInfo:TStringList;
//获得版本信息;
function GetVSFixedFileInfo(AOffset:Integer):TStringList;
function GetVSStringFileInfo(AOffset:Integer):TStringList;
function GetVSVerFileInfo(AOffset:Integer):TStringList;
function GetVSLanguageID(AOffset,ASize:Integer):DWORD;
{ 获取数据目录相应的大小及地址 }
function ImportDirAddr: Integer;
function ImportDirSize: Integer;
function ExportDirAddr: Integer;
function ExportDirSize: Integer;
function ExportName: String;
function GetImportName:TStringList;
function GetImportFunction(AIndexOfName:WORD):TStringList;
end;
implementation
{ Exceptions of EExeError }
procedure ExeError(const ErrMsg: string);
begin
raise EExeError.Create(ErrMsg);
end;
{ TExeImage }
{ 返回文件运行所需要CPU标记的机器名 }
function TExeImage.CheckFileMachine(Value:Cardinal):String;
begin
case Value of
IMAGE_FILE_MACHINE_I386 :Result:='Intel 386';
$160 :Result:='MIPS big-endian';
IMAGE_FILE_MACHINE_R3000 :Result:='MIPS little-endian';
IMAGE_FILE_MACHINE_R4000 :Result:='MIPS little-endian';
IMAGE_FILE_MACHINE_R10000 :Result:='MIPS little-endian';
IMAGE_FILE_MACHINE_WCEMIPSV2:Result:='MIPS little-endian WCE v2';
IMAGE_FILE_MACHINE_ALPHA :Result:='Alpha_AXP';
IMAGE_FILE_MACHINE_SH3 :Result:='SH3 little-endian';
IMAGE_FILE_MACHINE_SH3E :Result:='SH3E little-endian';
IMAGE_FILE_MACHINE_SH4 :Result:='SH4 little-endian';
IMAGE_FILE_MACHINE_SH5 :Result:='SH5';
IMAGE_FILE_MACHINE_ARM :Result:='ARM Little-Endian';
IMAGE_FILE_MACHINE_THUMB :Result:='THUMB';
IMAGE_FILE_MACHINE_ARM33 :Result:='ARM33';
IMAGE_FILE_MACHINE_POWERPC :Result:='IBM PowerPC Little-Endian';
IMAGE_FILE_MACHINE_IA64 :Result:='Intel 64';
IMAGE_FILE_MACHINE_MIPS16 :Result:='MIPS';
IMAGE_FILE_MACHINE_ALPHA64 :Result:='ALPHA64';
IMAGE_FILE_MACHINE_MIPSFPU :Result:='MIPS';
IMAGE_FILE_MACHINE_MIPSFPU16:Result:='MIPS';
IMAGE_FILE_MACHINE_AMD64 :Result:='AMD K8';
IMAGE_FILE_MACHINE_TRICORE :Result:='Infineon';
IMAGE_FILE_MACHINE_CEF :Result:='CEF';
else Result:='未知';
end;
end;
{ 返回文件特性值 }
function TExeImage.CheckFileCharacteristics(Value:Cardinal):String;
function BeTrue(fg:Cardinal):Boolean;
begin
Result:=fg and not Value=0;
end;
var
tmpStr:String;
begin
tmpStr:='';
if BeTrue(IMAGE_FILE_RELOCS_STRIPPED) then
tmpStr:='不含重定位信息';
if BeTrue(IMAGE_FILE_EXECUTABLE_IMAGE) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'可执行文件';
end;
if BeTrue(IMAGE_FILE_LINE_NUMS_STRIPPED) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'不含行号';
end;
if BeTrue(IMAGE_FILE_LOCAL_SYMS_STRIPPED) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'不含局部符号';
end;
if BeTrue(IMAGE_FILE_AGGRESIVE_WS_TRIM) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'安全工作集';
end;
if BeTrue(IMAGE_FILE_LARGE_ADDRESS_AWARE) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'句柄大于2G';
end;
if BeTrue(IMAGE_FILE_BYTES_REVERSED_LO) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'保留低位字节';
end;
if BeTrue(IMAGE_FILE_32BIT_MACHINE) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'32位机文件';
end;
if BeTrue(IMAGE_FILE_DEBUG_STRIPPED) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'不含调试信息';
end;
if BeTrue(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'可移动映像执行文件';
end;
if BeTrue(IMAGE_FILE_NET_RUN_FROM_SWAP) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'网络映像执行文件';
end;
if BeTrue(IMAGE_FILE_SYSTEM) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'系统文件';
end;
if BeTrue(IMAGE_FILE_DLL) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'DLL文件';
end;
if BeTrue(IMAGE_FILE_UP_SYSTEM_ONLY) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'仅是系统文件';
end;
if BeTrue(IMAGE_FILE_BYTES_REVERSED_HI) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'保留高位字节';
end;
result:=tmpStr;
end;
{ 返回块表特性值 }
function TExeImage.CheckSectionCharacteristics(Value:Cardinal):String;
function BeTrue(fg:Cardinal):Boolean;
begin
Result:=fg and not Value=0;
end;
var
tmpStr:String;
begin
tmpStr:='';
if BeTrue(IMAGE_SCN_CNT_CODE) then
tmpStr:='含代码';
if BeTrue(IMAGE_SCN_CNT_INITIALIZED_DATA) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'含初始数据';
end;
if BeTrue(IMAGE_SCN_CNT_UNINITIALIZED_DATA) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'含未初始数据';
end;
if BeTrue(IMAGE_SCN_LNK_INFO) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'含文字说明或其他信息';
end;
if BeTrue(IMAGE_SCN_LNK_REMOVE) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'此节不被放入最终EXE文件中';
end;
if BeTrue(IMAGE_SCN_LNK_COMDAT) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'含COMDAT';
end;
if BeTrue(IMAGE_SCN_LNK_NRELOC_OVFL) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'含扩展重定位信息';
end;
if BeTrue(IMAGE_SCN_MEM_DISCARDABLE) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'可丢弃';
end;
if BeTrue(IMAGE_SCN_MEM_NOT_CACHED) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'不可隐藏';
end;
if BeTrue(IMAGE_SCN_MEM_NOT_PAGED) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'不可分页';
end;
if BeTrue(IMAGE_SCN_MEM_SHARED) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'可共享';
end;
if BeTrue(IMAGE_SCN_MEM_EXECUTE) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'可执行';
end;
if BeTrue(IMAGE_SCN_MEM_READ) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'可读';
end;
if BeTrue(IMAGE_SCN_MEM_WRITE) then
begin
if tmpStr<>'' then tmpStr:=tmpStr+',';
tmpStr:=tmpStr+'可写';
end;
result:=tmpStr;
end;
{ 返回分析的Coff头信息 }
function TExeImage.AnalysisCoffHeader: Variant;
var
V: Variant;
tmpStr:String;
tmpExeOffSet: Integer;
tmpDt: TDateTime;
tmpFt: TFileTime;
tmpSt: TSystemTime;
begin
v:=VarArrayCreate([0,7],varVariant);
tmpExeOffSet:=FPEDosHead._lfanew;
with FPENTHead.FileHeader do
begin
v[0]:=VarArrayOf([tmpExeOffSet+0,Format('%.8x',[FPENTHead.Signature]),'PE文件头标志']);
tmpStr:=CheckFileMachine(Machine);
v[1]:=VarArrayOf([tmpExeOffSet+4,Format('%.4x',[Machine]),Format('运行所需要的CPU: %s',[tmpStr])]);
v[2]:=VarArrayOf([tmpExeOffSet+6,Format('%.4x',[NumberOfSections]),'文件的块表数']);
{
tmpSt.wYear:=1980;
tmpSt.wMonth:=7;
tmpSt.wDay:=6;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -