Как найти точку входа (или базовый адрес) процесса - позаботьтесь о ASLR

Из-за ASLR(рандомизации размещения адресного пространства, начиная с Windows Vista), базовый адрес exe является случайным, поэтому его больше нельзя найти в PE-файле.

В Visual C++ теперь опция /DYNAMICBASE включена по умолчанию, поэтому базовый адрес exe является случайным - каждый раз, когда его загружает загрузчик, это происходит.

После некоторых исследований в Google, я пытаюсь использовать этот шаблон, но он не работает.

Пожалуйста, взгляните на этот простой пример кода:

#include <iostream>

#include <vector>
#include <stdio.h>

#include <windows.h>
#include <psapi.h>

int main()
{
    STARTUPINFOA startupInfo = {0};
    startupInfo.cb = sizeof(startupInfo);
    PROCESS_INFORMATION processInformation = {0};

    if (CreateProcessA("UseCase01.exe", NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, &processInformation))
    {
        std::vector<HMODULE> buf(128);
        DWORD needed = 0;
        for (;;) {
            if (EnumProcessModulesEx(processInformation.hProcess, &buf[0], DWORD(buf.size()*sizeof(HMODULE)), &needed, LIST_MODULES_ALL) == FALSE) {
                DWORD ec = GetLastError();
                std::cout << ec << std::endl;
                break;
            }
            else if (needed <= buf.size() * sizeof(HMODULE)) {
                break;
            }
            else {
                const size_t oldSize = buf.size();
                buf.resize(oldSize * 2);
            }
        }
        ResumeThread(processInformation.hThread);
    }
}

Моя ОС - Windows 7 64bit Pro, мой компилятор - VS2013, это 32-битная консольная программа, и UseCase01.exe также является 32-битной консольной программой.

EnumProcessModulesEx всегда терпит неудачу, код ошибки, возвращаемый GetLastError(), равен 299, MSDN говорит об этом коде ошибки: ERROR_PARTIAL_COPY, "Была выполнена только часть запроса ReadProcessMemory или WriteProcessMemory".

Об этом коде ошибки на странице EnumProcessModules MSDN: "Если эта функция вызывается из 32-разрядного приложения, работающего на WOW64, она может перечислять только модули 32-разрядного процесса. Если процесс является 64-разрядным процессом, эта функция завершается ошибкой, а последний код ошибки - ERROR_PARTIAL_COPY (299)."

Но я уверен, что моя программа 32-битная, и я тестировал на 64-битной программе, она тоже не работает с ошибкой 299, поэтому она не имеет смысла.

"Дескриптор, возвращенный функцией CreateProcess, имеет доступ PROCESS_ALL_ACCESS к объекту процесса". - из MSDN, так что это не может быть проблема с правами доступа?

Затем я пытаюсь использовать CreateToolhelp32Snapshot, он завершается ошибкой с кодом ошибки 299, как 32-разрядным, так и 64-разрядным

Я просто не могу понять это.

Моя цель - найти точку входа в подпроцесс безопасным способом, независимо от того, 32-битный или 64-битный процесс.

Я нашел, что это самый глубокий ответ на этот вопрос: http://winprogger.com/getmodulefilenameex-enumprocessmodulesex-failures-in-wow64/

К сожалению, 64-битная программа тоже не сработает, не только для Wow64, поэтому она не имеет смысла.

Если это невозможно, каков хороший способ (найти базовый адрес или точку входа приостановленного подпроцесса)?

2 ответа

Решение

Вы создаете процесс приостановлено. Пока будут созданы ключевые структуры данных ядра, модули не будут загружены (что потребует выполнения кода в точках входа модулей (dllmain)).

Таким образом, ошибка имеет смысл: структуры данных для отслеживания загруженных модулей будут пустыми и, возможно, вообще не будут выделяться.

Немного подождите, это поможет вам, похоже, в данный момент ресурс недоступен.

Во всех операционных системах Windows (32/64bit):

DWORD ImageBaseAddress = ((LPDWORD)PEB)[2]
Другие вопросы по тегам