Trabaja en Ring3 pero maneja estructuras, APIs y tipos de Ring0.
Se usa el bloque PEB (Process Enviroment Block) este es el bloque mas intimo de Ring3 (el bloque mas intimo es la EPROCESS pero solo es accesible desde Ring0) al obtenerlo podemos devolver la ImageBase del proceso.
Solo se necesita pasarle un Handle del proceso con privilegios PROCESS_ALL_ACCESS.
Código: Seleccionar todo
unit PEBData;
interface
uses Windows;
type
PNtAnsiString = ^TNtAnsiString;
TNtAnsiString = packed record
Length: Word;
MaximumLength: Word;
Buffer: PAnsiChar;
end;
PNtUnicodeString = ^TNtUnicodeString;
TNtUnicodeString = packed record
Length: Word;
MaximumLength: Word;
Buffer: PWideChar;
end;
PLdrModule = ^TLdrModule;
TLdrModule = packed record
InLoadOrderModuleList : TListEntry; // 0h
InMemoryOrderModuleList : TListEntry; // 8h
InInitializationOrderModuleList: TListEntry; // 10h
BaseAddress : THandle; // 18h
EntryPoint : THandle; // 1Ch
SizeOfImage : Cardinal; // 20h
FullDllName : TNtUnicodeString;// 24h
// Length (2) 24h
// MaximumLength (2) 26h
// Buffer (4) 28h
BaseDllName : TNtUnicodeString;// 2Ch
Flags : ULONG; // 34h
LoadCount : SHORT; // 38h
TlsIndex : SHORT; // 3Ah
HashTableEntry : TListEntry; // 3Ch
TimeDataStamp : ULONG; // 44h
end;
PPebLdrData = ^TPebLdrData;
TPebLdrData = packed record
Length : Cardinal; // 0h
Initialized : LongBool; // 4h
SsHandle : THandle; // 8h
InLoadOrderModuleList : TListEntry; // 0Ch
InMemoryOrderModuleList : TListEntry; // 14h
InInitializationOrderModuleList: TListEntry; // 1Ch
end;
PCurDir = ^TCurDir;
TCurDir = packed record
DosPath: TNtUnicodeString;
Handle : THandle;
end;
PRtlDriveLetterCurDir = ^TRtlDriveLetterCurDir;
TRtlDriveLetterCurDir = packed record
Flags : Word;
Length : Word;
TimeStamp: Cardinal;
DosPath : TNtAnsiString;
end;
PRtlUserProcessParameters = ^TRtlUserProcessParameters;
TRtlUserProcessParameters = record
MaximumLength : Cardinal;
Length : Cardinal;
Flags : Cardinal;
DebugFlags : Cardinal;
ConsoleHandle : THandle;
ConsoleFlags : Cardinal;
StandardInput : THandle;
StandardOutput : THandle;
StandardError : THandle;
CurrentDirectory : TCurDir;
DllPath : TNtUnicodeString;
ImagePathName : TNtUnicodeString;
CommandLine : TNtUnicodeString;
Environment : Pointer;
StartingX : Cardinal;
StartingY : Cardinal;
CountX : Cardinal;
CountY : Cardinal;
CountCharsX : Cardinal;
CountCharsY : Cardinal;
FillAttribute : Cardinal;
WindowFlags : Cardinal;
ShowWindowFlags : Cardinal;
WindowTitle : TNtUnicodeString;
DesktopInfo : TNtUnicodeString;
ShellInfo : TNtUnicodeString;
RuntimeData : TNtUnicodeString;
CurrentDirectores: Array [0..31] of TRtlDriveLetterCurDir;
end;
PPebFreeBlock = ^TPebFreeBlock;
TPebFreeBlock = record
Next: PPebFreeBlock;
Size: Cardinal;
end;
PPeb = ^TPeb;
TPeb = packed record
InheritedAddressSpace : Boolean;
ReadImageFileExecOptions : Boolean;
BeingDebugged : Boolean;
SpareBool : Boolean;
Mutant : Pointer;
ImageBaseAddress : Pointer;
Ldr : PPebLdrData;
ProcessParameters : PRtlUserProcessParameters;
SubSystemData : Pointer;
ProcessHeap : Pointer;
FastPebLock : Pointer;
FastPebLockRoutine : Pointer;
FastPebUnlockRoutine : Pointer;
EnvironmentUpdateCount : Cardinal;
KernelCallbackTable : Pointer;
case Integer of
4: (
EventLogSection : Pointer;
EventLog : Pointer);
5: (
SystemReserved : Array [0..1] of Cardinal;
{ end; }
FreeList : PPebFreeBlock;
TlsExpansionCounter : Cardinal;
TlsBitmap : Pointer;
TlsBitmapBits : Array [0..1] of Cardinal;
ReadOnlySharedMemoryBase : Pointer;
ReadOnlySharedMemoryHeap : Pointer;
ReadOnlyStaticServerData : ^Pointer;
AnsiCodePageData : Pointer;
OemCodePageData : Pointer;
UnicodeCaseTableData : Pointer;
NumberOfProcessors : Cardinal;
NtGlobalFlag : Cardinal;
Unknown : Cardinal;
CriticalSectionTimeout : TLargeInteger;
HeapSegmentReserve : Cardinal;
HeapSegmentCommit : Cardinal;
HeapDeCommitTotalFreeThreshold: Cardinal;
HeapDeCommitFreeBlockThreshold: Cardinal;
NumberOfHeaps : Cardinal;
MaximumNumberOfHeaps : Cardinal;
ProcessHeaps : ^Pointer;
GdiSharedHandleTable : Pointer;
ProcessStarterHelper : Pointer;
GdiDCAttributeList : Cardinal;
LoaderLock : Pointer;
OSMajorVersion : Cardinal;
OSMinorVersion : Cardinal;
OSBuildNumber : Word;
OSCSDVersion : Word;
OSPlatformId : Cardinal;
ImageSubsystem : Cardinal;
ImageSubsystemMajorVersion : Cardinal;
ImageSubsystemMinorVersion : Cardinal;
ImageProcessAffinityMask : Cardinal;
GdiHandleBuffer : Array [0..33] of Cardinal;
PostProcessInitRoutine : ^Pointer;
TlsExpansionBitmap : Pointer;
TlsExpansionBitmapBits : Array [0..31] of Cardinal;
SessionId : Cardinal;
AppCompatInfo : Pointer;
CSDVersion : TNtUnicodeString);
end;
TProcessInfoClass = (
ProcessBasicInformation,
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort,
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers, // Note: this is kernel mode only
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
ProcessDeviceMap,
ProcessSessionInformation,
ProcessForegroundInformation,
ProcessWow64Information,
MaxProcessInfoClass);
PROCESS_BASIC_INFORMATION = packed record
ExitStatus: DWORD;
PebBaseAddress: Pointer;
AffinityMask: DWORD;
BasePriority: DWORD;
UniqueProcessId: DWORD;
InheritedUniquePID:DWORD;
end;
TProcessBasicInformation = PROCESS_BASIC_INFORMATION;
PProcessBasicInformation = ^TProcessBasicInformation;
function ZwQueryInformationProcess(hProcess: THandle; InformationClass: DWORD; Buffer: PProcessBasicInformation; BufferLength : DWORD; ReturnLength: PDWORD): Cardinal; stdcall; external 'ntdll.dll' name 'ZwQueryInformationProcess';
function ZwReadVirtualMemory(ProcessHandle: DWord; BaseAddress: Pointer; Buffer: Pointer; BufferLength: DWord; ReturnLength: PDWord): Cardinal; stdcall; external 'ntdll.dll';
function GetProcessImageBase(hProcess: THandle): Integer;
implementation
function NtSuccess(AStatus: Longint): Boolean;
begin
Result := AStatus >= 0;
end;
function GetProcessImageBase(hProcess: THandle): Integer;
var PBI: TProcessBasicInformation;
PEB: TPeb;
dwRet: DWord;
begin
Result := 0;
//Obtenemos la información del proceso
if not NTSuccess(ZwQueryInformationProcess(hProcess, 0 {ProcessBasicInformation}, @PBI, SizeOf(TProcessBasicInformation), @dwRet)) then
Exit;
//Copiamos el bloque PEB
if not NTSuccess(ZwReadVirtualMemory(hProcess, PBI.PebBaseAddress, @PEB, SizeOf(TPeb), @dwRet)) then
Exit;
//Devolvemos el valor del ImageBase
Result := Integer(PEB.ImageBaseAddress);
end;
end.
Saludos!