kernel32 是否总是从 System32 加载?

Does kernel32 always load from System32?

这似乎与我一直认为的 DLL 的默认行为相矛盾,即首先从本地应用程序目录加载,如果不存在则从 PATH 环境变量加载。但是,对于某些 DLL,如 ntdll 或 kernel32,Windows 似乎总是首先检查 System32。这是预期的行为吗?可以覆盖吗?

(我知道覆盖这将是不好的做法,但想知道这是否真的可能,为了科学!)

经过更多研究,我发现某些 DLL,例如 kernel32.dll 或 user32.dll 无法正常覆盖的原因是因为它们是 已知 DLL - Windows 有一个像这样的常用 DLL 列表,它们自动默认为 System32 版本,而不是首先检查应用程序文件夹的默认行为。

如果您想解决这个问题,例如制作代理 DLL,您需要在应用程序目录中包含两个文件:applicationName.exe.localapplicationName.exe.manifest 其中 applicationName 是您的 EXE 文件的名称。

这些需要是清单文件的内容:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity version="1.0.0.0" name="redirector" type="win32" />
    <file name="kernel32.dll" />
</assembly>

assemblyIdentity 标签旨在提供有关应用程序版本号和名称的信息,但我们基本上可以忽略它。重要的部分是文件标签,它指定要在本地加载的文件。将 kernel32.dll 替换为您要在本地加载的 DLL。

此外,Windows 仅在重启时或修改 EXE 文件时刷新 .manifest 文件的内容,因此您可以在某些十六进制编辑器中打开 EXE 文件,删除第一个字符,然后将其添加回去并保存...等以刷新清单文件。如果您的清单文件似乎被忽略,请执行此操作。

  • 在 Windows 2000 及以下,添加一个 .local 文件就足够了 说服它加载本地版本的 kernel32.dll .
  • 在 Windows XP 及更高版本上,您需要使用 .manifest 文件。
  • 应用程序中可以嵌入 .manifest 文件 它。在这种情况下,您可以使用 Stud_PE.
  • 等工具删除资源

Windows 中的 KnownDLLs 功能应该有助于更快地加载常见的 DLL,但它也会强制列表中的所有 DLL 从 system32 加载。

除此之外,kernel32.dll 和 ntdll.dll 在 Windows 的大多数版本中都得到了特殊处理,并且在 CreateProcess 中提前加载,因为用户模式进程的真正入口点是在其中一个模块中。

您可以使用 .local 和清单重定向来覆盖其中的一些。