Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get a process entry point address

Tags:

c

windows

winapi

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()

like image 900
user1021319 Avatar asked Dec 01 '11 03:12

user1021319


People also ask

What is the virtual address of the entry point?

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.

What is an exe entry point?

A function that specifies a user-defined starting address for an .exe file or DLL.

What is the entry point address of ELF file?

The entry point address specified in the ELF header is 0x8048170, which falls inside the region containing program code.


1 Answers

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.

like image 137
Alexey Frunze Avatar answered Oct 01 '22 14:10

Alexey Frunze