从完整的内存转储中查看托管堆栈

Posted

技术标签:

【中文标题】从完整的内存转储中查看托管堆栈【英文标题】:View managed stack from a full memory dump 【发布时间】:2019-01-19 10:24:20 【问题描述】:

怀疑我的托管进程导致客户端站点出现蓝屏死机。我收到了完整的内存转储(即:包括内核,仅物理页面)-但仍然无法检查我的进程堆栈。

切换到我的进程上下文后 -

.process /p /r <MyProcAddress>

我只看到-

1: kd> k
 # ChildEBP RetAddr  
00 b56e3b70 81f2aa5d nt!KeBugCheckEx+0x1e
01 b56e3b94 81e7b68d nt!PspCatchCriticalBreak+0x71
02 b56e3bc4 81e6dfd1 nt!PspTerminateAllThreads+0x2d
03 b56e3bf8 8d48159a nt!NtTerminateProcess+0xcd
WARNING: Stack unwind information not available. Following frames may be wrong.
04 b56e3c24 81c845e4 klif+0x7559a
05 b56e3c24 77da6bb4 nt!KiSystemServicePostCall
06 0262f34c 00220065 ntdll!KiFastSystemCallRet
07 0262f390 003e0022 0x220065
08 0262f394 0073003c 0x3e0022
09 0262f398 00730079 0x73003c
0a 0262f39c 006e003a 0x730079
0b 0262f3a0 006d0061 0x6e003a
0c 0262f3a4 00200065 0x6d0061
0d 0262f3a8 00610076 0x200065
0e 0262f3ac 0075006c 0x610076
0f 0262f3b0 003d0065 0x75006c
10 0262f3b4 00770022 0x3d0065
11 0262f3b8 006e0069 0x770022
12 0262f3bc 006f0077 0x6e0069
13 0262f3c0 00640072 0x6f0077
14 0262f3c4 00200022 0x640072

...

这对于托管进程来说是很自然的。 SOS 扩展不适用于内核转储。

我可以做些什么来查看抛出的托管堆栈吗? previously said 是“更加困难”,但希望并非不可能。


PS。 我知道堆栈中存在卡巴斯基驱动程序 kilf.sys,这是我个人的怀疑。但这个问题更笼统——希望有一种方法可以了解我的流程当时在做什么。

【问题讨论】:

要覆盖的堆栈序列 0x22 0x00 0x65 0x00 等看起来不像地址,但一个 unicode 字符串 65 对应于 e 22 对应于“双引号转储像 db esp 这样的地址,看看你是否能找到线索 可能先检查蓝屏的原因,然后检查你的客户端进程是否触发了它。 @ThomasWeller 当然,我正在调查我的客户端进程以尝试了解 BSOD。 因果关系似乎不对。为什么您如此确定您的进程参与了蓝屏死机?应用程序通常无法做到这一点。它们在用户模式下运行。只有内核模式的东西会导致蓝屏。 @ThomasWeller 遗憾的是,我的应用程序确实需要摆弄 csrss 挂钩。 【参考方案1】:

您发布的堆栈不正确 它似乎被覆盖或者是其他一些人工制品的结果 有了这样的堆栈详细信息,您将很难破译 任何有用的东西

堆栈的内容转换为英文的可打印范围看起来像这样

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000  00 3E 00 22 00 22 00 65 00 73 00 3C 00 3E 00 22  .>.".".e.s.<.>."
00000010  00 73 00 79 00 73 00 3C 00 6E 00 3A 00 73 00 79  .s.y.s.<.n.:.s.y
00000020  00 6D 00 61 00 6E 00 3A 00 20 00 65 00 6D 00 61  .m.a.n.:. .e.m.a
00000030  00 61 00 76 00 20 00 65 00 75 00 6C 00 61 00 76  .a.v. .e.u.l.a.v
00000040  00 3D 00 65 00 75 00 6C 00 77 00 22 00 3D 00 65  .=.e.u.l.w.".=.e
00000050  00 6E 00 69 00 77 00 22 00 6F 00 77 00 6E 00 69  .n.i.w.".o.w.n.i
00000060  00 64 00 72 00 6F 00 77 00 20 00 22 00 64 00 72  .d.r.o.w. .".d.r

试试!analyze -v 看看bsod分析结果是什么

【讨论】:

谢谢。 !analyze -v 提供的信息很少(直接症状是 csrss 未处理的异常)。你可能是对的,这不是堆栈 - 但我不认为它已损坏:我相信当调试器抱怨“跟随帧可能是错误的”时,它是非常严重的。这是一台 x86 机器,缺少卡巴斯基驱动程序的符号可能会使堆栈遍历几乎不可能(FPO?)。 更正:这确实不是堆栈,但不是由于 FPO 或损坏。引用这个答案 [***.com/a/1918944/89706] :“KiFastSystemCallRet 意味着线程处于系统调用中 - x86 NT 系统调用调度的一个不幸方面是它不会将上下文返回到原始位置,而是必须返回到静态位置ntdll,它将修复上下文并让你回到你来自的地方。”我想知道我是否应该修正问题标题以反映这种理解......

以上是关于从完整的内存转储中查看托管堆栈的主要内容,如果未能解决你的问题,请参考以下文章

如何使用参数自动从 Azure webapp 获取完整内存转储

从 boost 共享内存中转储数据的最佳方法

如何使用 WinDBG 列出所有托管线程的调用堆栈?

将堆栈和堆内存转储到文件,然后将其加载回 RAM?

多线程程序的核心转储

GDB核心转储具有损坏的堆栈,显示“堆栈帧无法访问地址0x12处的内存”