是' System.Reflection.Assembly.LoadFrom'修改本机DLL搜索顺序?

时间:2018-06-12 13:47:01

标签: c# .net winapi loadlibrary

我有以下情况:

base\C_sharp.exe -> base\sub\CPPCLI.dll -> base\sub\CPPnative.dll

我有一个C#可执行文件,通过静态链接到CPPnative.dll的{​​{3}}加载C ++ / CLI(.NET)dll。

现在,Windows上的System.Reflection.Assembly.LoadFrom是:

  1. 加载应用程序的目录
  2. 系统目录。使用GetSystemDirectory函数获取此目录的路径。
  3. 16位系统目录。 (...)
  4. Windows目录。 (...)
  5. 当前目录。
  6. PATH环境变量中列出的目录。
  7. 显然,如果我打电话

    System.Reflection.Assembly.LoadFrom("D:\....\base\sub\cppcli.dll");
    

    将找到.NET程序集,但接下来发生的是cppnative.dll的传递负载成功!

    1618:3088 @ 1557218328 - LdrLoadDll - ENTER: DLL name: D:\....\base\sub\cppcli.dll DLL path: D:\....\base\sub\;;C:\Windows\system32;...
    ...
    1618:3088 @ 1557218328 - LdrpHandleOneOldFormatImportDescriptor - INFO: DLL "D:\....\base\sub\cppcli.dll" imports "cppnative.dll"
    ...
    1618:3088 @ 1557218328 - LdrpLoadImportModule - ENTER: DLL name: cppnative.dll DLL path: D:\....\base\sub;;C:\Windows\system32;
    

    TL; DR :本机NT加载程序如何突然开始查看sub目录?

    正常LoadLibrary行为表明首先搜索可执行文件目录。

1 个答案:

答案 0 :(得分:0)

最终对{C ++ / CLI程序集进行LOAD_WITH_ALTERED_SEARCH_PATH调用时,.NET框架可能会在内部使用LoadLibrary

至少,我可以在我的调用堆栈中清楚地看到框架 在内部使用LoadLibraryEx将混合模式cppcli.dll加载到进程中。

首先:

>   cppnative1.dll!DllMain(HINSTANCE__ * hModule, unsigned long ul_reason_for_call, void * lpReserved) Line 13  C++ Symbols loaded.
    cppnative1.dll!dllmain_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 199   C++ Symbols loaded.
    ntdll.dll!LdrpRunInitializeRoutines()  Unknown Symbols loaded.
    ntdll.dll!LdrpLoadDll()    Unknown Symbols loaded.
    ntdll.dll!LdrLoadDll() Unknown Symbols loaded.
    KernelBase.dll!LoadLibraryExW()    Unknown Symbols loaded.
    [Managed to Native Transition]      Annotated Frame
    mscorlib.dll!System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(System.Reflection.AssemblyName assemblyRef, System.Security.Policy.Evidence assemblySecurity, System.Reflection.RuntimeAssembly reqAssembly, ref System.Threading.StackCrawlMark stackMark, System.IntPtr pPrivHostBinder, bool throwOnFileNotFound, bool forIntrospection, bool suppressSecurityChecks)    Unknown No symbols loaded.

然后:

>   cppcli.dll!DllMain(HINSTANCE__ * hModule, unsigned long ul_reason_for_call, void * lpReserved) Line 17  C++ Symbols loaded.
    cppcli.dll!dllmain_dispatch(HINSTANCE__ * const instance, const unsigned long reason, void * const reserved) Line 199   C++ Symbols loaded.
    mscoreei.dll!000007fef3ec0e64() Unknown No symbols loaded.
    mscoree.dll!000007fef5fd3281()  Unknown No symbols loaded.
    mscoree.dll!000007fef5fd32cf()  Unknown No symbols loaded.
    ntdll.dll!LdrpRunInitializeRoutines()  Unknown Symbols loaded.
    ntdll.dll!LdrpLoadDll()    Unknown Symbols loaded.
    ntdll.dll!LdrLoadDll() Unknown Symbols loaded.
    KernelBase.dll!LoadLibraryExW()    Unknown Symbols loaded.
    [Managed to Native Transition]      Annotated Frame
    mscorlib.dll!System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(System.Reflection.AssemblyName assemblyRef, System.Security.Policy.Evidence assemblySecurity, System.Reflection.RuntimeAssembly reqAssembly, ref System.Threading.StackCrawlMark stackMark, System.IntPtr pPrivHostBinder, bool throwOnFileNotFound, bool forIntrospection, bool suppressSecurityChecks)    Unknown No symbols loaded.

我还可以观察到,在此LoadLibraryEx调用期间解析传递(本机)模块依赖项时,不再搜索可执行路径

也就是说,所有传递(本机)依赖项必须驻留在LoadFrom调用的目录中,而不是在应用程序目录中。

(顺便说一句,CWD"。" 搜索,因此也会增加混淆。)