首页 > 解决方案 > C/C++ 在 x86 应用程序中使用 x64 结构参数导入 WinAPI 函数

问题描述

我有一个 x86 windows 应用程序(32 位),我正在导入一个带有 x64 结构参数定义的函数。

有问题的函数是:ImageRvaToSection。当您使用 ImageRvaToSection 时,函数定义会自动具有您的应用程序所需的结构 ( winnt.h );如果您的应用程序是 x86 (32),它使用扩展为 PIMAGE_NT_HEADERS32 的 PIMAGE_NT_HEADERS。

当然,如果您的应用程序是 x64,它使用相同的 PIMAGE_NT_HEADERS,但会扩展为 PIMAGE_NT_HEADERS64。

我需要能够在我的 x86 应用程序中使用 32 和 64 结构参数调用 ImageRvaToSection。

基本上我所做的是:

typedef PIMAGE_SECTION_HEADER(WINAPI* pImageRvaToSection64) (PIMAGE_NT_HEADERS64, PVOID, ULONG);

pImageRvaToSection64 pointerImageRvaToSection64;

pointerImageRvaToSection64 = (pImageRvaToSection64)::GetProcAddress(::GetModuleHandle(L"Dbghelp.dll"),"ImageRvaToSection");

这在我的测试中效果很好,我可以使用 pointerImageRvaToSection64 和 IMAGE_NT_HEADERS64 作为从 32 位应用程序内部调用的参数。

但是,我不知道这样做有多安全?我知道 wow64ext,但我不确定这是否适用于这种情况。

请指教。

标签: c++windowswinapi

解决方案


原始答案MSDN
上没有关于此的评论,但我认为它应该是通用的,因为 PE 格式。记住,在达到. 因此,该宏是 WoW64 安全的。您需要做的就是遍历并检查传递的 VA 是否在 VA 部分范围内。IMAGE_OPTIONAL_HEADERIMAGE_FIRST_SECTION(Nt)ImageFileHeader.NumberOfSections

更新
当我回答时我在移动设备上,但我只是去看看ImageRvaToSectionWindows 10。正如预期的那样,没有架构检查,它适用于两者PE32并且PE64文件相同。应该注意的Base是,甚至没有使用该参数,这可能是由于从那时起的向后兼容性,在这种情况下,这些旧版本的体系结构之间可能存在问题。由于 MSDN 没有关于架构的评论,我不能从技术上保证它对所有以前版本的 Windows 都是安全的。但是,确实没有理由不这样做,特别是因为它在 W10 上是安全的,并且没有任何评论表明这种情况已经改变。

替代方案
正如我在最初的回答中提到的那样,以独立于架构的方式实现自己是微不足道的。下面的代码使用与ImageRvaToSection我的系统相反的方法,并保证对PE32和都有效PE64

template<typename T>
PIMAGE_SECTION_HEADER ImageRvaToSectionEx(T NtHeaders, uint32_t Rva)
{
    auto nt = NtHeaders;
    auto num_sections = nt->FileHeader.NumberOfSections;
    auto cur_section = IMAGE_FIRST_SECTION(nt);

    for (auto i = 0; i < num_sections; ++i, ++cur_section)
    {
        auto sec_beg = cur_section->VirtualAddress;
        auto sec_end = (sec_beg + cur_section->Misc.VirtualSize);

        if (Rva >= sec_beg && Rva < sec_end)
            return cur_section;
    }

    return reinterpret_cast<PIMAGE_SECTION_HEADER>(nullptr);
}

推荐阅读