DUMP文件分析4:栈溢出

前面说到过,栈溢出类型的异常通过编程的方式获取DUMP可能不成功,因为栈溢出会破坏SEH(结构化异常处理)框架。实际上,通过DUMP文件来调试栈溢出同样是困难的,因为栈溢出本身一般不会造成异常,异常往往发生在栈溢出破坏栈上的数据之后,同时,由于栈溢出破坏了栈上的数据,使得我们无法对函数调用进行回溯,从而难以定位问题的发生位置。
本节的示例是经dump1简单修改而来,在Crash Me!按钮的消息处理函数中,写下如下代码:

int a[10];

for( int i = 0; i < 200; i++  )
    a[i] = i;

printf("%d\n", a[0]);

需要注意的是,Visual Studio针对栈溢出有保护措施,如果开启了保护措施,则栈溢出会被检测出来,例如:

这里我们使用Release编译,并选择最大化速度优化代码,这样就不会添加栈溢出的检查代码。此时,再运行程序:

就检查不到栈溢出了。同时,我们的MyUnhandledExceptionFilter函数也没有起作用,没有生成mini.dmp。因此,我们用任务管理器手动抓取DUMP文件。
加DUMP文件加载到Windbg中,切换到32位模式,然后使用 !analyze -v进行分析:

WARNING: ole32 overlaps gdi32
*** WARNING: symbols timestamp is wrong 0x569a9398 0x569a8dc2 for ole32.dll
*** ERROR: Module load completed but symbols could not be loaded for mfc90.dll
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for msvcr90.dll - 
Cannot find frame 0x7c, previous scope unchanged
Failed calling InternetOpenUrl, GLE=12029

FAULTING_IP: 
wow64cpu!CpupReturnFromSimulatedCode+0
7476271e 6744            inc     esp

EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 0000000000000000
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 0

FAULTING_THREAD:  00000000000014b0

DEFAULT_BUCKET_ID:  STACKIMMUNE

PROCESS_NAME:  dump2.exe

OVERLAPPED_MODULE: Address regions for 'ole32' and 'gdi32' overlap

ERROR_CODE: (NTSTATUS) 0x80000003 - {

EXCEPTION_CODE: (NTSTATUS) 0x80000003 (2147483651) - {

MOD_LIST: <ANALYSIS/>

NTGLOBALFLAG:  0

APPLICATION_VERIFIER_FLAGS:  0

CONTEXT:  ffffffffc0000005 -- (.cxr 0xffffffffc0000005)
Unable to read context, HRESULT 0x80004002

ADDITIONAL_DEBUG_TEXT:  Followup set based on attribute [Is_ChosenCrashFollowupThread] from Frame:[0] on thread:[PSEUDO_THREAD]

LAST_CONTROL_TRANSFER:  from 00000000775b94cf to 000000007752f971

PRIMARY_PROBLEM_CLASS:  STACKIMMUNE

BUGCHECK_STR:  APPLICATION_FAULT_STACKIMMUNE_ZEROED_STACK

STACK_TEXT:  
00000000`00000000 00000000`00000000 dump2.exe+0x0


STACK_COMMAND:  .cxr 00000000001AE2D0 ; kb ; ** Pseudo Context ** ; kb

SYMBOL_NAME:  dump2.exe

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: dump2

IMAGE_NAME:  dump2.exe

DEBUG_FLR_IMAGE_TIMESTAMP:  579d6915

FAILURE_BUCKET_ID:  STACKIMMUNE_80000003_dump2.exe!Unknown

BUCKET_ID:  X64_APPLICATION_FAULT_STACKIMMUNE_ZEROED_STACK_dump2.exe

FOLLOWUP_IP: 
dump2!__ImageBase+0
003c0000 4d              dec     ebp

WATSON_STAGEONE_URL:  http://watson.microsoft.com/StageOne/dump2_exe/1_0_0_1/579d6915/unknown/0_0_0_0/bbbbbbb4/80000003/00000000.htm?Retriage=1

Followup: MachineOwner
---------

没有得到什么有价值的信息。通过 kb 命令查看一下栈:

异常发生之后的栈还完好,之前的栈被破坏,已经解析不出来符号了。还记得上一节怎么做的吗?查看地址 0x39f230:

异常代码是 C0000005,异常地址是 0000000a。实际上,Windbg有专门的指令来解析_EXCEPTION_RECORD结构,即 .exr,如下:

来看看异常发生的地址:

这个地址无法读取(实际上位于NULL的64KB内)。现在的问题是,是谁读取了这个地址?是取数据?还是取指令?(实际上.exr指令已经给出了答案)上节说到了函数KiUserExceptionDispatcher,它的一个参数是_EXCEPTION_RECORD结构的指针,另一个参数是CONTEXT结构的指针,也就是如下原型:

VOID NTAPI KiUserExceptionDispatcher( PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context);

从栈调用栈中可以找到这个CONTEXT的地址:

来看看这个CONTEXT结构:

其中保存了异常发生时的寄存器上下文。Windbg中有专门解析这个结构的指令 .cxr,我们来看看寄存器的值:

看到EIP的值正是发生非法读取的地址,因此,可以判断是读指令的时候发生的异常。我们来看看栈被破坏的大概范围,使用的是dds指令,这个指令将地址范围内的符号进行解析:

0:000:x86> dds 39f568 39ffff
0039f568  0000000b
0039f56c  0000000c
0039f570  0000000d
0039f574  0000000e
0039f578  0000000f
0039f57c  00000010
0039f580  00000011
0039f584  00000012
0039f588  00000013
0039f58c  00000014
0039f590  00000015
0039f594  00000016
0039f598  00000017
0039f59c  00000018
0039f5a0  00000019
0039f5a4  0000001a
0039f5a8  0000001b
0039f5ac  0000001c
0039f5b0  0000001d
0039f5b4  0000001e
0039f5b8  0000001f
0039f5bc  00000020
0039f5c0  00000021
0039f5c4  00000022
0039f5c8  00000023
0039f5cc  00000024
0039f5d0  00000025
0039f5d4  00000026
0039f5d8  00000027
0039f5dc  00000028
0039f5e0  00000029
0039f5e4  0000002a
0039f5e8  0000002b
0039f5ec  0000002c
0039f5f0  0000002d
0039f5f4  0000002e
0039f5f8  0000002f
0039f5fc  00000030
0039f600  00000031
0039f604  00000032
0039f608  00000033
0039f60c  00000034
0039f610  00000035
0039f614  00000036
0039f618  00000037
0039f61c  00000038
0039f620  00000039
0039f624  0000003a
0039f628  0000003b
0039f62c  0000003c
0039f630  0000003d
0039f634  0000003e
0039f638  0000003f
0039f63c  00000040
0039f640  00000041
0039f644  00000042
0039f648  00000043
0039f64c  00000044
0039f650  00000045
0039f654  00000046
0039f658  00000047
0039f65c  00000048
0039f660  00000049
0039f664  0000004a
0039f668  0000004b
0039f66c  0000004c
0039f670  0000004d
0039f674  0000004e
0039f678  0000004f
0039f67c  00000050
0039f680  00000051
0039f684  00000052
0039f688  00000053
0039f68c  00000054
0039f690  00000055
0039f694  00000056
0039f698  00000057
0039f69c  00000058
0039f6a0  00000059
0039f6a4  0000005a
0039f6a8  0000005b
0039f6ac  0000005c
0039f6b0  0000005d
0039f6b4  0000005e
0039f6b8  0000005f
0039f6bc  00000060
0039f6c0  00000061
0039f6c4  00000062
0039f6c8  00000063
0039f6cc  00000064
0039f6d0  00000065
0039f6d4  00000066
0039f6d8  00000067
0039f6dc  00000068
0039f6e0  00000069
0039f6e4  0000006a
0039f6e8  0000006b
0039f6ec  0000006c
0039f6f0  0000006d
0039f6f4  0000006e
0039f6f8  0000006f
0039f6fc  00000070
0039f700  00000071
0039f704  00000072
0039f708  00000073
0039f70c  00000074
0039f710  00000075
0039f714  00000076
0039f718  00000077
0039f71c  00000078
0039f720  00000079
0039f724  0000007a
0039f728  0000007b
0039f72c  0000007c
0039f730  0000007d
0039f734  0000007e
0039f738  0000007f
0039f73c  00000080
0039f740  00000081
0039f744  00000082
0039f748  00000083
0039f74c  00000084
0039f750  00000085
0039f754  00000086
0039f758  00000087
0039f75c  00000088
0039f760  00000089
0039f764  0000008a
0039f768  0000008b
0039f76c  0000008c
0039f770  0000008d
0039f774  0000008e
0039f778  0000008f
0039f77c  00000090
0039f780  00000091
0039f784  00000092
0039f788  00000093
0039f78c  00000094
0039f790  00000095
0039f794  00000096
0039f798  00000097
0039f79c  00000098
0039f7a0  00000099
0039f7a4  0000009a
0039f7a8  0000009b
0039f7ac  0000009c
0039f7b0  0000009d
0039f7b4  0000009e
0039f7b8  0000009f
0039f7bc  000000a0
0039f7c0  000000a1
0039f7c4  000000a2
0039f7c8  000000a3
0039f7cc  000000a4
0039f7d0  000000a5
0039f7d4  000000a6
0039f7d8  000000a7
0039f7dc  000000a8
0039f7e0  000000a9
0039f7e4  000000aa
0039f7e8  000000ab
0039f7ec  000000ac
0039f7f0  000000ad
0039f7f4  000000ae
0039f7f8  000000af
0039f7fc  000000b0
0039f800  000000b1
0039f804  000000b2
0039f808  000000b3
0039f80c  000000b4
0039f810  000000b5
0039f814  000000b6
0039f818  000000b7
0039f81c  000000b8
0039f820  000000b9
0039f824  000000ba
0039f828  000000bb
0039f82c  000000bc
0039f830  000000bd
0039f834  000000be
0039f838  000000bf
0039f83c  000000c0
0039f840  000000c1
0039f844  000000c2
0039f848  000000c3
0039f84c  000000c4
0039f850  000000c5
0039f854  000000c6
0039f858  000000c7
0039f85c  00b455f8
0039f860  00000001
0039f864  00590f20
0039f868  00000111
0039f86c  00bb9930
0039f870  00b99890
0039f874  00000000
0039f878  001005d2
0039f87c  00000f20
0039f880  0039f8a4
0039f884  75b096d5 user32!SendMessageW+0x7f
0039f888  00b455d0
0039f88c  00000000
0039f890  5b68855d mfc90+0x5855d
0039f894  000003e8
0039f898  000209e6
0039f89c  00000000
0039f8a0  00000001
0039f8a4  0039f8bc
0039f8a8  75b45feb user32!xxxButtonNotifyParent+0x66
0039f8ac  001005d2
0039f8b0  00000111
0039f8b4  000003e8
0039f8b8  000209e6
0039f8bc  0039f8e4
0039f8c0  75b4612c user32!xxxBNReleaseCapture+0x138

可以看到,在地址0039f884 之后又可以解析出来符号,所以,我们大概可以判断39f568-0039f884 之间的栈被破坏了。对于这个DUMP文件,我们能做的差不多就这些了。由于栈被破坏,我们无法再回溯函数调用,无法再进一步定位异常的位置。因此,DUMP文件由于是一种静止的快照,有点时候,只能作为一种辅助分析手段,要定位具体的原因,需要多个DUMP文件综合分析,还需要进行动态调试。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值