kernel32是否总是从System32加载?

  • 从System32(或SysWOW64,如果您正在testing一个32位应用程序)复制kernel32.dll到包含您的EXE文件的目录
  • 运行EXE文件
  • 进程监视器显示它甚至不打扰先检查kernel32.dll的本地文件夹

这似乎与我一直认为是DLL的默认行为相矛盾,那就是先从本地应用程序目录加载,如果没有从PATH环境variables加载。 但是,对于像ntdll或kernel32这样的DLL,Windows似乎总是首先检查System32。 这是预期的行为? 可以被覆盖吗?

(我意识到,压倒性的这将是不好的做法,但是想知道这是否真的有可能,为了科学!)

Windows中的KnownDLLs功能可以帮助加载常见DLL,但也会强制列表中的所有DLL从system32加载。

最重要的是,kernel32.dll和ntdll.dll在大多数Windows版本中都有特殊的处理,并且在CreateProcess的早期加载,因为usermode进程的实际入口点位于其中一个模块中。

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

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

如果你想要解决这个问题,比如做一个代理DLL,你需要在application目录中包含两个文件: 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只刷新.manifest文件的内容重新启动时,或者当EXE文件被修改,所以你可以在一些十六进制编辑器中打开EXE文件,删除第一个字符,并将其添加回来,并保存…等。刷新清单文件。 如果你清单文件似乎被忽略,这样做。

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