📄 upeentry.pas
字号:
unit UPEEntry;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, Menus;
type
{PE导出表声明}
PImageExportDirectory = ^TImageExportDirectory;
TImageExportDirectory = packed record
Characteristics: DWORD;
TimeDateStamp: DWORD;
MajorVersion: WORD;
MinorVersion: WORD;
Name: DWORD;
Base: DWORD;
NumberOfFunctions: DWORD;
NumberOfNames: DWORD;
AddressOfFunctions: DWORD;
AddressOfNames: DWORD;
AddressOfNameOrdinals: DWORD;
end;
PImportByName=^TImportByName;
TImportByName =Packed record
ProcedureHint: word;
ProcedureName: array[0..1]of char;
end;
PImageImportDescriptor = ^TImageImportDescriptor;
TImageImportDescriptor = packed record
OriginalFirstThunk: DWord;
TimeDateStamp : DWord;
ForwarderChain : DWord;
DLLName : DWord;
FirstThunk : DWord;
end;
PImageThunkData=^TImageThunkData;
TImageThunkData = record
case integer of
1:( ForwarderString : DWord; );
2:( Function_ : DWord; );
3:( Ordinal : DWord; );
4:( AddressOfData : DWord; );
end;
PImageBaseRelocation=^TImageBaseRelocation;
TImageBaseRelocation=Packed Record
VirtualAddress: Dword;
SizeOfBlock: Dword;
TypeOffset: array[0..1] of Word; //不定长
end;
TPESection = record //自定义
ObjectName: string;
Address: PChar;
PhysicalSize: Integer;
// VirtualSize: Integer;
// Characteristics: Cardinal;
PointerToRawData: Integer;
end;
TNameOrID = (niName, niID);
TPEImport = record
NameOrID: TNameOrID;
Name: string;
ID: Integer;
// PAddress: PChar; {指向导入表函数用于执行此函数}
end;
TPEImports = record {记录一个Dll文件所调用的函数个数}
DLLName: string;
Entries: array of TPEImport; {函数数据}
end;
TPEExport = record
Name: string;
RelativeID: Integer;
ID: Integer;
Address: DWORD;{相对地址}
end;
TfrmPEEntry = class(TForm)
GroupBox1: TGroupBox;
ListBox1: TListBox;
GroupBox2: TGroupBox;
ListBox2: TListBox;
GroupBox3: TGroupBox;
BitBtn2: TBitBtn;
procedure BitBtn2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
PEImports: array of TPEImports;
PEExport: array of TPEExport;
Section: array of TPESection;
procedure Load(FileName:string);
end;
var
frmPEEntry: TfrmPEEntry;
implementation
uses UMain;
{$R *.DFM}
procedure TfrmPEEntry.Load(FileName:string);
type
TImageSectionHeaderArray=array[0..1]of TImageSectionHeader;
PImageSectionHeaderArray=^TImageSectionHeaderArray;
var
FileStream: TFileStream;
ImageDosHeader:TImageDosHeader;
ImageNtHeaders:TImageNtHeaders;
ImageBase: PChar;
FileBase: PChar;
ImageSize: Integer;
HeaderSize: Integer;
NTHeader: PImageNtHeaders;
I,J: integer;
ImportEntry: PImageImportDescriptor;
LookupEntry: PDWord;
ImportByName: PImportByName;
SectionTable:PImageSectionHeaderArray;
ExportEntry: PImageExportDirectory;
AddressOfFunctions: PChar;
AddressOfNames: PChar;
AddressOfNameOrdinals: PChar;
Found:boolean;
begin
ListBox1.Clear;
ListBox2.clear;
for I := 0 to High(PEImports) do
SetLength(PEImports[I].Entries, 0);
SetLength(PEImports,0);
FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
with FileStream do
begin
ReadBuffer(ImageDosHeader,sizeof(TImageDosHeader));
{以下检验是否是合法的PE文件}
if ImageDosHeader.e_magic<>IMAGE_DOS_SIGNATURE then
begin
showmessage('未知的文件格式.');
FileStream.free;
exit;
end;
if ImageDosHeader._lfanew >= Size then
begin
showmessage('未知的文件格式.');
FileStream.free;
exit;
end;
Position := ImageDosHeader._lfanew;
ReadBuffer(ImageNtHeaders,sizeof(TImageNtHeaders));
{检验 NT Header.}
if ImageNtHeaders.Signature<>IMAGE_NT_SIGNATURE then
begin
showmessage('此文件不是WIN32 PE可执行文件.');
FileStream.free;
exit;
end;
ImageBase:=pointer(ImageNtHeaders.OptionalHeader.ImageBase);
ImageSize:=ImageNtHeaders.OptionalHeader.SizeOfImage;
HeaderSize:=ImageNtHeaders.OptionalHeader.SizeOfHeaders;
{在ImageBaseAdress中分配内存}
FileBase := VirtualAlloc(ImageBase, ImageSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
{返回映射后的基地址}
if FileBase = nil then
begin
{由系统自动分配内存页}
FileBase := VirtualAlloc(nil, ImageSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
if FileBase = nil then
begin
showmessage('不能分配内存');
FileStream.free;
exit;
end;
end;
Position := 0;
ReadBuffer(PPointer(FileBase)^, HeaderSize); {读取数据到文件头中}
{把文件指针定位到NtHeader}
NTHeader := PImageNtHeaders(FileBase + PImageDosHeader(FileBase)^._lfanew);
{保存栈}
// StackCommitSize := NTHeader^.OptionalHeader.SizeOfStackCommit;
{保存保留栈}
// StackReserveSize := NTHeader^.OptionalHeader.SizeOfStackReserve;
{保存切入点}
// EntryPoint := FileBase + NTHeader^.OptionalHeader.AddressOfEntryPoint;
{保存代码大小}
// CodeSize := NTHeader^.OptionalHeader.SizeOfCode;
{保存代码地址}
// Code := FileBase + NTHeader^.OptionalHeader.BaseOfCode;
{保存数据大小}
// DataSize := NTHeader^.OptionalHeader.SizeOfInitializedData;
{保存数据地址}
// Data := FileBase + NTHeader^.OptionalHeader.BaseOfData;
{从文件中读取信息并保存在变量中}
SetLength(Section, NTHeader^.FileHeader.NumberOfSections);
SectionTable:= PImageSectionHeaderArray(longword(NtHeader)+sizeof(TImageNtHeaders));
for I := 0 to High(Section) do
begin
SetLength(Section[I].ObjectName, 8);
Move(SectionTable^[I].Name, Section[I].ObjectName[1], 8);
SetLength(Section[I].ObjectName, StrLen(PChar(Section[I].ObjectName)));
Section[I].PhysicalSize := SectionTable^[I].SizeOfRawData;
// Section[I].VirtualSize := SectionTable^[I].Misc.VirtualSize;
Section[I].Address := FileBase + SectionTable^[I].VirtualAddress;
Section[I].PointerToRawData := SectionTable^[I].PointerToRawData;
Position := SectionTable^[I].PointerToRawData;
ReadBuffer(PPointer(Section[I].Address)^, Section[I].PhysicalSize);
// Section[I].Characteristics := SectionTable^[I].Characteristics;
end;
if NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress<>0 then
begin
ImportEntry := PImageImportDescriptor(FileBase +
NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
{读取导入表入口,直到空为止}
while ImportEntry^.DLLName <> 0 do
begin
{新导入表入口}
SetLength(PEImports, Length(PEImports) + 1);
PEImports[High(PEImports)].DLLName := FileBase + ImportEntry^.DLLName;
if ImportEntry^.OriginalFirstThunk<>0 then
LookupEntry := PDWord(FileBase + ImportEntry^.OriginalFirstThunk)
else LookupEntry := PDWord(FileBase + ImportEntry^.FirstThunk);
{继续读取此Dll直到为空}
while LookupEntry^ <> 0 do
begin
{函数入口}
SetLength(PEImports[High(PEImports)].Entries, Length(PEImports[High(PEImports)].Entries) + 1);
with PEImports[High(PEImports)].Entries[High(PEImports[High(PEImports)].Entries)] do
begin
if (LookupEntry^ and $80000000) <> 0 then
begin
NameOrID := niID;
ID := LookupEntry^ and $7FFFFFFF; {为ID,屏蔽最高位}
frmPEEntry.listbox1.items.add(format('函数编号:%-34d 来自的DLL:%-28s 地址:%.8X',[id,PEImports[High(PEImports)].DllName, LookupEntry^]));
end
else
begin
NameOrID := niName;
ImportByName:=PImportByName(FileBase + LookupEntry^);
Name := ImportByName^.ProcedureName; {头两个字节存储ID,其后紧跟为名字}
frmPEEntry.listbox1.items.add(format('函数名:%-36s 来自的DLL:%-18s Hint:%.4X 地址:%.8X',[ImportByName^.ProcedureName, PEImports[High(PEImports)].DllName, ImportByName^.ProcedureHint, LookupEntry^]));
end;
// PAddress := PChar(LookupEntry);
end;
Inc(LookupEntry);
end; //end with
Inc(ImportEntry);
end; //end while
end;
if NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress <> 0 then
begin
ExportEntry := PImageExportDirectory(FileBase +
NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
{ExportEntry指向导出表的位置}
AddressOfNames := FileBase + ExportEntry^.AddressOfNames;
AddressOfNameOrdinals := FileBase + ExportEntry^.AddressOfNameOrdinals;
AddressOfFunctions := FileBase + ExportEntry^.AddressOfFunctions;
{导出的函数的个数}
setlength(PEExport,ExportEntry^.NumberOfFunctions);
// FillChar(FList^, FCount * SizeOf(TpeExport), 0);
for I := 0 to ExportEntry^.NumberOfNames - 1 do {以名字导出的函数的个数}
begin
{保存导出地址}
PEExport[I].Name := FileBase + PDWord(AddressOfNames + I * 4)^;
{以ID来查找的导出函数}
PEExport[I].RelativeID := PWord(AddressOfNameOrdinals + I * 2)^ ;
PEExport[I].ID := PEExport[I].RelativeID + integer(ExportEntry^.Base-1);
{函数所处一地址}
PEExport[I].Address := PDword(AddressOfFunctions + PEExport[I].RelativeID * 4)^; //相对地址,+FileBase=绝对地址
listbox2.items.add(format('函数名:%-36s 编号:%.5d 地址:%.8X',[PEExport[I].name,PEExport[I].ID ,Dword(PEExport[I].address)]));
end;
for I := 0 to ExportEntry^.NumberOfFunctions - 1 do {搜索以编号导出的函数}
begin
Found:=false;
for J := 0 to ExportEntry^.NumberOfNames - 1 do
begin
if I=PEExport[J].RelativeID then //if I+(Base-1)=PEExport[J].ID then
begin
Found:=true;
break;
end;
end;
if not Found then
begin
PEExport[I].Name := '';
PEExport[I].RelativeID := I;
PEExport[I].ID := PEExport[I].RelativeID + integer(ExportEntry^.Base-1);
PEExport[I].Address := PDword(AddressOfFunctions + PEExport[I].ID * 4)^; //相对地址,+FileBase=绝对地址
listbox2.items.add(format('函数名:%-36s 编号:%.5d 地址:%.8X',['',PEExport[I].ID-integer(ExportEntry^.Base-1) ,Dword(PEExport[I].address)]));
end;
end;
end;
end;
VirtualFree(FileBase, 0, MEM_RELEASE);
FileStream.free;
end;
procedure TfrmPEEntry.BitBtn2Click(Sender: TObject);
begin
close;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -