1. 程式人生 > >DUMP檔案分析4:棧溢位

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檔案綜合分析,還需要進行動態除錯。