관리 메뉴

kisoo

!analyze -v 가 찾아주는 스레드와 다른 스레드 컨텍스트 찾아서 Dump 디버깅하기 본문

01.About Programming /2.Kernel Lab

!analyze -v 가 찾아주는 스레드와 다른 스레드 컨텍스트 찾아서 Dump 디버깅하기

JamesK78 2009. 2. 4. 10:54
비스타 x64(64비트)버전에서 발생한 덤프를 분석해 보았다. 이미 알고 있으시겠지만 xp 에서는 디폴트로 설치된 drwtsn32.exe가 비스타에서는 없어졌다. 개인적으로 많이 아쉽다. 대신 오류가 발생하면 작업관리자에서 오른쪽 버튼 누르고 덤프를 생성해야 한다.(구찮아~) 안좋은점이 있다면 좋아진 점은 꼭 있다.(세상은 공평한가?!)  좋은점은 Hang(CPU 100%)가 되었을 때 기존에는 adplus를 이용해만 했다. 그러나 윈도우 비스타, 윈도우 2008 서버에서는 작업관리자에서 오른쪽 마우스를 클릭해서 바로 덤프를 생성하면 된다.

 

 어제 DUMP를 하나 분석했는데 특이하게 !analyze -v extension 명령을 통해 분석한 오류 결과가 스레트 call stack이 실제 오류가 난 스레드 call stack이 아니었다.

 

0:000> !analyze -v
...

FAULTING_IP:
+0
00000000`00000000 ??              ???

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

FAULTING_THREAD:  0000000000000174

DEFAULT_BUCKET_ID:  STATUS_BREAKPOINT

PROCESS_NAME:  abcde.exe

ERROR_CODE: (NTSTATUS) 0x80000003 - {

NTGLOBALFLAG:  400000

APPLICATION_VERIFIER_FLAGS:  0

PRIMARY_PROBLEM_CLASS:  STATUS_BREAKPOINT

BUGCHECK_STR:  APPLICATION_FAULT_STATUS_BREAKPOINT

LAST_CONTROL_TRANSFER:  from 000000007731904a to 000000007749754e

STACK_TEXT: 
00000000`0012fcd8 00000000`7731904a : 00000000`0000012c 00000000`ffffff00 00000000`00000000 00000000`00000000 : ntdll!NtWaitForSingleObject+0x1e
00000000`0012fce0 00000000`00404ac6 : 00000000`0000012c 00000000`ffffffff 00000000`00000000 00000000`0045bb40 : kernel32!WaitForSingleObjectEx+0x11e
00000000`0012fd90 000007fe`f2195047 : 00000000`00000000 00000000`00000000 00000000`00242cf0 00000e09`0000000a : aaaaa+0x4ac6
00000000`0012fe50 00000000`00432af1 : 00000000`00400000 00000000`00000000 00000000`00242cf0 00000000`0000000a : mfc42u!AfxWinMain+0x7b
00000000`0012fe90 00000000`7731b665 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : aaaaa+0x32af1
00000000`0012ff60 00000000`774031b1 : 00000000`00000000 00000000`004328c0 000007ff`fffd9000 00000000`00000000 : kernel32!BaseThreadInitThunk+0x1d
00000000`0012ff90 00000000`00000000 : 00000000`004328c0 000007ff`fffd9000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x25


STACK_COMMAND:  ~0s; .ecxr ; kb

FOLLOWUP_IP:
abcde+4ac6
00000000`00404ac6 4533c0          xor     r8d,r8d

SYMBOL_STACK_INDEX:  2

SYMBOL_NAME:  abcde+4ac6

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: abcde

IMAGE_NAME:  abcde.exe

DEBUG_FLR_IMAGE_TIMESTAMP:  48ecd1be

FAILURE_BUCKET_ID:  STATUS_BREAKPOINT_80000003_abcde.exe!Unknown

BUCKET_ID:  X64_APPLICATION_FAULT_STATUS_BREAKPOINT_abcde+4ac6

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

!analyze -v 를 이용해서 확인한 결과 덤프 발생 원인은 STATUS_BREAKPOINT 이다.
그러나 call stack에서는 정상적이고 STATUS_BREAKPOINT 와 관련이 없었다.

0:000> ~
.  0  Id: eec.174 Suspend: 1 Teb: 000007ff`fffde000 Unfrozen
   1  Id: eec.4e4 Suspend: 1 Teb: 000007ff`fffdc000 Unfrozen
   2  Id: eec.c6c Suspend: 1 Teb: 000007ff`fffda000 Unfrozen
   3  Id: eec.894 Suspend: 0 Teb: 000007ff`fffd5000 Unfrozen
   4  Id: eec.67c Suspend: 1 Teb: 000007ff`fffd3000 Unfrozen

크래쉬가 발생한 abcde에서는 5개의 스레드가 동작중에 있고 그 중에 4개의 스레드는 suspend 되어 있다.

0:000> ~3s
ntdll!DbgBreakPoint:
00000000`7749a600 cc              int     3

크래쉬가 발생할때 유일하게 동작중인 스레드(3)으로 context를 변경했다.

0:003> kvn
 # Child-SP          RetAddr           : Args to Child                                                           : Call Site
00 00000000`043f3f88 000007fe`ffb48bf5 : 00000000`043f7000 00000000`043f4000 00000000`00001000 00000000`043f7000 : ntdll!DbgBreakPoint
01 00000000`043f3f90 000007fe`ffb4972a : 00000000`00000002 000007fe`ffaf15f0 00000000`00000059 00000000`00000000 : msvcrt!VCrtDbgReportW+0x879
02 00000000`043fc050 000007fe`ffb49784 : 656c6c61`00000002 000007fe`ffaf15f0 00000000`00000059 00000000`00000000 : msvcrt!CrtDbgReportWV+0x36a
03 00000000`043ff0f0 000007fe`ffb16a02 : 00000000`00000002 000007fe`ffaf15f0 00000000`00000059 00000000`00000000 : msvcrt!CrtDbgReportW+0x30
04 00000000`043ff130 000007fe`ffb15c07 : 00000000`ffffffc4 00000000`00000103 00000000`00000002 00000000`043ff1d0 : msvcrt!chvalidator+0x3e
05 00000000`043ff170 000007fe`ffa76ec4 : 00000000`ffffffc4 00000000`003c0a74 00000000`00000000 00000000`00000000 : msvcrt!isalpha+0x1f
06 00000000`043ff1a0 000007fe`ffa7b51a : 00000000`043ff5e0 00000000`00000104 00000000`043ff360 00000000`043ff470 : shlwapi!PathCchCombineA+0x12c
07 00000000`043ff340 00000000`0268a380 : 00000000`043ff5e0 00000000`003c5d7c 00000000`0423d4bc 00000000`00000000 : shlwapi!PathCombineA+0x1a2
08 00000000`043ff5c0 00000000`026bd9a1 : 00000000`00000003 00000000`026d373f 00000000`00000016 00000000`0423d4ec : bbbbb!BBGetDBVersion+0x2630
09 00000000`043ffa00 00000000`0269726c : 00000000`043ffae0 00000000`00000000 00000000`003ceee8 00000000`026d45a0 : bbbbb!BBCheckScanResult+0x681d
0a 00000000`043ffa40 00000000`026b3f72 : 00000000`026e9330 000007ff`fffd5000 00000000`00000016 00000000`000000ec : bbbbb!BBGetLongPathName+0x1208
0b 00000000`043ffaa0 00000000`026b1b5b : 00000000`0423d4bc 00000000`00000000 00000000`0000002e 00000000`0000002d : bbbbb!BBRepairFile+0xa7a
0c 00000000`043ffe20 00000000`026b1c52 : 00000000`0420041c 00000000`7731cc3f 00000000`77754a80 00000000`00000001 : bbbbb!BBInitScan+0x1fb
0d 00000000`043ffe50 00000000`42c03c2f : 00000000`035b7b70 000007fe`ffbb3110 00000000`035bd5b0 000007fe`ffb463c5 : bbbbb!BBScan+0x7a
0e 00000000`043ffea0 00000000`42c05ab6 : 00000000`00000000 00000000`00000000 00000000`035bd5b0 000007fe`ffb5fcb4 : ccccc+0x3c2f
0f 00000000`043ffed0 000007fe`ffb600eb : 00000000`77754a80 00000000`00000001 000007fe`ffbb2600 00000000`00000001 : ccccc!SpywareSCN_SetLogData+0xca
10 00000000`043fff00 000007fe`ffb601b0 : 00000000`035bd5b0 00000000`00000000 00000000`00000000 00000000`00000000 : msvcrt!endthreadex+0x47
11 00000000`043fff30 00000000`7731b665 : 00000000`035bd5b0 00000000`00000000 00000000`00000000 00000000`00000000 : msvcrt!endthreadex+0x10c
12 00000000`043fff60 00000000`774031b1 : 00000000`00000000 000007fe`ffb60130 00000000`035bd5b0 00000000`00000000 : kernel32!BaseThreadInitThunk+0x1d
13 00000000`043fff90 00000000`00000000 : 000007fe`ffb60130 00000000`035bd5b0 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x25

변경한 스레드 call stack을 확인해 보니 마지막에 ntdll!DbgBreakPoint을 호출해서 자체적으로 덤프를 발생시켰다.

0:003> .frame 7
07 00000000`043ff340 00000000`0268a380 shlwapi!PathCombineA+0x1a2
0:003> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type ".hh dbgerr005" for details.

오류를 발생 시킨 모듈인(bbbbb.dll)에서 윈도우 API(shlwapi.dll)를 호출하는 frame으로 이동했다.
로컬 변수를 확인할려고 했으나 symbol이 맞지 않다고 나온다.ㅠㅠ
수동으로 분석을 해야한다.

msdn을 통해서 PathCombine API를 확인해 보니 아래와 같았다.
LPTSTR PathCombine(
    LPTSTR lpszDest,
    LPCTSTR lpszDir,
    LPCTSTR lpszFile
);

3개의 문자열 버퍼를  파라미터를 입력으로 받는다. 위 call stack 07 frame 에서도 3개의 아규먼트가
전달되고 있고 다른 하나는 NULL(00000000`00000000)이다.

0:003> dc 00000000`0423d4bc
00000000`0423d4bc  adbcfcc4 babdf1ba 38353120 30302d38  ........ 1588-00
00000000`0423d4cc  692e3532 6c006f63 726f7453 00000073  25.ico.lStors...
00000000`0423d4dc  00040003 04291c00 00000000 003cffb0  ......).......<.
00000000`0423d4ec  00000000 772f2f3a 712e7777 6b636975  ....://www.quick
00000000`0423d4fc  2e637673 6b2e6f63 726f0072 00000070  svc.co.kr.orp...
00000000`0423d50c  00040003 04291c00 00000000 003cffb0  ......).......<.
00000000`0423d51c  00000000 772f2f3a 712e7777 6b636975  ....://www.quick
00000000`0423d52c  2e637673 6b2e6f63 00000072 0000006d  svc.co.kr...m...
0:003> dc 00000000`003c5d7c
00000000`003c5d7c  555c3a43 73726573 6e68615c 5c62616c  C:\Users\abcde\
00000000`003c5d8c  75636f44 746e656d 00000073 00000000  Documents.......
00000000`003c5d9c  00000000 00000000 00000000 00000000  ................
00000000`003c5dac  00000000 00000000 00000000 00000000  ................
00000000`003c5dbc  00000000 00000000 00000000 00000000  ................
00000000`003c5dcc  00000000 00000000 00000000 00000000  ................
00000000`003c5ddc  00000000 00000000 00000000 00000000  ................
00000000`003c5dec  00000000 00000000 00000000 00000000  ................
0:003> dc 00000000`043ff5e0
00000000`043ff5e0  00000000 00000000 774237ea 00000000  .........7Bw....
00000000`043ff5f0  003c0a08 00000000 00000000 00000000  ..<.............
00000000`043ff600  043ff648 00000000 003c0a00 00000000  H.?.......<.....
00000000`043ff610  0000000a 00000000 00000001 00000000  ................
00000000`043ff620  00000001 00000000 00000001 00000000  ................
00000000`043ff630  003c0000 00000000 00000080 00000000  ..<.............
00000000`043ff640  0423d4d0 00000000 00000002 00000000  ..#.............
00000000`043ff650  00000000 00000000 774237ea 00000000  .........7Bw....

 

PathCombine API의 첫번째 파라미터가 잘못된것 같다. MSDN에 따르면 첫번째 파라미터는 [out]값으로
NULL 로 끝나는 스트링버퍼로 설정하고  크기는 MAX_PATH 로 해야 한다고 한다.
(lpszDest -> [out] Pointer to a buffer with the null-terminated string to hold the combined path string.
You should set the size of this buffer to MAX_PATH to ensure that it is large enough to hold the returned string.)
또한 세번째 파라미터이 파일 이름도 이상한것 같다.

 

bbbbb.dll모듈 개발 담당자가 PathCombine API에 넘기는 파라미터에 대해서 소스코드에서 확인을 해야 할것 같다.

Comments