OK, I hacked into a 32-bit solution that gets the base address of an image from a PEB process.
File EntryPt.c :
#include <windows.h> #include <tchar.h> #include <psapi.h> #include <stdio.h> #include <stddef.h> // To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS // and compile with -DPSAPI_VERSION=1 NTSTATUS (NTAPI *pNtQueryInformationProcess)(HANDLE, /*enum _PROCESSINFOCLASS*/DWORD, PVOID, ULONG, PULONG) = NULL; extern PVOID GetPeb(HANDLE ProcessHandle); // PEB definition comes from winternl.h. This is a 32-bit PEB. typedef struct _PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; // Reserved3[1] points to PEB /* PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; BYTE Reserved4[104]; PVOID Reserved5[52]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE Reserved6[128]; PVOID Reserved7[1]; ULONG SessionId; */ } PEB, *PPEB; int main(int argc, TCHAR* argv[]) { STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; PPEB pPeb; PVOID pImage, pEntry; PIMAGE_NT_HEADERS pNtHeaders; LONG e_lfanew; SIZE_T NumberOfBytesRead; pNtQueryInformationProcess = (NTSTATUS(NTAPI*)(HANDLE, /*enum _PROCESSINFOCLASS*/DWORD, PVOID, ULONG, PULONG)) GetProcAddress( GetModuleHandle(TEXT("ntdll.dll")), TEXT("NtQueryInformationProcess")); if (pNtQueryInformationProcess == NULL) { printf("GetProcAddress(ntdll.dll, NtQueryInformationProcess) failed with error 0x%08X\n", GetLastError()); return -1; } memset(&StartupInfo, 0, sizeof(StartupInfo)); memset(&ProcessInfo, 0, sizeof(ProcessInfo)); if (!CreateProcess( NULL, (argc > 1) ? argv[1] : argv[0], NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInfo)) { printf("CreateProcess() failed with error 0x%08X\n", GetLastError()); return -1; } printf("Current process:\n"); pPeb = GetPeb(GetCurrentProcess()); printf("PEB: 0x%08X\n", pPeb); pImage = pPeb->Reserved3[1]; printf("Image base: 0x%08X\n", pImage); pNtHeaders = (PIMAGE_NT_HEADERS)((PCHAR)pImage + ((PIMAGE_DOS_HEADER)pImage)->e_lfanew); pEntry = (PVOID)((PCHAR)pImage + pNtHeaders->OptionalHeader.AddressOfEntryPoint); printf("Image entry point: 0x%08X\n", pEntry); printf("\n"); printf("Child process:\n"); pPeb = GetPeb(ProcessInfo.hProcess); printf("PEB: 0x%08X\n", pPeb); if (!ReadProcessMemory( ProcessInfo.hProcess, &pPeb->Reserved3[1], &pImage, sizeof(pImage), &NumberOfBytesRead) || NumberOfBytesRead != sizeof(pImage)) { printf("ReadProcessMemory(&pImage) failed with error 0x%08X\n", GetLastError()); goto End; } printf("Image base: 0x%08X\n", pImage); if (!ReadProcessMemory( ProcessInfo.hProcess, (PCHAR)pImage + offsetof(IMAGE_DOS_HEADER, e_lfanew), &e_lfanew, sizeof(e_lfanew), &NumberOfBytesRead) || NumberOfBytesRead != sizeof(e_lfanew)) { printf("ReadProcessMemory(&e_lfanew) failed with error 0x%08X\n", GetLastError()); goto End; } pNtHeaders = (PIMAGE_NT_HEADERS)((PCHAR)pImage + e_lfanew); if (!ReadProcessMemory( ProcessInfo.hProcess, (PCHAR)pNtHeaders + offsetof(IMAGE_NT_HEADERS, OptionalHeader.AddressOfEntryPoint), &pEntry, sizeof(pEntry), &NumberOfBytesRead) || NumberOfBytesRead != sizeof(pEntry)) { printf("ReadProcessMemory(&pEntry) failed with error 0x%08X\n", GetLastError()); goto End; } pEntry = (PVOID)((PCHAR)pImage + (SIZE_T)pEntry); printf("Image entry point: 0x%08X\n", pEntry); End: TerminateProcess(ProcessInfo.hProcess, 0); CloseHandle(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); return 0; }
File GetPeb.c :
#include <ntddk.h> extern NTSTATUS (NTAPI *pNtQueryInformationProcess)( HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); PVOID GetPeb(HANDLE ProcessHandle) { NTSTATUS status; PROCESS_BASIC_INFORMATION pbi; PVOID pPeb; memset(&pbi, 0, sizeof(pbi)); status = pNtQueryInformationProcess( ProcessHandle, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); pPeb = NULL; if (NT_SUCCESS(status)) { pPeb = pbi.PebBaseAddress; } return pPeb; }
Compiled using Open Watcom 1.9 through this batch file:
set INCLUDE=%INCLUDE%;%WATCOM%\H\NT;%WATCOM%\H\NT\DDK; wcl386 /we /wx /q /d2 -DPSAPI_VERSION=1 EntryPt.c GetPeb.c %WATCOM%\lib386\nt\psapi.lib
Exit (runs on Windows XP):
>EntryPt.exe Current process: PEB: 0x7FFDD000 Image base: 0x00400000 Image entry point: 0x004013E8 Child process: PEB: 0x7FFDC000 Image base: 0x00400000 Image entry point: 0x004013E8 >EntryPt.exe calc.exe Current process: PEB: 0x7FFDC000 Image base: 0x00400000 Image entry point: 0x004013E8 Child process: PEB: 0x7FFDB000 Image base: 0x01000000 Image entry point: 0x01012475
This code uses NtQueryInformationProcess () , which may change in future versions of the OS. It also uses the undocumented definition of WOW64 ), and it may not work with future versions of Windows.