How can I get the address of the process entry point

I create a suspended test.exe process as follows:

 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 start point / start / main address for the test.exe process after creating it?

Should I search for PE file information or use an API like ReadProcessMemory() or VirtualQueryEx()

+6
source share
2 answers

When you execute a process with CREATE_SUSPENDED , it starts with the ntdll initialization code. This is not suitable for finding an entry point .exe; you should directly examine exe file headers:

 #include <Windows.h> #include <WinNT.h> DWORD FindEntryPointAddress(_TCHAR *exeFile) { BY_HANDLE_FILE_INFORMATION bhfi; HANDLE hMapping; char *lpBase; HANDLE hFile = CreateFile(exeFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) fail("Opening exe file", GetLastError()); if (!GetFileInformationByHandle(hFile, &bhfi)) fail("GetFileInformationByHandle", GetLastError()); hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, bhfi.nFileSizeHigh, bhfi.nFileSizeLow, NULL); if (!hMapping) fail("CreateFileMapping", GetLastError()); lpBase = (char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, bhfi.nFileSizeLow); if (!lpBase) fail("MapViewOfFile", GetLastError()); PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpBase; if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) fail("bad dos header signature", 0); PIMAGE_NT_HEADERS32 ntHeader = (PIMAGE_NT_HEADERS32)(lpBase + dosHeader->e_lfanew); if (ntHeader->Signature != IMAGE_NT_SIGNATURE) fail("bad nt header signature", 0); DWORD pEntryPoint = ntHeader->OptionalHeader.ImageBase + ntHeader->OptionalHeader.AddressOfEntryPoint; UnmapViewOfFile((LPCVOID)lpBase); CloseHandle(hMapping); CloseHandle(hFile); return pEntryPoint; } 

Note that this address has the first code that is executed after the initialization of the DLL. It cannot be (and usually not equal to) equal to the address of main or WinMain ; this is usually some C library startup code statically associated with EXE.

Also note that this will happen if the EXE moves and the ASLR is turned on, as the EXE can be loaded with a different base address. You will need to find where the base address of the EXE is located, and use this instead of ntHeader->OptionalHeader.ImageBase in this case.

+1
source

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.

+6
source

Source: https://habr.com/ru/post/902811/


All Articles