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

时间:2015-09-24 20:57:41

标签: c++ qt winapi dll loadlibrary

我想我已经对此进行了彻底的研究,但我没有找到可接受的答案。首先是广泛的描述:Windows 8.1,Visual Studio 2013.虽然,我不认为这些很重要。

问题如下。我正在编写的应用程序使用A.dll。我们使用在HKEY_CLASSES_ROOT \ Directory \ shellex \ ContextMenuHandlers下安装了Context Menu Handler控件的第三方供应商产品(备份程序,但这并不重要)。让我们说这个路径是c:\ Program Files \ Vendor \ control.dll。

现在,问题在于当我的程序打开一个文件选择器对话框(它是一个使用QFileDialog然后使用标准Windows的Qt程序)时,会加载此控件以提供上下文相关的右键单击功能。这种控制取决于不同版本的" A.dll"当加载control.dll时,我的程序会立即崩溃。

我不需要这个额外的功能。我想做的是防止在我的进程中加载​​这个特定的dll(control.dll)。在面向对象的世界中,我只是重载LoadLibrary(),检查这个特定的DLL,然后调用标准的DLL。然而,这似乎不可行。

有一种简单的方法吗?

谢谢! 丹

2 个答案:

答案 0 :(得分:3)

在这种情况下,您将启动一个标准的Windows Open File对话框,该对话框在内部托管Windows资源管理器作为其UI的一部分,并且Explorer加载Shell扩展DLL。为了防止这种情况,您必须:

  1. 直接调用GetOpenFileName() API,省略OFN_EXPLORER标记(较新的IFileOpenDialog API,选择使用旧式对话框而不是较新的资源管理器样式对话框不支持此选项)。旧式对话框不支持Shell Extensions(但它也有过时的外观)。

  2. 根本不使用标准的“打开文件”对话框。让你自己。

  3. 另一个选择是让资源管理器正常工作,但创建并注册自己的填充程序DLL,以替代违规的Shell扩展。让垫片检查调用过程是否为explorer.exe。如果是,请加载并将所有操作委托给原始扩展,否则不执行任何操作。看到 How To Disable Shell Extension In FileOpen Dialog

    另一个选项可能是为违规的Shell扩展创建一个并排的程序集清单,并让该清单明确说明要加载哪个DLL,因此扩展加载自己的DLL版本而不是你的应用程序的版本正在使用。

答案 1 :(得分:3)

为防止加载vendor.dll,您可以在以下Win32API函数LoadLibraryLoadLibraryEx上使用挂钩,它们负责动态加载DLL,并且还用于加载shell扩展。钩子实际上是LoadLibrary函数代码站点的汇编代码,它将(跳转)重定向到您自己定义的函数。在此函数中,您可以拦截对正在加载的vendor.dll的任何调用,并返回0,这表示无法加载库。

一些示例代码如何使用MinHook library进行处理:

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;
}