我正在尝试编写一个应用程序,该应用程序读取 EXE 文件并将其放入内存中,修复其新的 IAT 表并解决重定位问题。
int main()
{
LOADED_IMAGE loadedImage;
MapAndLoad("D:\\program\\test.exe", nullptr, &loadedImage, false, false);
LPVOID v = VirtualAlloc(nullptr, loadedImage.FileHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(v, loadedImage.MappedAddress, loadedImage.FileHeader->OptionalHeader.SizeOfHeaders);
for (int i = 0; i < loadedImage.FileHeader->FileHeader.NumberOfSections; ++i) {
const IMAGE_SECTION_HEADER& section = loadedImage.Sections[i];
LPVOID dest = reinterpret_cast<BYTE*>(v) + section.VirtualAddress;
LPVOID src = reinterpret_cast<BYTE*>(loadedImage.MappedAddress) + section.PointerToRawData;
memcpy(dest, src, section.SizeOfRawData);
}
DWORD_PTR delta = reinterpret_cast<DWORD_PTR>(v) - loadedImage.FileHeader->OptionalHeader.ImageBase;
ApplyRelocations(v, loadedImage.FileHeader, delta);
IMAGE_DATA_DIRECTORY& importDirectory = loadedImage.FileHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
IMAGE_IMPORT_DESCRIPTOR* imd = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*>((char*)v + importDirectory.VirtualAddress);
while (imd->Name != 0) {
const char* dllName = reinterpret_cast<const char*>((char*)v+ imd->Name);
if (*dllName == '\0') {
imd++;
continue;
}
HMODULE hMod = GetModuleHandleA((LPCSTR)dllName);
if (!hMod) {
hMod = LoadLibraryExA((LPSTR)(std::string("C:\\Windows\\System32\\") + std::string(dllName)).c_str(), 0, DONT_RESOLVE_DLL_REFERENCES);
}
auto nameAddressPtr = (PIMAGE_THUNK_DATA)(DWORD_PTR)(imd->OriginalFirstThunk +(char*)v);
auto funcAddr = (PIMAGE_THUNK_DATA)(DWORD_PTR)(imd->FirstThunk + (char*)v);
while (nameAddressPtr->u1.Function) {
FARPROC proc;
auto impotByNameImage = (PIMAGE_IMPORT_BY_NAME)(DWORD_PTR)(nameAddressPtr->u1.AddressOfData + (char*)v);
if (nameAddressPtr->u1.Ordinal&IMAGE_ORDINAL_FLAG) {
proc = GetProcAddress(hMod, MAKEINTRESOURCEA(impotByNameImage->Name));
}
else {
proc = GetProcAddress(hMod,impotByNameImage->Name);
}
auto oldProt = 0ul;
VirtualProtect(imd->FirstThunk+(char*)v, sizeof(IMAGE_THUNK_DATA), PAGE_EXECUTE_READWRITE, &oldProt);
funcAddr->u1.AddressOfData = (DWORD_PTR)proc;
nameAddressPtr++;
funcAddr++;
}
imd++;
}
void (*q)() = (void(*)())(reinterpret_cast<BYTE*>(v) + loadedImage.FileHeader->OptionalHeader.AddressOfEntryPoint);
UnMapAndLoad(&loadedImage);
q();
}
我正在尝试阅读的应用程序只是一个简单的
hello world
应用程序。
是否可以解析应用程序并从内存中运行它?或者,操作系统中是否实施了安全措施来防止这种情况发生?
我确信 IAT 已正确初始化,因为我可以在 x64dbg 中看到正确的函数名称。
PS:由于不确定性,我到目前为止已经忽略了解析
.tls
部分。
是的。有一个库here可以从内存加载模块。 它修补导入表并使返回的句柄可在 GetProcAddress 中使用。我用 Dll 测试了它,但只要您调用入口点,它就应该可以在任何 PE 上工作,或者更容易地从可执行文件中导出一个函数来为您调用它。
我使用它的修改版本将 x86 DLL 加载到 x64 进程中。