如何在Visual Studio中为DLL设置断点?

6
我正在研究一款用C++编写的DLL源代码,它是另一个程序的插件。由于没有文档,而且我也没有主程序的源代码,所以我正试图找出主程序何时、在哪里调用该DLL。有100多个函数被标记为“DllExport”,但这并没有什么帮助。
因此,如果能够在我的DLL中每次执行达到某段代码时触发断点,或者在某处记录下来,那就太好了。这是否可行?如何实现呢?
1个回答

6

哇,您的要求真是不小。但说实话,这可能对其他场景也非常有用。

我认为最简单的方法是使用WinDbg并在其中设置断点。使用WinDbg,您可以这样做(假设您的映像文件名为myplugin.dll):

  1. 打开WinDbg
  2. 文件 -> 符号文件路径(添加插件的.pdb所在路径)
  3. 文件 -> 源文件路径(添加插件源代码所在路径)
  4. 文件 -> 映像文件路径(添加插件DLL本身所在路径)
  5. 文件 -> 打开可执行文件(或附加到现有进程,选择主应用程序)
  6. 在命令行中输入:bm myplugin!*
  7. 运行程序(F5)

第6步将在myplugin.dll中的每个符号处添加一个断点。但请注意:这确实会在每个函数处添加断点,甚至包括您没有自己定义但通过头文件(如STL)包含的函数。这是在模块中设置断点的最激进方式。如果插件以所有导出函数都位于命名空间或具有前缀的方式编程,则可以缩小搜索模式并获得更准确的断点。假设您感兴趣的所有这些函数都以PLG_为前缀,那么您将编写:

bm myplugin!PLG_*

要想让每个断点都设置得恰当,这很简单。当然,缺点是你必须使用外部调试器。Visual Studio支持“函数断点”,它们的工作方式类似,但据我所知,在某些情况下它们不能很好地与通配符配合使用,或者在VS2013+中已经改变了。这是我知道的最简单的方法(不是没有其他方法,而是我不知道)。第二种最容易的方法:手动添加断点,并保存.suo文件以便以后需要断点时使用。这是一项繁琐的任务,但寻找更快的解决方案可能比手动完成更加耗时(计算一个工作日)。其他方法是编写一个程序,在导出函数的开头添加一个跳板(读取PE头并获取函数的RVA),其中包含int 3和原始指令,但这是过度的——在手动放置1000个断点之前,您可以轻松地手动完成此操作。另一种方法是修改.suo解决方案选项文件,其中存储了断点。但是,根据我的了解,这些仅通过Visual Studio的可扩展性API提供,这意味着您必须为Visual Studio本身编写插件或宏。我也对此非常感兴趣。因此,我会观察这个问题一段时间,也许有人知道更简单的解决方案。如果您是WinDbg的新手,请添加评论,我会尝试解释如何获取它以及它的工作原理 :)

我刚刚发现了dumpbin实用程序。通过它,我可以看到DLL有2432个导出函数。我怀疑它们并不全部被调用,但是没有办法确定... - Vilx-
我听说过 WinDbg,也许可以找到并下载它,但是我对汇编和 CPU 的内部工作经验很少。我发现这个主题很有趣,在学习的过程中也学到了一些东西,但还不足以阅读和理解汇编代码。 :( - Vilx-
以下是可能的攻击向量:所有导出函数都是通过在声明中添加“DllExport”来导出的,该声明先前为“#define DllExport __declspec(dllexport)” 。这意味着我可以更改该#define并以某种方式影响所有导出函数...但我不知道是否有任何有用的操作。 - Vilx-
@Vilx- 然后你只需在每个函数的开头编写 __asm int 3; 即可 ;) 这将触发一个断点(应该会弹出一个窗口,您可以在其中选择调试器,它应该是“Visual Studio 20XX”)。但这样做与在每个函数中手动设置断点完全相同,如果没有自动化,那将是耗时的。虽然我没有AspectC++的经验,但看了几个例子后,在与所述 __asm 指令结合使用时,可能非常可行... - PuerNoctis
好的观点! :) 这就是 - 有了导出函数列表,我认为我可以自动化它。我不是完全确定,因为名称被大量修饰,但到目前为止似乎是可行的... 哦,是的,我想我忘了提到 - 我认为所有导出函数都是C++类成员(我还没有注意到任何普通函数)。 :P 而且它们的名称没有很好的模式。 :( - Vilx-
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接