简体   繁体   English

如何防止特定DLL加载到我的进程中

[英]How to prevent a specific DLL from loading into my process

I think I have researched this pretty thoroughly and I have not found an acceptable answer. 我想我已经对此进行了彻底的研究,但我没有找到可接受的答案。 First the broad strokes: Windows 8.1, Visual Studio 2013. Although, I don't think these are important. 首先是广泛的笔触:Windows 8.1,Visual Studio 2013.虽然,我认为这些并不重要。

Problem as follows. 问题如下。 The application I am writing makes use of A.dll. 我正在编写的应用程序使用A.dll。 We use a third-party vendor product (a backup program, but again this is not important) that has installed a Context Menu Handler control under HKEY_CLASSES_ROOT\\Directory\\shellex\\ContextMenuHandlers. 我们使用在HKEY_CLASSES_ROOT \\ Directory \\ shellex \\ ContextMenuHandlers下安装了Context Menu Handler控件的第三方供应商产品(备份程序,但这并不重要)。 Let's say the path to this is c:\\Program Files\\Vendor\\control.dll. 假设这个路径是c:\\ Program Files \\ Vendor \\ control.dll。

Now, the issue is that when my program opens a file chooser dialog (it's a Qt program that uses QFileDialog which then uses the standard Windows one), this control is loaded to provide context-sensitive right-click functionality. 现在,问题是当我的程序打开一个文件选择器对话框(它是一个使用QFileDialog然后使用标准Windows的Qt程序)时,加载此控件以提供上下文相关的右键单击功能。 This control depends on a different version of "A.dll" and when control.dll is loaded, my program promptly crashes. 此控件取决于“A.dll”的不同版本,并且当加载control.dll时,我的程序会立即崩溃。

I don't need this extra functionality. 我不需要这个额外的功能。 What I would love to do is to prevent this specific dll (control.dll) from loading in my process. 我想做的是防止在我的进程中加载​​这个特定的dll(control.dll)。 In an object-oriented world I would simply overload LoadLibrary(), check for this specific DLL, and then call the standard one otherwise. 在面向对象的世界中,我只是重载LoadLibrary(),检查这个特定的DLL,然后调用标准的DLL。 However this doesn't seem feasible. 然而,这似乎不可行。

Is there an easy way to do this? 是否有捷径可寻?

Thanks! 谢谢! Dan

In this situation, you are launching a standard Windows Open File dialog that internally hosts Windows Explorer as part of its UI, and Explorer loads Shell Extension DLLs. 在这种情况下,您将启动一个标准的Windows Open File对话框,该对话框在内部托管Windows资源管理器作为其UI的一部分,并且Explorer加载Shell扩展DLL。 To prevent that, you have to either: 为了防止这种情况,您必须:

  1. call the GetOpenFileName() API directly, opting to use the old-style dialog instead of the newer explorer-style dialog by omitting the OFN_EXPLORER flag (the newer IFileOpenDialog API does not support this option). 直接调用GetOpenFileName() API,通过省略OFN_EXPLORER标志(较新的IFileOpenDialog API不支持此选项)选择使用旧式对话框而不是较新的资源管理器样式对话框。 The older-style dialog does not support Shell Extensions (but it also has an outdated look-and-feel). 旧式对话框不支持Shell Extensions(但它也具有过时的外观)。

  2. don't use the standard Open File dialog at all. 根本不要使用标准的“打开文件”对话框。 Make you own instead. 让你自己。

Another option is to let Explorer do its job normally, but create and register your own shim DLL as a replacement for the offending Shell Extension. 另一种选择是让Explorer正常工作,但创建并注册自己的填充程序DLL,以替代违规的Shell扩展。 Have the shim check if the calling process is explorer.exe . 让垫片检查调用进程是否为explorer.exe If so, load and delegate all actions to the original Extension, otherwise do nothing. 如果是,请加载并将所有操作委托给原始扩展,否则不执行任何操作。 See How To Disable Shell Extension In FileOpen Dialog . 请参见如何在FileOpen对话框中禁用Shell扩展

Another option might be to create a side-by-side assembly manifest for the offending Shell Extension, and have that manifest explicitly state which DLL to load, so the Extension loads its own version of the DLL and not the version your app is using. 另一个选项可能是为违规的Shell扩展创建一个并排的程序集清单,并让该清单明确说明要加载哪个DLL,因此Extension加载其自己的DLL版本而不是您的应用程序使用的版本。

To prevent the vendor.dll from loading you can use a hook on the following Win32API function LoadLibrary and LoadLibraryEx which are responsible for dynamically loading DLLs and which are also used to load shell extensions. 为了防止vendor.dll被加载,你可以在下面的Win32API函数LoadLibraryLoadLibraryEx上使用一个钩子,它负责动态加载DLL,并且还用于加载shell扩展。 The hook is really assembler code at the code site of the LoadLibrary function, which redirects (jumps) to a function defined by yourself. 钩子实际上是LoadLibrary函数代码站点的汇编代码,它将(跳转)重定向到您自己定义的函数。 In this function you can then intercept any call to vendor.dll being loaded and just return 0, which indicates that the library could not be loaded. 在此函数中,您可以拦截对正在加载的vendor.dll的任何调用,并返回0,这表示无法加载库。

Some example code how to go about it using MinHook library : 一些示例代码如何使用MinHook库进行处理

HMODULE WINAPI LoadLibraryA_check(_In_ LPCTSTR lpFileName)
{
  if (isInWhiteList(lpFileName))
    return loadLibraryA_Original(lpFileName);
  else 
  {
    // Pretend that the module was not found by returning
    // 126 (0x7E): "The specified module could not be found."
    SetLastError(ERROR_MOD_NOT_FOUND);         
    return NULL;
  }
}

bool installWhitelistFilter()
{
  // Initialize MinHook.
  if (MH_Initialize() != MH_OK)
    return false;

  if (MH_CreateHook(&LoadLibraryA, &LoadLibraryA_check, 
      reinterpret_cast<LPVOID*>(&loadLibraryA_Original)) != MH_OK)
    return false;

  if (MH_EnableHook(&LoadLibraryA) != MH_OK)
    return false;

  // same for LoadLibraryW, LoadLibraryExW, LoadLibraryExA

  return true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM