Реальный начальный адрес процесса в памяти / API отладки Win32

Сначала я новичок в c ++ и отлаживаю. Я использую API CreateProcess с параметром DEBUG_ONLY_THIS_PROCESS, затем жду CREATE_PROCESS_DEBUG_EVENT. Когда получено, я проверяю регистр Eip, чтобы получить адрес точки. И я подумал, что этот пункт является адресом главной функции.

Чтобы проверить эту идею, я использовал ollydbg, чтобы увидеть начальный адрес exe. Но это не было с моим. Тот, который я нашел с отладочным apis, это 0x77a364d8, но олли говорит, что это 0x00401000. Тогда я не остановился и проверил адрес 0x77a364d8 в Олли. Я нашел адрес и установил там точку останова.

Затем я перезагрузил olly и увидел, что olly сначала идет по адресу 0x77a364d8 и загружает процесс, а затем переходит по адресу 0x00401000 и ждет там. Адрес 0x77a364d8 указывает на некоторые функции ntdll для загрузки процесса в память, как я вижу.

Если это правда, как я могу получить адрес 0x00401000 по коду (c ++, я новичок и прошу вас пересечь :)), и это адрес основной функции или как?

3

Решение

После того как вы получите CREATE_PROCESS_DEBUG_EVENT Вы должны иметь доступ к CREATE_PROCESS_DEBUG_INFO член союза. У него есть член под названием lpStartAddress,

Ваш цикл событий отладки должен выглядеть примерно так:

DWORD dwContinueDebugStatus = DBG_CONTINUE;
while(dwContinueDebugStatus)
{
DEBUG_EVENT debugEvt;
WaitForDebugEvent(&debugEvt, INFINITE);
switch(debugEvt.dwDebugEventCode)
{
case CREATE_PROCESS_DEBUG_EVENT:
// Grab the main thread entry point.
LPTHREAD_START_ROUTINE exentry = debugEvt.u.CreateProcessInfo.lpStartAddress;
break;
/* Handle the rest of your debug events here. */
}
ContinueDebugEvent(debugEvt.dwProcessId, debugEvt.dwThreadId, dwContinueDebugStatus);
}

Редактировать:
Несколько вещей, которые я забыл упомянуть …

Получение точки входа любым из этих способов, вероятно, будет функцией CRT, которая вызывает ваш main(), Не существует надежного способа получить main() без поиска символов в использовании dbghelp.dll,

Также книга Отладка приложений Джон Роббинс имеет главу о создании небольшого отладчика с примером кода. Вероятно, это лучшая документация / пример, который я нашел (но я бы хотел, чтобы это было лучше). Это может быть довольно дешево, поэтому стоит посмотреть.

3

Другие решения

Точка входа будет не (по крайней мере, нормально) быть таким же, как main, Подпись для точки входа void entrypoint(void);, Для этого нужно извлечь командную строку, разобрать ее на отдельные аргументы и т. Д. При подготовке к вызову main (и есть совершенно отдельный, который извлекает довольно разные «вещи», необходимые перед вызовом WinMain в программе с графическим интерфейсом).

Если вы хотите фактический адрес mainвы можете хотя бы попробовать использовать SymFromName для имен _main и / или _wmain (или, если вы имеете дело с программой с графическим интерфейсом, WinMain/wWinmain) чтобы получить код, который действительно является частью целевой программы, а не чего-то из библиотечного модуля, который почти никто даже не видел.

1

Это все из памяти, поэтому может содержать несколько ошибок.

Чтобы найти адрес точки входа EXE в новом процессе, необходимо прочитать поле PEB этого процесса. ImageBaseAddress, PEB всегда находится по фиксированному адресу, но это зависит от того, является ли ваш EXE-файл 32-битным или 64-битным, что вы должны определить заранее (есть 32-битный PEB для WOW64, но я думаю, что он еще не может быть инициализирован в таком случае).

Обратите внимание, что вы не можете просто извлечь это из EXE, потому что это может быть перемещено из-за ASLR. Как только вы это сделаете, вы можете прочитать PE заголовок EXE, используя ReadProcessMemory и получить AddressOfEntryPoint поле из IMAGE_OPTIONAL_HEADER структура. Это RVA, поэтому добавьте его к найденному ранее базовому адресу, и вуаля, у вас есть адрес точки входа.

0
По вопросам рекламы [email protected]