Как получить адрес точки входа процесса
Я создаю приостановленный процесс test.exe
такой:
CreateProcess(
TEXT( "C:Documents and Settingswilly桌面projecttest.exe" ),
TEXT( "test.exe" ),
NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi
);
как я могу получить точку входа/запуска/основной адрес для процесса test.exe
после его создания?
должен ли я искать информацию о файле PE или использовать API, например ReadProcessMemory()
или VirtualQueryEx()
2 ответов
когда вы выполняете процесс с CREATE_SUSPENDED
, Он начинается с кода инициализации ntdll. Это мало пользы для поиска .точка входа exe; вы должны проверить заголовки exe-файла непосредственно для этого:
#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;
}
обратите внимание, что этот адрес является первым кодом, который выполняется после завершения инициализации DLL. Он может быть не равен (и обычно не равен) адресу main
или WinMain
; обычно некоторый код запуска библиотеки C статически связан с ИСПОЛНЯЕМЫЙ.
также обратите внимание, что это не удастся, если EXE перемещается и ASLR включен, так как EXE может быть загружен по другому базовому адресу. Вам нужно будет найти, где находится базовый адрес EXE, и использовать его вместо ntHeader->OptionalHeader.ImageBase
в этом случае.
хорошо, я взломал 32-битное единственное решение, которое получает базовый адрес изображения из процесса PEB.
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;
}
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;
}
скомпилирован с Open Watcom 1.9 через этот пакетный файл:
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
вывод (выполняется в 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
этот код использует NtQueryInformationProcess() это может измениться в будущих версиях ОС. Он также использует недокументированные определение на ПЭБ. Этот код не будет работать на 64-разрядной Windows, если не будет изменен соответствующим образом (возможно, с учетом эмуляторе WoW64) и он может не работать с будущими версиями Windows.