2017-03-08 29 views
2

我正在用C#应用程序中的MS Word做一些Office自动化,并且我发现Word有时会挂起。我无法在开发环境中重现挂起,所以我希望能够通过采取核心转储并使用WinDbg进行分析来准确诊断Word挂起的原因。WinDbg:如何从核心转储中获取Word对话框中显示的消息?

如果我跑KB,我得到这个堆栈跟踪(我已经警告后离开的一切,因为它可能是无关紧要的):

ChildEBP RetAddr Args to Child    
003bc94c 762ed846 00037b72 00000008 00000000 user32!NtUserWaitMessage+0x15 
003bc988 762eda5c 00047b12 00037b72 00000008 user32!DialogBox2+0x222 
003bc9b4 762ed98a 59870000 0089aa30 00037b72 user32!InternalDialogBox+0xe5 
003bc9d4 762ed70e 59870000 0089aa30 00037b72 user32!DialogBoxIndirectParamAorW+0x37 
003bc9f4 59acdf5e 59870000 0089aa30 00037b72 user32!DialogBoxIndirectParamW+0x1b 
WARNING: Stack unwind information not available. Following frames may be wrong. 

因此,这似乎表明,字挂,因为它呈现出对话框。 如何获取该对话框的内容?

如果我看看内存地址0089aa30,我看到:

........................3.... 
.M.i.c.r.o.s.o.f.t. .W.o.r.d. 
........T.a.h.o.m.a.......... 
....P#.!.*...........O.K..... 
...........PW.!.*...........& 
.H.e.l.p..................P.. 
............................. 
....P+...r.......M.S.O.U.N.I. 
S.T.A.T...W.o.r.d. .c.a.n.n.o 
.t. .o.p.e.n. .t.h.e. .e.x.i. 
s.t.i.n.g. .f.i.l.e..... .(.N 
.o.r.m.a.l.)[email protected] 
..+.........M.S.O.U.N.I.S.T.A 
.T...2.0.0.5.2.1............. 

所以对我来说这是说对话框中的消息是“Word无法打开现有文件”(正常)。

我在正确的轨道上吗?我在寻找正确的记忆?

有什么方法可以获得消息的确切内存地址吗? (我觉得我有点猜测,因为上面的消息恰好在内存中与DialogBoxIndirectParam的参数紧密相关。)我已经看了一下DialogBoxIndirectParam的MSDN文档,希望弄清楚我应该在内存中的哪个位置希望看到对话的消息,但没有太多。


编辑:看到blabb的(绝对令人难以置信)的答案后,我试图执行的WinDbg相同的步骤为我的MS Word的核心转储。下面是输出:

0:000> ub 762ed98a 
user32!DialogBoxIndirectParamAorW+0x1f: 
762ed972 83c801   or  eax,1 
762ed975 50    push eax 
762ed976 ff7518   push dword ptr [ebp+18h] 
762ed979 ff7514   push dword ptr [ebp+14h] 
762ed97c ff7510   push dword ptr [ebp+10h] 
762ed97f ff750c   push dword ptr [ebp+0Ch] 
762ed982 ff7508   push dword ptr [ebp+8] 
762ed985 e809000000  call user32!InternalDialogBox (762ed993) 
0:000> .frame /r 2 
02 003bc9b4 762ed98a user32!InternalDialogBox+0xe5 
eax=00000000 ebx=00037b72 ecx=00000000 edx=00000000 esi=003bc97c edi=003bc918 
eip=762eda5c esp=003bc990 ebp=003bc9b4 iopl=0   nv up ei pl zr na pe nc 
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b    efl=00000246 
user32!InternalDialogBox+0xe5: 
762eda5c 5f    pop  edi 
0:000> dc /c 1 003bc990 l8 
003bc990 00047b12 .{.. 
003bc994 00037b72 r{.. 
003bc998 00000008 .... 
003bc99c 00000000 .... 
003bc9a0 00000000 .... 
003bc9a4 00037b72 r{.. 
003bc9a8 003bcb98 ..;. 
003bc9ac 00000000 .... 

我知道我在寻找记忆的错误位(即我传递给DC地址不正确),但我不知道为什么。我用“.frame/r 2”来获取esp的地址,我做错了什么?

+1

您可以通过从Andrew Richards下载和使用[pde](https://onedrive.live.com/redir?resid=DAE128BD454CF957!7152&authkey=!AJeSzeiu8SQ7T4w&ithint=folder%2czip)让您的生活更轻松。在Windbg中,将它加载为'.load \ pde.dll'并执行'!dpx'。它会向您展示可以从堆栈中检索的所有字符串。 –

+0

由于您很可能正在寻找正确的方向,因此更容易从sysinternals下载'procmon'。启动它,运行你的代码,停止它并转到'工具 - 统计出现 - 列:结果 - 计数'并过滤错误或访问被拒绝的值。 –

+0

谢谢列文。鉴于缺陷是间歇性的,我认为procmon可能具有挑战性。不知道pde,所以我现在就试试。 – Justin

回答

5

的InternalDialogBox API采用六个参数

C:\>cdb -c ".fnent user32!InternalDialogbox;q" cdb | grep Params 
Params: 0n6 (0x18 bytes) 

你可以尝试解密通过在碰撞堆栈

0:000> kb 1 
# ChildEBP RetAddr Args to Child    
00 0017fad8 778be0d5 77860000 001ec4f0 00000000 USER32!InternalDialogBox 

0:000> ub @$ra 
USER32!SoftModalMessageBox+0x66d: 
778be0b8 e87c48fdff  call USER32!MessageBeep (77892939) 
778be0bd 56    push esi 
778be0be 53    push ebx 
778be0bf 6848d68b77  push offset USER32!MB_DlgProc (778bd648) 
778be0c4 ff75ac   push dword ptr [ebp-54h] 
778be0c7 ff75e4   push dword ptr [ebp-1Ch] 
778be0ca ff35d0908c77 push dword ptr [USER32!hmodUser (778c90d0)] 
778be0d0 e8a059fdff  call USER32!InternalDialogBox (77893a75) 

上的返回地址做一个落后的拆解此调用转储可以替代地址,而不是的登记或你可以 做。帧/ R {帧数}抓取的ESP

0:000> dc /c 1 @esp l8 
0017fadc 778be0d5 ...w 
0017fae0 77860000 ...w 
0017fae4 001ec4f0 .... 
0017fae8 00000000 .... 
0017faec 778bd648 H..w 
0017faf0 0017fcd8 .... 
0017faf4 00000000 .... 
0017faf8 00000001 .... 

1的地址)的第一个参数是hModUser一个全局变量 2)第四个参数是记录 3)第三和第六参数一个DialogProc回调是DLGTEMPLATE阵列随后DLGITEMTEMPLATE结构的NULL

第二个参数consits查看该可变尺寸的阵列

第五个参数的格式的文件是MSGBOXPARAMS结构

样品转储和解密转储为可变尺寸的阵列作为这里如下

0:000> db 1ec4f0 l f8 
001ec4f0 c5 01 c8 80 00 00 00 00-02 00 1a 01 9b 00 a7 00 ................ 
001ec500 3e 00 00 00 00 00 54 00-68 00 69 00 73 00 20 00 >.....T.h.i.s. . 
001ec510 69 00 73 00 20 00 4d 00-79 00 20 00 43 00 61 00 i.s. .M.y. .C.a. 
001ec520 70 00 74 00 69 00 6f 00-6e 00 20 00 46 00 6f 00 p.t.i.o.n. .F.o. 
001ec530 72 00 20 00 32 00 30 00-31 00 35 00 20 00 43 00 r. .2.0.1.5. .C. 
001ec540 6f 00 6d 00 6d 00 75 00-6e 00 69 00 74 00 79 00 o.m.m.u.n.i.t.y. 
001ec550 20 00 76 00 73 00 00 00-ff 7f 00 00 01 00 03 50 .v.s..........P 
001ec560 00 00 00 00 71 00 2a 00-32 00 0e 00 01 00 ff ff ....q.*.2....... 
001ec570 80 00 4f 00 4b 00 00 00-00 00 00 00 80 20 02 50 ..O.K........ .P 
001ec580 00 00 00 00 07 00 0e 00-8c 00 09 00 ff ff ff ff ................ 
001ec590 82 00 54 00 68 00 69 00-73 00 20 00 69 00 73 00 ..T.h.i.s. .i.s. 
001ec5a0 20 00 6d 00 79 00 20 00-66 00 69 00 72 00 73 00 .m.y. .f.i.r.s. 
001ec5b0 74 00 20 00 54 00 65 00-73 00 74 00 20 00 77 00 t. .T.e.s.t. .w. 
001ec5c0 69 00 74 00 68 00 20 00-32 00 30 00 31 00 35 00 i.t.h. .2.0.1.5. 
001ec5d0 20 00 63 00 6f 00 6d 00-6d 00 75 00 6e 00 69 00 .c.o.m.m.u.n.i. 
001ec5e0 74 00 79 00 00 00 00 00       t.y..... 
0:000> dt ConsoleApplication1!DLGTEMPLATE 1ec4f0 
    +0x000 style   : 0x80c801c5 
    +0x004 dwExtendedStyle : 0 
    +0x008 cdit    : 2 
    +0x00a x    : 0x11a 
    +0x00c y    : 0x9b 
    +0x00e cx    : 0xa7 
    +0x010 cy    : 0x3e 
0:000> du 1ec504 
001ec504 "" 
0:000> du 1ec506 
001ec506 "This is My Caption For 2015 Comm" 
001ec546 "unity vs" 
0:000> dt ConsoleApplication1!DLGITEMTEMPLATE 1ec55c 
    +0x000 style   : 0x50030001 
    +0x004 dwExtendedStyle : 0 
    +0x008 x    : 0x71 
    +0x00a y    : 0x2a 
    +0x00c cx    : 0x32 
    +0x00e cy    : 0xe 
    +0x010 id    : 1 
0:000> $$ 80 is a predfined button and the text is OK 
0:000> dt ConsoleApplication1!DLGITEMTEMPLATE 1ec57c 
    +0x000 style   : 0x50022080 
    +0x004 dwExtendedStyle : 0 
    +0x008 x    : 7 
    +0x00a y    : 0xe 
    +0x00c cx    : 0x8c 
    +0x00e cy    : 9 
    +0x010 id    : 0xffff 
0:000> $$ 82 is a predfined static text and the text is 
0:000> du 1ec592 
001ec592 "This is my first Test with 2015 " 
001ec5d2 "community" 

是MSGBOXPARAMSW转储

0:000> dt ConsoleApplication1!MSGBOXPARAMSW 0017fcd8 
    +0x000 cbSize   : 0x28 
    +0x004 hwndOwner  : (null) 
    +0x008 hInstance  : (null) 
    +0x00c lpszText   : 0x01172150 "This is my first Test with 2015 community" 
    +0x010 lpszCaption  : 0x011720f8 "This is My Caption For 2015 Community vs" 
    +0x014 dwStyle   : 0 
    +0x018 lpszIcon   : (null) 
    +0x01c dwContextHelpId : 0 
    +0x020 lpfnMsgBoxCallback : (null) 
    +0x024 dwLanguageId  : 0 

EDIT

从任务管理器创建的转储和加载它

0:000> .shell -ci "version" grep DMP 
Full memory user mini dump: C:\Users\HP\Desktop\cons.DMP 
command line: 'windbg -z cons.DMP' Debugger Process 0x17CC 
.shell: Process exited 

只是要确定重置背景记录

0:000> .cxr 
Resetting default scope 

倾销的利益堆栈跟踪第九条帧不是在顶部位置)的帧数

0:000> kb 5 
# ChildEBP RetAddr Args to Child    
00 0028f6fc 778766c9 7789382a 00000000 00000000 ntdll!KiFastSystemCallRet 
01 0028f700 7789382a 00000000 00000000 00000000 user32!NtUserWaitMessage+0xc 
02 0028f734 77893b27 00aa0350 00000000 00000000 user32!DialogBox2+0x207 
03 0028f758 778be0d5 77860000 002f63f0 00000000 user32!InternalDialogBox+0xcb 
04 0028f7fc 778be659 00000000 69d52104 69d52108 user32!SoftModalMessageBox+0x68a 

压倒一切的地方背景感兴趣

0:000> .frame /c /r 04 
04 0028f7fc 778be659 user32!SoftModalMessageBox+0x68a 
eax=00000001 ebx=0028f958 ecx=0028f458 edx=77ad70f4 esi=005fab18 edi=00000001 
eip=778be0d5 esp=0028f760 ebp=0028f7fc iopl=0   nv up ei pl zr na pe nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000246 
user32!SoftModalMessageBox+0x68a: 
778be0d5 8945e8   mov  dword ptr [ebp-18h],eax ss:0023:0028f7e4=00000000 

checking esp you can use esp as it is instead of groping for address 

0:000> dc /c 1 @esp l 8 
0028f760 77860000 ...w 
0028f764 002f63f0 .c/. 
0028f768 00000000 .... 
0028f76c 778bd648 H..w 
0028f770 0028f958 X.(. 
0028f774 00000000 .... 
0028f778 00000001 .... 
0028f77c 0028f958 X.(. 

倾销DLGTEMPLATE第二ARG

0:000> db 2f63f0 lf8 
002f63f0 c5 01 c8 80 00 00 00 00-02 00 1a 01 9b 00 a7 00 ................ 
002f6400 3e 00 00 00 00 00 54 00-68 00 69 00 73 00 20 00 >.....T.h.i.s. . 
002f6410 69 00 73 00 20 00 4d 00-79 00 20 00 43 00 61 00 i.s. .M.y. .C.a. 
002f6420 70 00 74 00 69 00 6f 00-6e 00 20 00 46 00 6f 00 p.t.i.o.n. .F.o. 
002f6430 72 00 20 00 32 00 30 00-31 00 35 00 20 00 43 00 r. .2.0.1.5. .C. 
002f6440 6f 00 6d 00 6d 00 75 00-6e 00 69 00 74 00 79 00 o.m.m.u.n.i.t.y. 
002f6450 20 00 76 00 73 00 00 00-ff 7f 00 00 01 00 03 50 .v.s..........P 
002f6460 00 00 00 00 71 00 2a 00-32 00 0e 00 01 00 ff ff ....q.*.2....... 
002f6470 80 00 4f 00 4b 00 00 00-00 00 00 00 80 20 02 50 ..O.K........ .P 
002f6480 00 00 00 00 07 00 0e 00-8c 00 09 00 ff ff ff ff ................ 
002f6490 82 00 54 00 68 00 69 00-73 00 20 00 69 00 73 00 ..T.h.i.s. .i.s. 
002f64a0 20 00 6d 00 79 00 20 00-66 00 69 00 72 00 73 00 .m.y. .f.i.r.s. 
002f64b0 74 00 20 00 54 00 65 00-73 00 74 00 20 00 77 00 t. .T.e.s.t. .w. 
002f64c0 69 00 74 00 68 00 20 00-32 00 30 00 31 00 35 00 i.t.h. .2.0.1.5. 
002f64d0 20 00 63 00 6f 00 6d 00-6d 00 75 00 6e 00 69 00 .c.o.m.m.u.n.i. 
002f64e0 74 00 79 00 00 00 00 00       t.y..... 

所属类别(您需要适当的私人PDB或破解装入时将汇编成地址空间中的二进制或从MS添加DLGTEMPLATE结构进入官方PDB为USER32(我以为我有一个解释这个在se的文章,但我似乎无法找到)稍后,如果我找到它或网站搜索谷歌如何添加typeinfo到pdb在网站:病态链接它。COM

0:000> dt cons!DLGTEMPLATE poi(@esp+4) 
    +0x000 style   : 0x80c801c5 
    +0x004 dwExtendedStyle : 0 
    +0x008 cdit    : 2 
    +0x00a x    : 0n282 
    +0x00c y    : 0n155 
    +0x00e cx    : 0n167 
    +0x010 cy    : 0n62 

0:000> du poi(@esp+4)+16 
002f6406 "This is My Caption For 2015 Comm" 
002f6446 "unity vs" 

编辑2这是在转储模式下,你需要修改一个PDB,你不能使用执行的实况会话命令

我们是在我们可以使用步进命令直播DBG会议这在DMP模式的arent可用

0:000> .tlist -c -v 
0n3324 Msgbox.exe 
     Session: 1 User: HP-PC\HP Command Line: Msgbox.exe 

让搜索一些所属类别,我们需要

0:000> dt *!*DLGTEMPLATE* 
0:000> $$ no the thype info is not available 
0:000> $$ we know ole32.dll has it 
0:000> $$ so lets hack load it 

分配一些存储器

0:000> .dvalloc 1000 
Allocated 1000 bytes starting at 00020000 
save the current eip 

0:000> ? @eip 
Evaluate expression: 2008221094 = 77b305a6 

在所分配的存储器

0:000> ea 20100 "ole32.dll" 
0:000> db 20100 l20 
00020100 6f 6c 65 33 32 2e 64 6c-6c 00 00 00 00 00 00 00 ole32.dll....... 
00020110 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 

组装一个LoadLibraryA呼叫直列

嵌入模块名字符串在一些地址
0:000> a 20000 
00020000 push 20100 
push 20100 
00020005 call kernel32!LoadLibraryA 
call kernel32!LoadLibraryA 
0002000a 

变化EIP到迂回地址

0:000> r eip = 20000 

single step to load a dll into the address space 


0:000> p 
eax=00000000 ebx=00000000 ecx=0026f80c edx=77ad70f4 esi=fffffffe edi=00000000 
eip=00020005 esp=0026f824 ebp=0026f854 iopl=0   nv up ei pl zr na pe nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000246 
00020005 e852395877  call kernel32!LoadLibraryA (775a395c) 
0:000> p 
ModLoad: 77930000 77a8c000 C:\Windows\system32\ole32.dll 
ModLoad: 75ee0000 75f81000 C:\Windows\system32\RPCRT4.dll 
ModLoad: 77530000 7754f000 C:\Windows\system32\IMM32.DLL 
ModLoad: 76030000 760fc000 C:\Windows\system32\MSCTF.dll 
eax=77930000 ebx=00000000 ecx=77ae6570 edx=002b0174 esi=fffffffe edi=00000000 
eip=0002000a esp=0026f828 ebp=0026f854 iopl=0   nv up ei pl zr na pe nc 
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000    efl=00000246 
0002000a 0000   add  byte ptr [eax],al   ds:0023:77930000=4d 

复位EIP回

0:000> r eip = 77b305a6 

我们研究的所属类别和宾果我们把它

0:000> dt *!*DLGTEMPLATE* 
      ole32!LPDLGTEMPLATEA 
      ole32!LPDLGTEMPLATE 
      ole32!LPDLGTEMPLATEW 
      ole32!LPCDLGTEMPLATE 
      ole32!LPCDLGTEMPLATEA 
      ole32!LPCDLGTEMPLATEW 
      ole32!DLGTEMPLATE 
      ole32!DLGTEMPLATE 
+0

首先,非常感谢您为此付出的所有努力,我绝对被吹当我第一次读到这个时候离开。我试图完成与您相同的步骤并编辑了问题以包含我的WinDbg输出。对我来说,InternalDialogBox不在调用堆栈的顶部,所以我试图按照你的建议使用.frame/r来获取正确的esp地址。但不幸的是,直流输出没有给我InternalDialogBox的参数。有没有机会从我的编辑中知道我做错了什么? – Justin

+0

它取决于我通过在任务管理器中创建一个正在运行的进程的转储并添加注释来添加一些信息,看看是否有帮助(我似乎无法使用最新的编辑核实您的较早的转储地址(aslr不适用于转储iirc但地址不同在你的文章中是相同的转储或不同的转储) – blabb

+0

对不起,我切换转储:)我会看看我能否找到原始并更新问题。 – Justin

相关问题