Chinaunix首页 | 论坛 | 博客
  • 博客访问: 212982
  • 博文数量: 78
  • 博客积分: 3169
  • 博客等级: 中校
  • 技术积分: 805
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-25 13:50
文章分类
文章存档

2012年(1)

2011年(77)

分类: C/C++

2011-10-05 16:56:40

windbg调试实例(3)——崩溃蓝屏之内核堆栈溢出
1、崩溃发生背景
一个系统内核驱动程序运行过程中导致蓝屏。
2、提取dump文件
a) Dump可用前提:崩溃存储为核心内存存储,该项设置在:系统属性–高级–启动和故障恢复–设置–写入调试信息
b) 找到系统windows目录下memory.dmp
3、分析蓝屏原因
1)windbg打开dump
2)!analyze -v 分析挂掉线程的详细情形,错误原因。
[code]01 0: kd> !analyze -v
02 UNEXPECTED_KERNEL_MODE_TRAP (7f)
03 This means a trap occurred in kernel mode, and it's a trap of a kind
04 that the kernel isn't allowed to have/catch (bound trap) or that
05 is always instant death (double fault). The first number in the
06 bugcheck params is the number of the trap (8 = double fault, etc)
07 Consult an Intel x86 family manual to learn more about what these
08 traps are. Here is a *portion* of those codes:
09 If kv shows a taskGate
10 use .tss on the part before the colon, then kv.
11 Else if kv shows a trapframe
12 use .trap on that value
13 Else
14 .trap on the appropriate frame will show where the trap was taken
15 (on x86, this will be the ebp that goes with the procedure KiTrap)
16 Endif
17 kb will then show the corrected stack.
18 Arguments:
19 Arg1: 00000008, EXCEPTION_DOUBLE_FAULT
20 Arg2: 80148000
21 Arg3: 00000000
22 Arg4: 00000000
[/code]
UNEXPECTED_KERNEL_MODE_TRAP (7f)表示这个问题发生在内核模式。一个线程的内核栈只有12K大小,在栈的末端有一页无效的页面进行保护。当使用的栈大小超过12K,访问到那个无效页面的时候,处理器就会触发一个页错误,然后试图把寄存器压入栈中,结果造成了第二个页错误。这就是double fault的含义。这里可以猜测这个内核驱动程序访问了12k以外的内存。
因为!analyze -v显示的堆栈信息不完全,所以要加个数字比如100 来完全显示,同时用f需要显示栈上每个部分使用了多少字节:
[code]01 0: kd> kf 100
02 24 951e5f84 84d7ea91 fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x22a
03 4c 951e5fd0 81827ecf fltmgr!FltpCreate+0x2a1
04 18 951e5fe8 8c383125 nt!IofCallDriver+0x63
05 c 951e5ff4 8c385142 Lanman+0x1125
06 aa4 951e6a98 8c384eca Lanman+0x3142
07 20 951e6ab8 8c3839ac Lanman+0x2eca
08 10 951e6ac8 81827ecf Lanman+0x19ac
09 18 951e6ae0 81996f5c nt!IofCallDriver+0x63
10 b8 951e6b98 819eef0d nt!IopParseDevice+0xcff
11 90 951e6c28 819ec6b9 nt!ObpLookupObjectName+0x615
12 60 951e6c88 819839e0 nt!ObOpenObjectByName+0x13c
13 74 951e6cfc 819833ca nt!IopCreateFile+0x5ec
14 5c 951e6d58 84d85516 nt!IoCreateFileEx+0x9d
15 98 951e6df0 84d85891 fltmgr!FltpExpandFilePathWorker+0x162
16 18 951e6e08 84d85ada fltmgr!FltpExpandFilePath+0x19
17 1c 951e6e24 84d86129 fltmgr!FltpGetNormalizedFileNameWorker+0x160
18 18 951e6e3c 84d8351f fltmgr!FltpGetNormalizedFileName+0x19
19 18 951e6e54 84d6eb71 fltmgr!FltpCreateFileNameInformation+0x81
20 20 951e6e74 84d6ecbe fltmgr!HandleStreamListNotSupported+0x125
21 30 951e6ea4 84d6f37c fltmgr!FltpGetFileNameInformation+0xc6
22 28 951e6ecc 8c396a8a fltmgr!FltGetFileNameInformation+0x120
23 3c 951e6f08 84d69843 PROCMON12+0x2a8a
24 5c 951e6f64 84d6bf10 fltmgr!FltpPerformPreCallbacks+0x2e5
25 14 951e6f78 84d7e292 fltmgr!FltpPassThroughInternal+0x32
26 14 951e6f8c 84d7ea7f fltmgr!FltpCreateInternal+0x24
27 44 951e6fd0 81827ecf fltmgr!FltpCreate+0x28f
28 18 951e6fe8 8c383125 nt!IofCallDriver+0x63
29 c 951e6ff4 8c385142 Lanman+0x1125
30 aa4 951e7a98 8c384eca Lanman+0x3142
31 20 951e7ab8 8c3839ac Lanman+0x2eca
32 10 951e7ac8 81827ecf Lanman+0x19ac
33 18 951e7ae0 81996f5c nt!IofCallDriver+0x63
34 b8 951e7b98 819eef0d nt!IopParseDevice+0xcff
35 90 951e7c28 819ec6b9 nt!ObpLookupObjectName+0x615
36 60 951e7c88 819839e0 nt!ObOpenObjectByName+0x13c
37 74 951e7cfc 819900f5 nt!IopCreateFile+0x5ec
38 48 951e7d44 8188c96a nt!NtOpenFile+0x2a
39 0 951e7d44 77020f34 nt!KiFastCallEntry+0x12a
40 0006f7c0 00000000 0x77020f34
[/code]
看一下两处红色标示,使用字节很大并且都来自lanman这个程序,达到5448byte,这就已经接近12k的一半了,所以后面猜测是耗尽、溢出了。再此开发也应该知道问题在哪里了,使用这12k内存不小心,所以开发人员须注意尽量不要在栈上分配超过1K的内存,不能递替调用,但是如果调用太深的话,还是会溢出的,这个就要遇到看怎么解决了.

实例二

1、程序崩溃发生过程
这是一个对文件进行处理的模块,而处理模块在处理之前,需查询被处理的文件是否值得处理。这个任务执
行过程中发生了崩溃,问题就发生在查询模块。
2、提取dump文件
3、分析dump:
1)启动windbg,file–open crash dump 配置符号库,reload完成 。
2)使用命令 :.ecxr获得进程崩溃时寄存器的内容
[code]1 0:021> .ecxr (意指恢复崩溃时所有寄存器的内容,包括堆栈等)
2 eax=0532d414 ebx=00000fec ecx=000003fb edx=00000000 esi=0532c428 edi=00000000
3 eip=750f53ea esp=0490f22c ebp=0490f234 iopl=0 nv up ei pl nz na pe nc
4 cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
5 msvcr80!memmove+0x5a:
6 750f53ea f3a5 rep movs dword ptr es:[edi],dword ptr [esi] es:002b:00000000=???????? ds:002b:0532c428=00000000
[/code]
3)使用命令:k 显示堆栈
[code]01 0:021> k (.ecxr不能直接显示堆栈,需使用k显示堆栈)
02 *** Stack trace for last set context - .thread/.cxr resets it
03 ChildEBP RetAddr
04 WARNING: Stack unwind information not available. Following frames may be wrong.
05 0490f234 03ba4806 msvcr80!memmove+0x5a(kxewfsys调用memmove,memmove是个字符串操作函数,能把字符串的一部分复制到另一部分,这里出问题,可能是复制时传递的指针有问题,或者字符串的大小有问题)
06 0490f25c 03ba2547 kxewfsys!__ovfl_get+0xa6 (调用memmove之前内部的一些处理)
07 0490f27c 03ba4a74 kxewfsys!__bt_cmp+0x77
08 0490f2a8 03ba2679 kxewfsys!__bt_search+0x74
09 0490f2c4 03ba1409 kxewfsys!__bt_get+0x49
10 0490f2d8 03ba7448 kxewfsys!IKBDBImpl::Get+0x19
11 0490f2f8 03ba750d kxewfsys!CFdbFileInfo::Search+0x28 [e:\eingsoft_euba\build\build_src\kice\kice_kxewhite\src\kxewfssys\fdbfileinfo.cpp @ 483]
12 0490f338 03ba9c63 kxewfsys!CFdbFileInfo::QueryFileInfo+0x4d [e:\eingsoft_euba\build\build_src\kice\kice_kxewhite\src\kxewfssys\fdbfileinfo.cpp @ 546]
13 0490f380 028210d1 kxewfsys!CFdbManager::QueryFileInfo+0xa3 [e:\eingsoft_euba\build\build_src\kice\kice_kxewhite\src\kxewfssys\fdbmanager.cpp @ 370] (kxewfsys 是处理查询模块)
14 *** ERROR: Symbol file could not be found. Defaulted to export symbols for kspfeng.dll
15 0490f390 03b1323c kxewhite!kxe_white_query_file_info+0x21 [e:\eingsoft_euba\build\build_src\kice\kice_kxewhite\src\kxewfssdk\kxewfs.cpp @ 103] (将文件提交进行查询.)
16 0490f45c 03b13442 kspfeng!KSEGetAddonEntries+0x21fbc (kspfeng.dll是文件处理模块用到的公共功能的封装文件)
17 *** ERROR: Symbol file could not be found. Defaulted to export symbols for ksecore.dll
18 0490f498 03abcaa4 kspfeng!KSEGetAddonEntries+0x221c2
19 0490f4c8 03b07fd5 ksecore+0x1caa4
20 0490f52c 03b1c52b kspfeng!KSEGetAddonEntries+0x16d55
21 0490f860 5019dd7c kspfeng!KSEGetAddonEntries+0x2b2ab
22 0490f864 01c95695 0x5019dd7c
23 0490f868 1a77217c 0x1c95695
24 0490f86c 01c95693 0x1a77217c
25 0490f870 1a7982dc 0x1c95693
26 0490f874 01c95693 0x1a7982dc
[/code]
4、总结崩溃原因
查询模块,对文件路径的处理存在bug。

实例1

这个系列的文章是vivilisa写的,但是前几天去他的博客看貌似没有这几篇文章了,原来把这系列文章存在

了电脑里,现在拿出来跟大家分享,不知道vivilisa是不是同意。暂时先发表了再说,不成的话就了。感觉他写

的这几篇调试文章很好,称赞下。

1、崩溃发生过程    程序执行过程中崩溃,弹出mssagebox,提示R6034错误。查看r6034错误:表示运行库的

manifest设置不正确。

2、提取dump过程
1)查看任务管理器,崩溃的进程还在。判定可以用Windbg截获dump
2)打开windbg,file–attach to a process,选择崩溃进程如test.exe;
3)使用命令 .dump /mf d://test.dmp
4)确认提取成功:查看在d盘根目录下是否有test.dmp文件。
3、分析崩溃原因
1) 打开windbg,file–open crash dump ,打开dump文件test.dmp
2) 查看崩溃文件版本:使用lm v m test*  获得崩溃进程文件test.exe文件信息。
01     0:008> lm v m test*
02     start    end        module name
03    00400000 00526000   test     (deferred)
04     Image path: C:”Program Files (x86)”test”test.exe
05     Image name: test.exe
06     Timestamp:        Wed Dec 10 17:29:43 2008 (493F8C07)
07     CheckSum:         0012ACC3
08     ImageSize:        00126000
09     File version:     2008.12.10.34
10     Product version:  1.0.1126.34
11     File flags:       0 (Mask 3F)
12     File OS:          40004 NT Win32
13     File type:        2.0 Dll
14     File date:        00000000.00000000
15     Translations:     0000.04b0
16     InternalName:     test
17     ProductVersion:   1,0,1126,34
18     FileVersion:      2008,12,10,34
3)加载对应符号pdb,根据Timestamp: Wed Dec 10 17:29:43 2008 (493F8C07),找到对应的pdb文件,选择file–symble file path 将pdb文件路径加入。
4)分析
01 0:008> ~*k  看所有线程的堆栈
02    0  Id: 990.c38 Suspend: 1 Teb: 7efdd000 Unfrozen
03 ChildEBP RetAddr
04 WARNING: Stack unwind information not available. Following frames may be wrong.
05 0017d878 75ae81c8 user32!WaitMessage+0×15
06 0017d8ac 75af478a user32!GetCursorFrameInfo+0x7c
07 0017d958 75af46f5 user32!SetMessageQueue+0x4e8
08 0017dab0 75b2d2c3 user32!SetMessageQueue+0×453
09 0017db0c 75b2d342 user32!MessageBoxTimeoutW+0×52
10 0017db40 75b2d390 user32!MessageBoxTimeoutA+0×76
11 0017db60 75b2d3d5 user32!MessageBoxExA+0x1b
12 0017db7c 718f986e user32!MessageBoxA+0×18
13 0017dbc0 718f1c2c msvcr80!__crtMessageBoxA+0x1b4
14 0017dbe4 718f2217 msvcr80!_NMSG_WRITE+0×162
15 0017dc20 718f2348 msvcr80!__p__winver+0x13c
16 0017dc30 776dfcc0 msvcr80!_CRTDLL_INIT+0x1d
17 0017dc50 776e9b28 ntdll!RtlReleasePebLock+0×28
18 0017dd48 776e95ae ntdll!LdrFindResourceDirectory_U+0x9bf
19 0017dfcc 777029db ntdll!LdrFindResourceDirectory_U+0×445
20 0017e250 765e4d50 ntdll!RtlDestroyQueryDebugBuffer+0x48d5
21 0017e2b4 765e4dca kernel32!LoadLibraryExW+0×112
22 0017e2c8 004265e9 kernel32!LoadLibraryW+0×11
//此处为程序到系统程序的一个临界点。分析首先从这里分析起。
23 0017e524 00426e43 test!KLoadDllUtility::AutoSearchLoadLibrary+0x5f [e:"kloaddllutility.h @ 32]
24 0017e554 00426877 test!KPopSupport::InitializeKPopSystem+0×29 [e:"popimport.cpp @ 1037]
分析线程堆栈,一般情况下,出现messagebox都是不正常的。由于此次崩溃系统有弹出messagebox,而刚好第一个线程堆栈有messagebox相关字眼,所以怀疑是第一个线程堆栈出现问题。
01 0:008> dd 0017e2c8 dd  (dd表示以四个字节的方式查看ebp信息。)
02 0017e2c8  0017e524 004265e9 0017e314 004d3578  (0017e524表示上一个函数的ebp; 004265e9 表示函数返回地址 0017e314 表示函数的参数 查看msdn,loadlibary只有一个参数,并且参数是一个字符串,所以只有0017e314有效,并且表示一个地址。)
03 0017e2d8  02724fd8 00000000 00000000 00000000
04 0017e2e8  00000000 026fc1a8 00000000 00000000
05 0017e2f8  00000000 00000008 0000000f 00000000
06 0017e308  00000000 00000000 00000000 003a0063
07 0017e318  0050005c 006f0072 00720067 006d0061
08 0017e328  00460020 006c0069 00730065 00280020
09 0017e338  00380078 00290036 004b005c 006e0069
10 0:008> db 0017e314   (db以字节的方式查看参数内容)
11 0017e314  63 00 3a 00 5c 00 50 00-72 00 6f 00 67 00 72 00  c.:.”.P.r.o.g.r.
12 0017e324  61 00 6d 00 20 00 46 00-69 00 6c 00 65 00 73 00  a.m. .F.i.l.e.s.
13 0017e334  20 00 28 00 78 00 38 00-36 00 29 00 5c 00 4b 00   .(.x.8.6.).”.e.
14 0017e344  69 00 6e 00 67 00 73 00-6f 00 66 00 74 00 5c 00  i.r.g.s.o.f.t.”.
15 0017e354  4b 00 69 00 6e 00 67 00-73 00 6f 00 66 00 74 00  e.i.n.g.s.o.f.t.
16 0017e364  20 00 49 00 6e 00 74 00-65 00 72 00 6e 00 65 00   .I.n.t.e.r.n.e.
17 0017e374  74 00 20 00 53 00 65 00-63 00 75 00 72 00 69 00  t. .h.e.c.u.r.i.
18 0017e384  74 00 79 00 20 00 32 00-30 00 30 00 38 00 5c 00  t.y. .2.0.0.8.”.
19 0:008> db (db继续显示,使内容显示完全)
20 0017e394  53 00 43 00 4f 00 4d 00-2e 00 64 00 6c 00 6c 00  S.C.O.M…d.l.l.
21 0017e3a4  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  …………….
22 0017e3b4  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  …………….
23 0017e3c4  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  …………….
24 0017e3d4  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  …………….
25 0017e3e4  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  …………….
26 0017e3f4  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  …………….
27 0017e404  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ……………
4、分析结果总结
分析发现 :调用了scom.dll.根据对产品功能的了解,test不会调用该dll,说明调用出错,调错了文件,接下来需要做的是理清test调用流程,修改bug啦。至于为啥错误id为r6034,是因为scom.dll需要运行库,而test进程内部未设定。

阅读(4784) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~