LoadLibrary指定绝对路径为何加载自身DLL?不同程序行为问询
你遇到的这个问题确实有点绕——明明写死了绝对路径c:\windows\system32\name.dll调用真实DLL,结果在own.exe里反而返回自己的DLL句柄,还报"文件未找到"。结合你给出的细节,咱们从Windows加载机制的几个核心点来拆解:
1. .local文件夹的重定向优先级陷阱
你把自己的name.dll放在own.exe.local里,这触发了Windows的本地DLL重定向机制。按道理绝对路径应该绕过这个规则,但这里可能有例外:
- 虽然你删除了
own.exe的manifest,也确认没有嵌入式清单,但可以再用Resource Hacker这类工具扫一遍进程资源,确保没有残留的重定向配置(比如<loaderRedirect>true</loaderRedirect>)——有些程序的manifest会被打包进资源段,手动删除文件可能没用。 - 还有一种可能是
own.exe依赖的某个系统组件间接开启了重定向,比如它调用的COM组件启用了加载重定向,导致整个进程的加载上下文被修改,让绝对路径的解析也受到影响。
2. 隐式加载导致的同名模块冲突(最可能的原因)
你提到已经在LoadLibrary系列函数上设了断点,但要注意:隐式加载是通过PE导入表完成的,不会触发LoadLibrary断点!
如果own.exe的导入表中本来就有name.dll,那么进程启动时就会自动加载你的name.dll(因为.local文件夹优先级更高)。当你在DLL里调用LoadLibrary("c:\\windows\\system32\\name.dll")时,Windows会先检查进程中是否已经加载了同名模块——这里的"同名"只看模块基名(name.dll),不看路径。如果发现已有同名模块,就直接返回已有的句柄,同时因为你指定的路径和已加载模块的路径不匹配,会返回ERROR_FILE_NOT_FOUND的错误码。
而fine.exe是你自己的程序,要么是显式加载你的DLL,要么导入表里根本没name.dll,所以进程里没有预加载的同名模块,你的LoadLibrary就能正常去System32找真实DLL。
验证这个猜想的方法:
- 用Process Explorer打开
own.exe,查看它的模块列表,看是不是在你调用LoadLibrary之前就已经加载了你的name.dll。 - 在你的DLL的
DllMain里加个日志,记录DLL_PROCESS_ATTACH的触发时机——如果进程一启动就触发了,那肯定是隐式加载。
3. 文件系统虚拟化或权限问题
如果own.exe是安装在Program Files这类受UAC保护的目录下,且没有以管理员身份运行,Windows可能会开启文件系统虚拟化,把对c:\windows\system32的访问重定向到用户的AppData虚拟目录,导致找不到真实的name.dll。可以试试右键以管理员身份运行own.exe,看问题是否消失。
4. 64位进程的路径解析小坑(虽然你已经确认是64位,但还是提一下)
64位进程访问c:\windows\system32不会被重定向到SysWOW64,但如果有第三方工具(比如某些调试器、注入工具)修改了进程的Wow64FsRedirection状态,也可能导致路径解析异常。可以在调用LoadLibrary前临时禁用重定向测试:
PVOID oldValue = NULL; Wow64DisableWow64FsRedirection(&oldValue); driver_library = LoadLibrary(_T("c:\\windows\\system32\\name.dll")); Wow64RevertWow64FsRedirection(oldValue);
解决建议
针对最可能的"隐式加载冲突"问题,推荐这几个方案:
- 用LoadLibraryEx替代LoadLibrary,指定
LOAD_LIBRARY_SEARCH_SYSTEM32标志,强制系统只在System32目录搜索,完全绕过进程的加载上下文和.local重定向:driver_library = LoadLibraryEx(_T("name.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); - 给你自己的DLL改个名字(比如
my_name.dll),然后通过钩子或者manifest重定向让own.exe加载它,从根源上避免同名冲突。 - 如果必须保留原名,可以先调用
GetModuleHandleEx检查进程中是否已加载name.dll,如果存在,考虑用FreeLibrary卸载后再加载真实DLL——但这个操作风险很高,可能导致进程崩溃,不推荐。
内容的提问来源于stack exchange,提问作者Lauriane.C

