我可以从另一个进程卸载DLL吗?的(Win32)

时间:2012-01-12 09:02:31

标签: winapi dll

我想从另一个进程卸载DLL。可能吗? 如果是的话,怎么做? (我正在使用Win32 API)

非常感谢你。

4 个答案:

答案 0 :(得分:7)

是的,这是可能的。它被称为DLL弹出,并且是一些DLL注入器的特征。通常加载DLL的方式是LoadLibrary,然后通过FreeLibrary卸载。 FreeLibrary只接受一个参数,该参数是要卸载的模块的句柄。如果你首先注入了DLL,你应该能够很容易地找到它。否则有一些方法可以通过CreateToolHelp32Snapshot / Module32First进一步枚举来获取Module32Next等句柄。假设您已通过某种方式获得句柄,那么弹出DLL的步骤很简单:

  • 使用FreeLibrary获取GetProcAddress的地址。由于Windows的工作方式,此地址将与目标中相同功能的地址匹配。
  • 在目标流程上调用CreateRemoteThread,将lpStartAddress指定为FreeLibrary的地址,并将lpParameter指定为模块的句柄

DLL弹出有几点需要注意。

  • 你应该只弹出一个你确定以后没有代码会再次使用的DLL。如果任何动态链接的代码在释放后尝试调用您的代码,则很可能会触发某种形式的页面访问冲突。
  • 在出于类似原因执行弹出时,应确保DLL内的代码中没有执行任何线程。

应使用常规避免DLL弹出。如果库希望可以选择被释放,它应该提供一些用户可以访问它的接口,最终通过该接口调用FreeLibraryAndExitThread

如果你需要一个代码示例,我已经写了一个顶出器作为我过去在C中写的一个注入器的一部分。我可以搜索它并找到它但是它来自很多年前并且代码质量不是可能是好的。

答案 1 :(得分:3)

你不想这样做。

“加载”DLL不仅仅是打开(和锁定)文件。当NT加载程序启动可执行文件时,它会处理图像引用的所有DLL(递归)并连接函数调用(递归):加载DLL,调用DLL初始化代码等。

卸载DLL意味着您需要停止加载DLL的所有进程,加载新的DLL,并执行NT加载器的所有操作。当然,卸载和重新加载DLL需要恢复旧DLL的状态(初始化变量等),这是Win32中未指定的操作。

有关背景信息,请参阅此article on MSDN和此Under the Hood article in MSJ

答案 2 :(得分:3)

简短回答:不,这是不可能的。

Win32不提供卸载另一个进程的DLL的API。如果库意外释放,则进程将崩溃。这导致严重的安全漏洞,因为它破坏了过程保护机制。

如果您可以修改这两个进程,则可以修改应用程序并添加例程以释放库,并让其他应用程序发送消息。

答案 3 :(得分:0)

我希望在进程尝试调用该dll中的函数时更改调用的函数。我知道这可能是理论上的

这将意味着一些内存黑客攻击,并知道存储函数指针的位置,但所有这些都可以很容易地找到(ollydbg设法做到了),如果他们使用序数会更难,甚至更难如果他们硬编码指针,但现在没有人这样做。然后,您可以注入自己的代码(理想情况下)模仿它们掩盖的函数,但实际上并没有做任何事情。它们可能必须被注入到流程中,这样您就可以在没有流程知道的情况下使其工作,并且不会发生任何崩溃。