📄 pefile.pas
字号:
RL[I].FName[1], Length(RL[I].FName) * 2);
if PDWord(PChar(DirEntry) + 4)^ and $80000000 = 0 then
begin
// DataEntry
RL[I].FDataOrEntries := deData;
RL[I].FData := FFileBase + PDWord(BaseEntry + PDWord(DirEntry + 4)^)^;
RL[I].FDataSize := PInteger(BaseEntry + PDWord(DirEntry +4)^ +4)^;
end
else
begin
// SubEntries
RL[I].FDataOrEntries := deEntries;
FillResources(RL[I].FEntries,
Integer(BaseEntry + PDWord(DirEntry + 4)^ and $7FFFFFFF));
end;
Inc(DirEntry, 8);
end;
for I := NameCount to NameCount + IDCount -1 do
begin
// Create object
RL[I] := TPEResource.Create;
// Name or ID is Name.
RL[I].FNameOrID := niID;
// Copy name.
RL[I].FID := PDWord(DirEntry)^;
if PDWord(DirEntry+ 4)^ and $80000000 = 0 then
begin
// DataEntry
RL[I].FDataOrEntries := deData;
RL[I].FData := FFileBase + PDWord(BaseEntry + PDWord(DirEntry + 4)^)^;
RL[I].FDataSize := PInteger(BaseEntry + PDWord(DirEntry +4)^ +4)^;
end
else
begin
// SubEntries
RL[I].FDataOrEntries := deEntries;
FillResources(RL[I].FEntries,
Integer(BaseEntry + PDWord(DirEntry + 4)^ and $7FFFFFFF));
end;
Inc(DirEntry, 8);
end;
end;
begin
if NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size <> 0 then
begin
BaseEntry := FFileBase +
NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
FillResources(Resources, Integer(BaseEntry));
end;
end;
procedure LoadImports;
type
PImage_Import_Entry = ^Image_Import_Entry;
Image_Import_Entry = record
Characteristics: Integer;
TimeDateStamp: Integer;
MajorVersion: WORD;
MinorVersion: WORD;
Name: Integer;
LookupTable: Integer;
end;
var
ImportEntry: PImage_Import_Entry;
LookupEntry: PDWord;
begin
ImportEntry := PImage_Import_Entry(FFileBase +
NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
// Keep reading import entry until empty entry.
while ImportEntry^.Name <> 0 do
begin
// New Import entry.
SetLength(Imports, Length(Imports) +1);
with Imports[High(Imports)] do
begin
DLLName := FFileBase + ImportEntry.Name;
LookupEntry := PDWord(FFileBase + ImportEntry.LookupTable);
// Keep reading loolup table until empty lookup
while LookupEntry^ <> 0 do
begin
SetLength(Entries, Length(Entries) +1);
with Entries[High(Entries)] do
begin
if (LookupEntry^ and $80000000) <> 0 then
begin
NameOrID := niID;
ID := LookupEntry^ and $7FFFFFFF;
end
else
begin
NameOrID := niName;
Name := PChar(FFileBase + LookupEntry^ + 2);
end;
PAddress := PChar(LookupEntry);
end;
Inc(LookupEntry);
end;
Inc(ImportEntry);
end;
end;
end;
var
J: Integer;
begin
inherited Create;
FFileName := FileName;
FProjectName := ExtractFileName(FileName);
SetLength(FProjectName, Length(FProjectName) - Length(ExtractFileExt(FProjectName)));
FFileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
with FFileStream do
begin
// Read new header address.
Position := 60;
ReadBuffer(I, 4);
Position := I + 52;
ReadBuffer(ImageBase, 4);
Seek(24, soFromCurrent);
// Read Image and Header size.
ReadBuffer(FImageSize, 4);
ReadBuffer(FHeaderSize, 4);
// Allocate memory at ImageAddress.
FFileBase := VirtualAlloc(ImageBase, FImageSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
if FFileBase = nil then
begin
FFileBase := VirtualAlloc(nil, FImageSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
if FFileBase = nil then
Error('Couldn''t allocate memory.');
end;
// Read Header
Position := 0;
ReadBuffer(PPointer(FFileBase)^, FHeaderSize);
with PImageDosHeader(FFileBase)^ do
begin
// Check magic number.
if not e_magic = IMAGE_DOS_SIGNATURE then Error('unrecognized file format');
// Load NT Header.
FNTHeader := PIMAGE_NT_HEADERS(FFileBase + _lfanew);
end;
with NTHeader^ do
begin
// Check NT Header.
if Signature <> IMAGE_NT_SIGNATURE then
Error('Not a PE (WIN32 Executable) file');
// Save StackCommitSize
StackCommitSize := OptionalHeader.SizeOfStackCommit;
// Save StackReserveSize
StackReserveSize := OptionalHeader.SizeOfStackReserve;
// Save EntryPoint
EntryPoint := FFileBase + OptionalHeader.AddressOfEntryPoint;
// Save Code Size
CodeSize := OptionalHeader.SizeOfCode;
// Save Code Address
Code := FFileBase + OptionalHeader.BaseOfCode;
// Save Data Size
DataSize := OptionalHeader.SizeOfInitializedData;
// Save Data Address
Data := FFileBase + OptionalHeader.BaseOfData;
{ Read the object from file and save the information }
// Set the number of Objects
SetLength(Objects, FileHeader.NumberOfSections);
// Save the Objects
for I := 0 to High(Objects) do
begin
// Copy the name.
SetLength(Objects[I].ObjectName, 8);
Move(OptionalHeader.Objects[I].Name, Objects[I].ObjectName[1], 8);
SetLength(Objects[I].ObjectName, StrLen(PChar(Objects[I].ObjectName)));
// Save the physical size.
Objects[I].PhysicalSize := OptionalHeader.Objects[I].SizeOfRawData;
Objects[I].VirtualSize := OptionalHeader.Objects[I].Misc.VirtualSize;
// Save the address (virtual).
Objects[I].Address := FFileBase + OptionalHeader.Objects[I].VirtualAddress;
// Read the data to the Address
Objects[I].PointerToRawData := OptionalHeader.Objects[I].PointerToRawData;
Position := OptionalHeader.Objects[I].PointerToRawData;
ReadBuffer(PPointer(Objects[I].Address)^, Objects[I].PhysicalSize);
// Save the Characteristics.
Objects[I].Characteristics := OptionalHeader.Objects[I].Characteristics;
end;
// Load the BBS
for J := 0 to High(Objects) -1 do
if Objects[J].ObjectName = 'BSS' then
begin
BSS := Objects[J].Address;
BSSSize := Objects[J +1].Address - Objects[J].Address;
Break;
end;
// Set IsConsole
FIsConsole := OptionalHeader.SubSystem = 3;
Fixups := TFixups.Create(Self);
Fixups.ApplyFixups;
LoadResources;
LoadImports;
end;
end;
PEExports := TpeExportList.Create(Self);
end;
destructor TPEFile.Destroy;
procedure FreeResources(const AResources: TPEResourceList);
var
I: Integer;
begin
for I := 0 to High(AResources) do
begin
if AResources[I].DataOrEntries = deEntries then
FreeResources(AResources[I].Entries);
AResources[I].Free;
end;
end;
begin
FreeResources(Resources);
PEExports.Free;
Fixups.Free;
if FFileBase <> nil then
VirtualFree(FFileBase, 0, MEM_RELEASE);
FFileStream.Free;
inherited Destroy;
end;
procedure TPEFile.Error(S: string);
begin
raise EPEError.Create(S);
end;
function TPEFile.PhysOffset(Address: PChar): Integer;
var
I: Integer;
begin
// Return a address is physical offset in the file, for modifying it.
if (Address < FileBase) or
(Address >= Objects[High(Objects)].Address + Objects[High(Objects)].VirtualSize) then
raise EPEError.CreateFmt(SErrorAddressNotInFile, [Pointer(Address)]);
// If the address in one of the objects.
for I := 0 to High(Objects) do
if (Address >= Objects[I].Address) and (Address < Objects[I].Address + Objects[I].VirtualSize) then
begin
// Address must be inside the physical declared part.
if Address >= Objects[I].Address + Objects[I].PhysicalSize then
raise EPEError.CreateFmt(SErrorAddressNotInFile, [Pointer(Address)]);
// Calculate the address.
Result := Address - Objects[I].Address + Objects[I].PointerToRawData;
Exit;
end;
if Address < PChar(NTHeader) + SizeOf(Windows.IMAGE_NT_HEADERS) +
Length(Objects) * SizeOf(TImageSectionHeader) then
begin
Result := Address - FFileBase;
Exit;
end;
raise EPEError.CreateFmt(SErrorAddressNotInFile, [Pointer(Address)]);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -