I create a suspended process test.exe
like this:
CreateProcess(
TEXT( "C:\\Documents and Settings\\willy\\桌面\\project\\test.exe" ),
TEXT( "test.exe" ),
NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi
);
How can I get the entry point/startup/main address for the process test.exe
after it has been created?
Should I look up PE file information or use API like ReadProcessMemory()
or VirtualQueryEx()
The AddressOfEntryPoint is the relative virtual address of the entry point, not the raw offset in the file. It holds the address of the first instruction that will be executed when the program starts. Usually this is not the same as the beginning of the code section.
A function that specifies a user-defined starting address for an .exe file or DLL.
The entry point address specified in the ELF header is 0x8048170, which falls inside the region containing program code.
OK, I've hacked up a 32-bit only solution that gets the image base address from the process' PEB.
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 with Open Watcom 1.9 via 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
Output (run 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() that may change in future versions of the OS. It also uses undocumented definition of the PEB. This code won't work on 64-bit Windows unless modified appropriately (possibly taking into account WOW64) and it may not work with future versions of Windows.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With