为什么调试器有时不显示整个调用堆栈?

逆向工程 视窗 ollydbg 调用栈
2021-06-11 21:24:04

有一些我不明白的地方。为什么调试器有时只显示调用堆栈的一部分?我试过的是 WinDbg 和 OllyDbg。

让我解释一下我的意思。考虑这个例子:

我启动了一个应用程序,当出现一个对话框时,我将 OllyDbg 附加到应用程序并停下来查看调用堆栈。但是,我看到了这一点:

调用栈

如您所见,这是应用程序主线程的调用堆栈。不幸的是,所呈现的调用堆栈似乎停止ntdll并没有继续显示可执行文件中的函数。因为这是主线程,main()绝对没有返回,否则进程会终止。

当我尝试使用WinDbg中,类似的事情发生,我作为显示在这里

为什么会发生这种情况,我如何找到完整的调用堆栈?

1个回答

Olly 和 WinDbg 通过使用函数签名和调用约定解析实际堆栈来生成“调用堆栈”。当反汇编器没有签名时(例如,当开发人员没有公开函数签名时),它只能根据推送和弹出指令(薄冰)进行有根据的猜测。

问题是,您实际上需要这些信息来正确计算堆栈帧的大小。没有这些信息,你就无法判断堆栈上是否有数据,或者它是否是下一个函数的返回地址。

您可以通过自己跟踪调用而不依赖实际堆栈来克服这些问题,自己维护调用堆栈。在这种情况下,实施通常会限制跟踪列表的深度。

遗憾的是,我不能告诉你它是如何在 OllyDbg 中准确实现的。如果您考虑使用更现代的调试器,您可能会接触到能够帮助您解决此问题的活跃开发人员。

例如,这是x64dbg 中调用堆栈的当前状态

当调用堆栈视图的上下文菜单中的显示可疑调用堆栈框架选项处于活动状态时,它将在整个堆栈中搜索可能的返回地址。当它处于非活动状态时,它将使用标准的堆栈遍历算法来获取调用堆栈。当显示可疑调用堆栈帧选项处于活动状态时,它通常会获得更多结果,但其中一些可能不是实际的调用堆栈帧。