Как найти точку входа (или базовый адрес) процесса - позаботьтесь о 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]