是否可以从内存中运行可执行文件?

问题描述 投票:0回答:1

我正在尝试编写一个应用程序,该应用程序读取 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
部分。

c++ windows winapi exe
1个回答
0
投票

是的。有一个库here可以从内存加载模块。 它修补导入表并使返回的句柄可在 GetProcAddress 中使用。我用 Dll 测试了它,但只要您调用入口点,它就应该可以在任何 PE 上工作,或者更容易地从可执行文件中导出一个函数来为您调用它。

我使用它的修改版本将 x86 DLL 加载到 x64 进程中。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.