由于ASLR(地址空间布局随机化,自Windows Vista以来),exe的基地址是随机的,因此无法在PE文件中找到它。
在Visual C ++中,现在/ DYNAMICBASE选项是默认启用的,因此exe的基地址是随机的 - 每当加载器加载它时,它就会发生。
在谷歌做了一些研究后,我试图使用这种模式,但它不起作用。
请看一下这个简单的代码示例:
#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 64位专业版,我的编译器是VS2013,这是一个32位控制台程序,而UseCase01.exe也是一个32位控制台程序。
EnumProcessModulesEx总是失败,GetLastError()返回的错误代码是299,MSDN说明了这个错误代码:ERROR_PARTIAL_COPY,“只完成了ReadProcessMemory或WriteProcessMemory请求的一部分。”
关于此错误代码,在MSDN的EnumProcessModules页面上,“如果从WOW64上运行的32位应用程序调用此函数,它只能枚举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,所以它没有出现。
如果这是不可行的,那么有什么好办法(找到暂停子流程的基地址或入口点)?
您正在创建暂停的流程。虽然将创建关键内核数据结构,但不会加载任何模块(这将涉及在模块入口点(dllmain
)中执行代码)。
因此错误是有道理的:跟踪加载的模块的数据结构将是空的,并且很可能根本不分配。
在所有Windows操作系统(32/64位)上:
DWORD ImageBaseAddress = ((LPDWORD)PEB)[2]
放一些等待它会帮助你看起来目前资源不可用。