使用Windbg解析dump檔案
阿新 • • 發佈:2019-01-04
例項1 如何調查堆被破壞問題。
錯誤程式碼:0xc0000374
錯誤含義:ACTIONABLE_HEAP_CORRUPTION_heap_failure_buffer_overrun
第一步、先用「!analyze -v」分析出錯誤的地方以及由於什麼原因導致程式Dump掉的。
無非是記憶體溢位,訪問非法地址等幾種。
0:009> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
GetPageUrlData failed, server returned HTTP status 404
URL requested: http://watson.microsoft.com/StageOne/ProcessA_exe/1_0_0_1/5134aefd/ntdll_dll/6_1_7601_18229/51fb164a/c0000374/000c4102.htm?Retriage=1
FAULTING_IP:
ntdll!RtlReportCriticalFailure+62
00000000`777b4102 eb00 jmp ntdll!RtlReportCriticalFailure+0x64 (00000000`777b4104)
EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 00000000777b4102 (ntdll!RtlReportCriticalFailure+0x0000000000000062)
ExceptionCode: c0000374
ExceptionFlags: 00000001
NumberParameters: 1
Parameter[0]: 000000007782b4b0
PROCESS_NAME: ProcessA.exe
ERROR_CODE: (NTSTATUS) 0xc0000374 - <Unable to get error code text>
EXCEPTION_CODE: (NTSTATUS) 0xc0000374 - <Unable to get error code text>
EXCEPTION_PARAMETER1: 000000007782b4b0
MOD_LIST: <ANALYSIS/>
NTGLOBALFLAG: 0
APPLICATION_VERIFIER_FLAGS: 0
FAULTING_THREAD: 0000000000002f8c
DEFAULT_BUCKET_ID: ACTIONABLE_HEAP_CORRUPTION_heap_failure_buffer_overrun
PRIMARY_PROBLEM_CLASS: ACTIONABLE_HEAP_CORRUPTION_heap_failure_buffer_overrun
BUGCHECK_STR: APPLICATION_FAULT_ACTIONABLE_HEAP_CORRUPTION_heap_failure_buffer_overrun
LAST_CONTROL_TRANSFER: from 00000000777b4746 to 00000000777b4102
STACK_TEXT:
00000000`0548e170 00000000`777b4746 : 00000000`00000002 00000000`00000023 00000000`00000000 00000000`00000003 : ntdll!RtlReportCriticalFailure+0x62
00000000`0548e240 00000000`777b5952 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`1c01001d : ntdll!RtlpReportHeapFailure+0x26
00000000`0548e270 00000000`777b7604 : 00000000`00c50000 00000000`00c50000 00000000`0000000a 00000000`00000000 : ntdll!RtlpHeapHandleError+0x12
00000000`0548e2a0 00000000`777b79e8 : 00000000`00c50000 00000000`00000000 00000000`00100000 00000000`00000000 : ntdll!RtlpLogHeapFailure+0xa4
00000000`0548e2d0 00000000`7774fad6 : 00000000`00c50000 00000000`00c59e50 00000000`00c50000 00000000`00000000 : ntdll!RtlpAnalyzeHeapFailure+0x3a8
00000000`0548e330 00000000`777434d8 : 00000000`00c50000 00000000`00000003 00000000`000006cc 00000000`000006e0 : ntdll!RtlpAllocateHeap+0x1d2a
00000000`0548e8d0 00000000`777247ea : 00000000`00000003 00000000`00c5ee80 00000000`00c50278 00000000`000006cc : ntdll!RtlAllocateHeap+0x16c
00000000`0548e9e0 00000000`77723ff2 : 00000000`00c50000 00000000`00000003 00000000`00c5ee90 00000000`000006cc : ntdll!RtlpReAllocateHeap+0x648
00000000`0548eca0 00000000`750c712f : 00000000`0548fbe8 00000000`00c5ee90 00000000`00000000 00000000`000005ac : ntdll!RtlReAllocateHeap+0xa2
00000000`0548edb0 00000001`40010f6f : 00000000`00000000 00000000`0548fbe8 00000000`00000000 00000000`00000661 : msvcr80!realloc+0x6f [f:\dd\vctools\crt_bld\self_64_amd64\crt\src\realloc.c @ 332]
00000000`0548ede0 00000001`4000f63c : ffffffff`ffffffff 00000000`0548ff10 00000000`00c97fd0 00000000`0548fe48 : ProcessA!FunctionA_AnalyzeEventData+0xfcf [e:\ProcessA\FunctionA_sockserv.cpp @ 1666]
00000000`0548f8a0 00000000`774e652d : 00000000`000002a0 00000000`00000000 00000000`00000000 00000000`00000000 : ProcessA!FunctionA_SockWork+0xe1c [e:\ProcessA\FunctionA_sockserv.cpp @ 1102]
00000000`0548ff60 00000000`7771c541 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0xd
00000000`0548ff90 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x1d
STACK_COMMAND: !heap ; ~9s; .ecxr ; kb
FOLLOWUP_IP:
msvcr80!realloc+6f [f:\dd\vctools\crt_bld\self_64_amd64\crt\src\realloc.c @ 332]
00000000`750c712f 4885c0 test rax,rax
SYMBOL_STACK_INDEX: 9
SYMBOL_NAME: msvcr80!realloc+6f
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: msvcr80
IMAGE_NAME: msvcr80.dll
DEBUG_FLR_IMAGE_TIMESTAMP: 4ec3407e
FAILURE_BUCKET_ID: ACTIONABLE_HEAP_CORRUPTION_heap_failure_buffer_overrun_c0000374_msvcr80.dll!realloc
BUCKET_ID: X64_APPLICATION_FAULT_ACTIONABLE_HEAP_CORRUPTION_heap_failure_buffer_overrun_msvcr80!realloc+6f
WATSON_STAGEONE_URL: http://watson.microsoft.com/StageOne/ProcessA_exe/1_0_0_1/5134aefd/ntdll_dll/6_1_7601_18229/51fb164a/c0000374/000c4102.htm?Retriage=1
Followup: MachineOwner
---------
第二步、使用「!heap」找出出錯的堆。分析出錯的原因。
0000000000c59c80
0000000000c59e50 ←出錯的堆地址。
0000000000c59fd0
大家應該有這樣的常識,在使用malloc()或者realloc()分配出來的空間的前面都有
相應的管理情報,用來記錄這塊分配的記憶體的大小以及返回的時候用的情報。
從這裡很自然的猜想到,在寫往0000000000c59c80裡面寫資料的時候寫過了,
寫到0000000000c59e50上去了,導致它的管理情報被覆蓋了。從而程式dump掉了。
0:009> !heap
**************************************************************
* *
* HEAP ERROR DETECTED *
* *
**************************************************************
Details:
Error address: 0000000000c59e50
Heap handle: 0000000000c50000
Error type heap_failure_buffer_overrun (6)
Parameter 1: 000000000000000a
Last known valid blocks: before - 0000000000c59c80, after -0000000000c59fd0
Stack trace:
00000000777b79e8: ntdll!RtlpAnalyzeHeapFailure+0x00000000000003a8
000000007774fad6: ntdll!RtlpAllocateHeap+0x0000000000001d2a
00000000777434d8: ntdll!RtlAllocateHeap+0x000000000000016c
00000000777247ea: ntdll!RtlpReAllocateHeap+0x0000000000000648
0000000077723ff2: ntdll!RtlReAllocateHeap+0x00000000000000a2
00000000750c712f: msvcr80!realloc+0x000000000000006f
0000000140010f6f: ProcessA!FunctionA_AnalyzeEventData+0x0000000000000fcf
000000014000f63c: ProcessA!FunctionA_SockWork+0x0000000000000e1c
00000000774e652d: kernel32!BaseThreadInitThunk+0x000000000000000d
000000007771c541: ntdll!RtlUserThreadStart+0x000000000000001d
Index Address Name Debugging options enabled
1: 001f0000
2: 00010000
3: 00020000
4: 00670000
5: 00950000
6: 00c50000
7: 00910000
8: 00bc0000
9: 010e0000
10: 01220000
11: 01420000
12: 00c30000
13: 03660000
14: 00ba0000
15: 037b0000
16: 01340000
17: 039a0000
第三步、使用「!for_each_frame dv /t」打印出錯函式的區域性變數,找出元凶。
從下面的變數裡面找到距離0000000000c59c80地址最近的變數,對了就是它:
char * pData_n = 0x00000000`00c59c90 "SE:Security: ???"
※注意如果變數值指標的指標需要先用dc看一下該指標指向的地址。
之後看程式碼知道,程式在讀取pData_n的資料的時候如果遇到是0a(Windos換行符)就自動在後面加上
0d變成0a0d。導致pData_n記憶體越界了。
0:009> !for_each_frame dv /t
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
12 00000000`0548edb0 00000001`40010f6f msvcr80!realloc+0x6f [f:\dd\vctools\crt_bld\self_64_amd64\crt\src\realloc.c @ 332]
void * pBlock = 0x00000000`00000000
unsigned int64 newsize = 0x548fbe8
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
13 00000000`0548ede0 00000001`4000f63c ProcessA!FunctionA_AnalyzeEventData+0xfcf [e:\ProcessA\FunctionA_sockserv.cpp @ 1666]
void * cd = 0xffffffff`ffffffff
struct _MpEvsHead * Head = 0x00000000`0548ff10
char * pEventData = 0x00000000`00c97fd0 "???"
char ** pNewData = 0x00000000`0548fe48
char * SiteName = 0x00000000`0548fe18 ""
int oval_check = 0n0
char * pszHostIp = 0x00000000`0548fbf0 "192.168.1.1"
int j = 0n469
int NodeName_check = 0n0
char [2068] eventtext = char [2068] "SE:Security: ???"
unsigned long err = 0
int NL_henkan = 0n1
int Evttxt_check = 0n1
char [129] nameWork = char [129] "`_???"
int ret = 0n0
struct NameObject_t * pNameObj_n = 0x00000000`00c5eee8
char * pData_n = 0x00000000`00c59c90 "SE:Security: ???"
long lWork = 0n9
char [257] szTrcBuff = char [257] "safely divided text.([453]bytes --> [469]bytes)"
long nNameNum = 0n44
long nNewLen = 0n1740
struct NameObject_t * pNameObj_o = 0x00000000`00c98028
char * pData_o = 0x00000000`00c984c6 "SE:Security: ???"
char * pt = 0x00000000`00c59e55 "[???"
long i = 0n20
int IpAddr_check = 0n0
int res = 0n1
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
14 00000000`0548f8a0 00000000`774e652d ProcessA!FunctionA_SockWork+0xe1c [e:\ProcessA\FunctionA_sockserv.cpp @ 1102]
void * ns = 0x00000000`000002a0
char * pRead_str = 0x00000000`00c562f0 ","
int bTableRegisterd = 0n0
unsigned long err = 0
char [3] traceflg = char [3] ""
int ret = 0n0
short sWork = 0n2
int oval_check = 0n0
char * pNewData = 0x00000000`00c5ee90 "???"
char * wk = 0x00000000`0548f930 "192.168.1.1"
char [33] SiteName = char [33] ""
long lWork = 0n2032
char [257] szTrcBuff = char [257] "recv event OK"
int iLastSerchedIndex = 0n0
char [256] HostIp = char [256] "192.168.1.1"
int ret2 = 0n0
struct _MpEvsHead Head = struct _MpEvsHead
long nDataLen = 0n3
char [257] szTrcBuff2 = char [257] ""
char [20] szSendData = char [20] "OK"
struct addrinfo hinst = struct addrinfo
int conv_disc_set = 0n1
long lRc = 0n0
void * conv_disc = 0xffffffff`ffffffff
int res = 0n1
char * pData = 0x00000000`00c97fd0 "???"
long nRead = 0n3726
char [16] evttype = char [16] "Alarm.sys"
char * lpszEventid = 0x00000000`00c5f180 ""
long nSend = 0n12
char [256] ipTmp = char [256] "192.168.1.1"
char [20] szToCode = char [20] "sjis"
char [20] szFromCode = char [20] "sjis"
int bWriteEvent = 0n1
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _