将DLL固定在内存中(增加引用计数)

Tho*_*ler 3 debugging dll memory-leaks windbg access-violation

我正在尝试运行应用程序,但应用程序因访问冲突而退出.在调试器中运行应用程序我可以看到这是由卸载的库引起的.我等不及应用程序的下一个版本了,所以我正在尝试解决这个问题.

我想知道WinDbg是否提供了一种增加加载模块的引用计数的方法,类似于C++ LoadLibrary()调用.然后我可以打破模块加载并增加受影响的DLL上的引用计数,看看我是否可以使用该应用程序.

我已经看过开始的命令.load,!load,.lock,!lock,.mod!mod在WinDbg的帮助..load会将DLL作为扩展加载到调试器进程中,而不是加载到目标进程中.

更新

忘记提到我没有源代码,所以我不能简单地实现LoadLibrary()调用作为变通方法并重新编译.

Hans Passant的评论引导我去.call尝试使用它

.call /v kernel32!LoadLibraryA("....dll")
Run Code Online (Sandbox Code Playgroud)

但它给出了错误信息

符号不是'.call/v kernel32!LoadLibraryA(".... dll")'中的函数

更新2

可能是文件名的字符串.call应该是指向目标进程中某些内存的指针,而不是驻留在我输入命令的WinDbg.exe中的字符串.这又意味着我可能意味着分配一些内存来存储字符串,所以这可能会变得更复杂.

Sea*_*ine 7

.call在windbg中使用对我来说一直很挑剔.我相信你遇到了麻烦,因为kernel32只有公共符号,所以调试器不知道它的参数是什么样的.

那么让我们来看看一些替代方案......

简单的方法

您可以使用Process Hacker之类的工具,我认为这是任何调试器工具箱的一个很好的补充.它可以选择将DLL注入进程.

进程黑客注入DLL

在幕后,它调用CreateRemoteThread在目标进程中生成一个线程,该线程调用LoadLibrary所选的DLL.运气好的话,这会增加模块引用次数.您可以LoadCount通过!dlls在dll注入之前和之后运行命令来验证windbg中的增加.

艰难的方式

您还可以深入了解Windows用于跟踪进程加载的模块并使用的内部数据结构LoadCount.这在Windows版本之间发生了变化,这是一个严重的禁忌.但是,我们正在调试,所以,到底是什么?我们开工吧.

首先获取已加载模块的列表!dlls.假设我们关心your.dll; 我们可能会看到类似于:

0x002772a8: C:\path\to\your.dll
      Base   0x06b80000  EntryPoint  0x06b81000  Size        0x000cb000    DdagNode     0x002b3a10
      Flags  0x800822cc  TlsIndex    0x00000000  LoadCount   0x00000001    NodeRefCount 0x00000001
Run Code Online (Sandbox Code Playgroud)

我们可以看到当前的加载计数为1.要修改它,我们可以使用模块路径之前打印的地址.它是该ntdll!_LDR_DATA_TABLE_ENTRY模块的过程地址.

r? @$t0 = (ntdll!_LDR_DATA_TABLE_ENTRY*) 0x002772a8
Run Code Online (Sandbox Code Playgroud)

而且,现在您可以将LoadCount成员更改为更大的成员:

?? @$t0->LoadCount = 2
Run Code Online (Sandbox Code Playgroud)

但是,正如我所说,这些东西随着Windows的新版本而变化.在Windows 8上,该LoadCount成员已移出_LDR_DATA_TABLE_ENTRYntdll!_LDR_DDAG_NODE结构.取而代之的是,现在有一个ObsoleteNodeCount不是我们想要的东西.

在Windows 8上,我们将运行以下命令:

?? @$t0->DdagNode->LoadCount = 2
Run Code Online (Sandbox Code Playgroud)

并且,是时候检查我们的工作......

0x002772a8: C:\path\to\your.dll
      Base   0x06b80000  EntryPoint  0x06b81000  Size        0x000cb000    DdagNode     0x002b3a10
      Flags  0x800822cc  TlsIndex    0x00000000  LoadCount   0x00000002    NodeRefCount 0x00000001
Run Code Online (Sandbox Code Playgroud)

真棒.现在是2.FreeLibrary在我们说它之前,这将教授关于卸载我们的DLL的教训.

外卖

首先尝试简单的方法.如果这不起作用,您可以开始查看Windows用于跟踪此类内容的内部数据结构.我没有提供希望你真正尝试它的艰难方法,但是它可能会让你!dlls在将来的命令和数据结构方面更加舒适.

尽管如此,所有修改LoadCount意味着你都会确认你看到DLL在它应该被卸载之前就已经卸载了.如果问题在人工增加之后消失LoadCount,意味着你已经确认了你的理论,那么你将不得不采取不同的方法来调试它 - 弄清楚何时以及为什么它被卸载.