c++ - Windows API SysWOW 重定向意外行为

标签 c++ windows winapi syswow64

我有一个旧的 32 位安装程序,它将一些 32 位依赖项 DLL 安装到 Windows 系统文件夹中。我发现在 64 位系统上安装某些 32 位 DLL 失败,因为 SysWOW 重定向正在执行一些我不理解的操作。

安装程序依赖 Windows API 函数 GetFileVersionInfo 来指示 DLL 是否已存在且具有较新的版本号。但是,我现在看到文件 MSVCR100.DLL 已存在于 System32 文件夹中,但不存在于 SysWOW64 文件夹中。当使用 GetFileVersionInfo 测试 C:\Windows\System32\MSVCR100.DLL 时,我希望它重定向到 C:\Windows\SysWOW64\MSVCR100.DLL。似乎如果 SysWOW64 中不存在该文件,那么它会在 System32 中查找作为后备。因此,安装程序认为 MSVCR100.DLL 已经存在并且无法安装它。

我创建了一个 C++ Win32 控制台应用程序来测试这一点。全部代码为:

int _tmain(int argc, _TCHAR* argv[])
{
    char sysDirName[64], sysWow64DirName[64];
    char fileName[256];

    strcpy_s(fileName, argv[1]);
    GetSystemDirectory((LPSTR)sysDirName, 256);
    GetSystemWow64Directory((LPSTR)sysWow64DirName, 256);

    test_file(sysDirName, fileName);
    test_file(sysWow64DirName, fileName);

    return 0;
}

void test_file(char *dir, char* fileName)
{
    char filePath[256];
    DWORD verInfoSize, tempDWORD;
    BOOL found;
    byte buff[8192];

    PathCombine((LPSTR)filePath, (LPSTR)dir, (LPSTR)fileName);
    verInfoSize = GetFileVersionInfoSize((LPSTR)filePath, &tempDWORD);
    found = GetFileVersionInfo((LPSTR)filePath, 0, verInfoSize, buff);
    if (found)
        printf("%s   --found\n", filePath);
    else
        printf("%s   --NOT found\n", filePath);
}

我在 3 台不同的 64 位计算机上进行了测试,包括 Win 10、Win 7,得到了相同的结果。

如果 MSVCR100.DLL 在 SysWOW64 中但不在 System32 中,那么我的测试显示重定向按预期工作:

>testSysFile msvcr100.dll
C:\WINDOWS\system32\msvcr100.dll   --found
C:\WINDOWS\SysWOW64\msvcr100.dll   --found

如果 MSVCR100.DLL 既不在 System32 也不在 SysWOW64 中,则结果是预期的:

>testSysFile msvcr100.dll
C:\WINDOWS\system32\msvcr100.dll   --NOT found
C:\WINDOWS\SysWOW64\msvcr100.dll   --NOT found

如果 MSVCR100.DLL 在 System32 中,但不在 SysWOW64 中,则结果会显示一些意外且无用的内容:

>testSysFile msvcr100.dll
C:\WINDOWS\system32\msvcr100.dll   --found
C:\WINDOWS\SysWOW64\msvcr100.dll   --NOT found

网络搜索向我展示了许多有关 SysWOW 重定向的信息,但我找不到任何有关此行为的文档或讨论。这真的是我应该期待的吗?我的测试还表明,如果我使用 API 函数 GetSystemWow64Directory,我可以获得不依赖重定向的文件路径。仅复制 DLL 并将它们注册到该路径是否安全?

最佳答案

GetFileVersionInfo* 使用 LoadLibraryEx 通过将文件加载为数据文件来完成其工作。

出于某种原因,LoadLibraryW 内的 KERNELBASE!BasepLoadLibraryAsDataFile 调用 ntdll!RtlWow64EnableFsRedirectionEx 来禁用重定向,并且如果请求的文件位于“%WinDir”内%\System32"然后它尝试再次加载该文件,这次是从“真实的”system32 目录。

这显然是设计使然,我想不出一种不是巨大的黑客攻击的方法。我认为他们这样做是出于兼容性原因。

但是,您可以通过以下方式检测它:

bool validFile = !(GetFileAttributes(filePath) & FILE_ATTRIBUTE_DIRECTORY);
bool falsePositive = gotversioninfo && !validFile;

关于c++ - Windows API SysWOW 重定向意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48218694/

相关文章:

c++ - 在 win32 用户态代码中 Hook OpenProcess() 或 ReadVirtualMemory()

c++ - 访问读取冲突C++任务计划程序

c++ - isFollowingCamelCaseConventionInCPlusPlus more_import_than_readability?

C++ getenv() 包装函数未设置值

sql-server - SQL Server 2012 开发人员版 - 安装失败

windows - 注定的技术?

windows - 我在哪里可以获得我的通用应用程序的客户端密码?

c++ - 使 C++ 对象数组在 Python 中可迭代

winapi - 如何在golang中从windows `syscall`加载图片资源?

c - 为什么我的所有者数据 ListView 状态图像在 Windows XP 上显示为空白?