program k32base;
uses
Windows;
{$R *.res}
const
IMAGE_FILE_LARGE_ADDRESS_AWARE = $0020;
{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}
////////////////////////////////////////////////////////////////////////////////
//
// GetKernel32Base
//
// Returns base address of the kernel32.dll by walking the SEH handler chain.
// Assumes:
// a) Last record is ThreadStartup's exception handler inside kernel32.dll.
// b) Images loaded on 64KB boundary (TSystemInfo.dwAllocationGranularity).
//
// (code is optimized for minimal code size)
//
function GetKernel32Base: Pointer;
assembler;
type
PExceptionRegistrationRecord = ^TExceptionRegistrationRecord;
TExceptionRegistrationRecord =
record
Next : PExceptionRegistrationRecord;
Handler: TFarProc;
end;
PNtTib = ^TNtTib;
TNtTib =
record
ExceptionList : PExceptionRegistrationRecord;
StackBase : Pointer;
StackLimit : Pointer;
SubSystemTib : Pointer;
case Integer
of
1: (Version : DWORD);
0: (FiberData : Pointer;
ArbitraryUserPointer: Pointer;
Self : PNtTib);
end;
asm
xor eax, eax
mov ecx, fs:[eax].TNtTib.ExceptionList
@@loop:
{ Loop until 0/-1 }
jecxz @@last
mov eax, [ecx].TExceptionRegistrationRecord.Handler
mov ecx, [ecx].TExceptionRegistrationRecord.Next
inc ecx
jecxz @@last
dec ecx
jmp @@loop
@@last:
{ Align and check }
dec ecx
shl ecx, 10h
and eax, ecx
jz @@exit
@@down:
{ Search downward }
add eax, ecx
cmp [eax].TImageDosHeader.e_magic, IMAGE_DOS_SIGNATURE
jne @@down
movzx edx, word ptr [eax].TImageDosHeader._lfanew
cmp [eax+edx].TImageNtHeaders.Signature, IMAGE_NT_SIGNATURE
jne @@down
@@exit:
{ exit: 30h bytes }
end;
////////////////////////////////////////////////////////////////////////////////
function HModToHex(Module: HMODULE; Digits: Integer):
string;
const
Digi:
array [0..15]
of Char = '
0123456789ABCDEF';
var
Loop: Byte;
begin
SetLength(Result, Digits);
for Loop := Digits
downto 1
do
begin
Result[Loop] := Digi[Byte(Module)
and $0F];
Module := Module
shr $04;
end;
end;
var
HKernel32: HMODULE;
Filename:
array [0..MAX_PATH]
of Char;
begin
HKernel32 := HMODULE(GetKernel32Base);
GetModuleFilename(HKernel32, Filename, MAX_PATH);
MessageBox(0, Filename, PChar(HModToHex(HKernel32, 8)), MB_OK);
end.