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]);
- 1
- 2
- 3
- 4
- 5
- 6
需要注意的是,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
---------
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
沒有得到什麼有價值的資訊。通過 kb 命令檢視一下棧:
異常發生之後的棧還完好,之前的棧被破壞,已經解析不出來符號了。還記得上一節怎麼做的嗎?檢視地址 0x39f230:
異常程式碼是 C0000005,異常地址是 0000000a。實際上,Windbg有專門的指令來解析_EXCEPTION_RECORD結構,即 .exr,如下:
來看看異常發生的地址:
這個地址無法讀取(實際上位於NULL的64KB內)。現在的問題是,是誰讀取了這個地址?是取資料?還是取指令?(實際上.exr指令已經給出了答案)上節說到了函式KiUserExceptionDispatcher,它的一個引數是_EXCEPTION_RECORD結構的指標,另一個引數是CONTEXT結構的指標,也就是如下原型:
VOID NTAPI KiUserExceptionDispatcher( PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context);
- 1
- 2
從棧呼叫棧中可以找到這個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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
可以看到,在地址0039f884 之後又可以解析出來符號,所以,我們大概可以判斷39f568-0039f884 之間的棧被破壞了。對於這個DUMP檔案,我們能做的差不多就這些了。由於棧被破壞,我們無法再回溯函式呼叫,無法再進一步定位異常的位置。因此,DUMP檔案由於是一種靜止的快照,有點時候,只能作為一種輔助分析手段,要定位具體的原因,需要多個DUMP檔案綜合分析,還需要進行動態除錯。