unit PE32Stub
{platform};
interface
function GetOverlay(
var Buffer: Pointer): Cardinal;
procedure FreeOverlay(
var Buffer: Pointer);
implementation
uses
Windows;
// types/defs (mostly Delphi 2/3 stuff)
type
LONG = Longint;
const
IMAGE_DOS_SIGNATURE = $5A4D;
type
TImageDosHeader =
packed record
e_magic : WORD;
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 [0..3]
of WORD;
e_oemid : WORD;
e_oeminfo : WORD;
e_res2 :
array [0..9]
of WORD;
e_lfanew : LONG;
end;
TImageFileHeader =
packed record
Machine : WORD;
NumberOfSections : WORD;
TimeDateStamp : DWORD;
PointerToSymbolTable: DWORD;
NumberOfSymbols : DWORD;
SizeOfOptionalHeader: WORD;
Characteristics : WORD;
end;
const
IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
IMAGE_NT_OPTIONAL_HDR_MAGIC = WORD($010B);
type
TImageDataDirectory =
record
VirtualAddress: DWORD;
Size : DWORD;
end;
TImageOptionalHeader =
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;
DataDirectory :
array [0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1]
of TImageDataDirectory;
end;
const
IMAGE_NT_SIGNATURE = DWORD($00004550);
type
TImageNtHeaders =
packed record
Signature : DWORD;
FileHeader : TImageFileHeader;
OptionalHeader: TImageOptionalHeader;
end;
const
IMAGE_SIZEOF_SHORT_NAME = 8;
type
TImageSectionHeader =
packed record
Name :
array [0..IMAGE_SIZEOF_SHORT_NAME - 1]
of AnsiChar;
Misc :
record
case Integer
of
0: (PhysicalAddress: DWORD);
1: (VirtualSize : DWORD);
end;
VirtualAddress : DWORD;
SizeOfRawData : DWORD;
PointerToRawData : DWORD;
PointerToRelocations : DWORD;
PointerToLinenumbers : DWORD;
NumberOfRelocations : WORD;
NumberOfLinenumbers : WORD;
Characteristics : DWORD;
end;
// GetOverlay
function GetOverlay(
var Buffer: Pointer): Cardinal;
const
INVALID_FILE_SIZE = DWORD(-1);
INVALID_SET_FILE_POINTER = DWORD(-1);
var
FileName:
array [0..MAX_PATH]
of Char;
FileHandle: THandle;
FileSizeLo: DWORD;
DosHeader: TImageDosHeader;
BytesRead: DWORD;
NtHeaders: TImageNtHeaders;
Offset: DWORD;
Section: WORD;
SecHeader: TImageSectionHeader;
begin
Result := 0;
Buffer :=
nil;
if GetModuleFileName(HMODULE(
nil), FileName, MAX_PATH) <= 0
then
Exit;
FileHandle := CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ,
nil,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, THandle(
nil));
if INVALID_HANDLE_VALUE = FileHandle
then
Exit;
try
// Get FileSize
FileSizeLo := GetFileSize(FileHandle,
nil);
if INVALID_FILE_SIZE = FileSizeLo
then
Exit;
// Read Headers
with DosHeader, NtHeaders, NtHeaders.FileHeader, NtHeaders.OptionalHeader
do
if not ReadFile(FileHandle, DosHeader, SizeOf(TImageDosHeader), BytesRead,
nil)
or (BytesRead <> SizeOf(TImageDosHeader))
or
(e_magic <> IMAGE_DOS_SIGNATURE)
or
(e_lfanew < SizeOf(TImageDosHeader))
or
(INVALID_SET_FILE_POINTER = SetFilePointer(FileHandle,
e_lfanew - SizeOf(TImageDosHeader),
nil, FILE_CURRENT))
or
not ReadFile(FileHandle, NtHeaders, SizeOf(TImageNtHeaders), BytesRead,
nil)
or (BytesRead <> SizeOf(TImageNtHeaders))
or
(Signature <> IMAGE_NT_SIGNATURE)
or (NumberOfSections <= 0)
or
(SizeOfOptionalHeader < SizeOf(TImageOptionalHeader))
or
(INVALID_SET_FILE_POINTER = SetFilePointer(FileHandle,
SizeOfOptionalHeader - SizeOf(TImageOptionalHeader),
nil,
FILE_CURRENT))
then
Exit;
// Read Sections
Offset := 0;
for Section := 1
to NtHeaders.FileHeader.NumberOfSections
do
begin
if not ReadFile(FileHandle, SecHeader, SizeOf(TImageSectionHeader),
BytesRead,
nil)
or (BytesRead <> SizeOf(TImageSectionHeader))
then
Exit;
if Offset < SecHeader.PointerToRawData + SecHeader.SizeOfRawData
then
Offset := SecHeader.PointerToRawData + SecHeader.SizeOfRawData;
end;
if Offset <= 0
then
Exit;
Result := FileSizeLo - Offset;
if Result <= 0
then
Exit;
// Get Overlay
Buffer := VirtualAlloc(
nil, Result + 1, MEM_COMMIT, PAGE_READWRITE);
if not Assigned(Buffer)
then
begin
Result := 0;
Exit;
end;
try
if (INVALID_SET_FILE_POINTER = SetFilePointer(FileHandle, Offset,
nil,
FILE_BEGIN))
or
not ReadFile(FileHandle, Buffer^, Result, BytesRead,
nil)
or
(BytesRead <> Result)
then
begin
VirtualFree(Buffer, 0, MEM_RELEASE);
Buffer :=
nil;
Result := 0;
end
else
PAnsiChar(Buffer)[Result] := #0;
// termiating null for strings
except
VirtualFree(Buffer, 0, MEM_RELEASE);
Buffer :=
nil;
Result := 0;
end;
finally
CloseHandle(FileHandle);
end;
end;
procedure FreeOverlay(
var Buffer: Pointer);
begin
if Assigned(Buffer)
then
begin
VirtualFree(Buffer, 0, MEM_RELEASE);
Buffer :=
nil;
end;
end;
end.