400 likes | 415 Views
WinDbg 를 이용한 커널 드라이버 디버깅 2. Live Debugging. KOREA SYSTEM PROGRAMMER 1 st System Kernel Conference 2003.11.8. 목차. Debugger 와 Debuggee Symbol Driver Verifier 소스레벨 디버깅 Deadlock Debugging. Debugger 와 Debuggee. Debugger – WinDbg 를 수행하는 PC(HOST) Debuggee – Driver 를 수행하는 PC(TARGET).
E N D
WinDbg를 이용한 커널 드라이버 디버깅2. Live Debugging KOREA SYSTEM PROGRAMMER 1st System Kernel Conference 2003.11.8
목차 • Debugger 와 Debuggee • Symbol • Driver Verifier • 소스레벨 디버깅 • Deadlock Debugging
Debugger 와 Debuggee • Debugger – WinDbg를 수행하는 PC(HOST) • Debuggee – Driver를 수행하는 PC(TARGET)
Debugger 와 Debuggee • 디버거와 디버기의 연결 준비 • 시리얼 케이블( 널모뎀 ) – 9 pin to 9 pin • HOST notebook - USB to Serial cable • HOST – WinDbg • Debugger OS: Windows NT4, 2000, XP, 2003 Server • TARGET – NT OS • Debuggee OS: Windows NT4, 2000, XP, 2003 Server • Debuggee Platform: x86, IA-64, AMD64
Debugger 와 Debuggee • Step 0. 시리얼 케이블 연결 • Debugger(HOST) – COM1 • Debuggee(TARGET) – COM2
Debugger 와 Debuggee • Step 1. Debuggee 설정과 부팅 • OS를 디버그 모드로 부팅해야 한다 • C:\boot.ini 수정 Hidden, ReadOnly 속성제거 [boot loader] timeout=30 default=multi(0)disk(0)rdisk(0)partition(1)\WINNT [operating systems] multi(0)disk(0)rdisk(0)partition(1)\WINNT="Microsoft Windows XP Professional" /fastdetect
Debugger 와 Debuggee [operating systems] multi(0)disk(0)rdisk(0)partition(1)\WINNT="Microsoft Windows XP Professional" /fastdetect multi(0)disk(0)rdisk(0)partition(1)\WINNT="Microsoft Windows XP Professional" /fastdetect /debug /debugport=com2 /baudrate=115200 • /debug – OS를 디버그 모드로 설정 • /debugport –시리얼포트 지정(디폴트는 com2) • /baudrate – 9600, 19200, 38400, 57600, 115200 중 선택 • 부트메뉴 시작할 운영 체제를 선택하십시오: Windows XP Professional Windows XP Professional [디버그 가능]
Debugger 와 Debuggee • Step 2. 디버거(HOST) PC에서 WinDbg 실행 • File 메뉴에서 Kernel Debug …메뉴 선택
Debugger 와 Debuggee • Step 3. WinDbg와 Debuggee 연결 • WinDbg는 연결 대기 상태에서 • Debuggee가 디버그 모드로 부팅하면 WinDbg와 연결되어 디버그 메시지를 뿌리기 시작 • Debuggee가 먼저 디버그 모드로 부팅되어 있었다면 Ctrl-Break 로 연결
Debugger 와 Debuggee • 부팅하면서 연결된 화면
Symbol • Symbol이 없다면… kernel32+0x102A84 • Symbol이 있다면… kernel32!CreateFileA kernel32!CreateFileW … ntdll!NtCreateFile ntdll!NtCreateProcess … nt!NtCreateFile nt!ZwCreateFile (nt = ntoskrnl.exe) …
Symbol • WinDbg로 OS를 디버깅하기 위한 기본요소 • OS 심볼 파일 ( NT4, 2000, XP, … ) • 링커가 exe, dll, sys 등과 함께 심볼 생성 • .dbg files, .pdb files • ntoskrnl.exe – ntoskrnl.pdb (checked build) • ntoskrnl.exe – ntoskrnl.pdb (free build) • ntoskrnl.exe – ntoskrnl.pdb (NT4) • ntoskrnl.exe – ntoskrnl.pdb (Win2K, sp1, sp?) • ntoskrnl.exe – ntoskrnl.pdb (XP, sp1)
Symbol • 심볼에 들어있는 정보 • 함수이름, 주소, (인자) • (전역변수, 지역변수) • (소스라인, 파일패스) • 심볼 다운로드 • http://www.microsoft.com/ddk/debugging/symbols.asp • NT4 sp6, sp6a ~ XP sp1 free build • OS에 default로 들어가는 모든 모듈의 심볼 포함 • Debuggee OS 에 맞춰서 사용
Symbol • WinDbg에 Debuggee OS 심볼 설정 • Step 1. C:\ossymbol\2ksp3에 심볼 저장 • Step 2. WinDbg Command에서 • kd>.sympath c:\ossymbol\2ksp3 • Symbol search path is: c:\ossymbol\2ksp3 • File - Symbol • Search Path
Symbol • WebSymbol • Symbol Search Path에 MS 웹심볼 사이트지정 • Debuggee OS 구분없이 사용 가능 • 모듈 CheckSum 비교하여 일치하는 심볼 다운로드 • Lazy symbol loading ( download ) • 서버의 공유폴더에 다운로드하여 공유가능 • WebSymbol 설정 • kd>.sympath srv*c:\websymbol*http:// • msdl.microsoft.com/download/symbols • Symbol search path is: SRV*c:\websymbol* • http://msdl.microsoft.com/download/symbols
Symbol • WebSymbol 설정 • kd> .symfix c:\websymbol • Symbol search path is: SRV*c:\websymbol* • http://msdl.microsoft.com/download/symbols • File – Symbol • Search Path
Symbol • Public symbol 과 Private symbol • Public symbol – MS가 외부에 공개하는 심볼 • 함수이름, 주소 표시 • Private symbol – MS가 내부에서 사용하는 심볼 • 전역변수, 지역변수, 소스라인, 파일패스까지 표시 • 소스 연동 가능
Symbol • 심볼생성 • WinDbg로 우리의 모듈을 디버깅하려면 • 우리 모듈의 심볼파일이 필요 • Checked Build ( debug build ) • drvname.sys, drvname.pdb 생성 • drvname.pdb는 private symbol • Full 디버그 정보 포함 • Free Build ( release build ) • drvname.sys, drvname.pdb 생성 • 2K, XP DDK에서는 Free도 디폴트로 pdb 생성
Symbol • Free build에서 Private symbol 생성 • Free build sys(exe)를 소스레벨 디버깅 가능 • 릴리즈된 모듈에 대해서 소스레벨 디버깅 가능 • Compiler Option ( NT4 DDK ) • -Zi • Linker Option ( NT4 DDK ) • /DEBUG /DEBUGTYPE=windbg • Build Utility Macro ( NT4 DDK ) • Set NTDEBUGTYPE=windbg • Set USE_PDB=1
Driver Verifier • 개발검증이란?
Driver Verifier • 드라이버 검증을 위한 도구 • Driver Verifier ( Windows 2000, XP or later ) • Bounds Checker for Driver Edition • Checked Build OS from MSDN • HCT ( Hardware Compatibility Test ) • Driver Verifier Option • Special Pool – Memory 앞뒤에 Guard 영역 체크 • Force IRQL checking – IRQL 문제 확인 • Low resource simulation –가상 리소스 부족 • Pool tracking – Memory leak 체크 • I/O verification – IRP 핸들링 체크
Driver Verifier • Driver Verifier 실행 • 실행창에서 verifier.exe ENTER • 도스창에서 verifier.exe ENTER
Driver Verifier • Io Verification Example *********************************************************************** * THIS VALIDATION BUG IS FATAL AND WILL CAUSE THE VERIFIER TO HALT * * WINDOWS (BUGCHECK) WHEN THE MACHINE IS NOT UNDER A KERNEL DEBUGGER! * *********************************************************************** WDM DRIVER ERROR: [MyDrv.sys @ 0xF9D5C900] An IRP dispatch handler (F9D5C900 ) has returned a status that is inconsistent with the Irp's IoStatus.Status field. ( Irp = B23CEF68 - Irp->IoStatus.Status = 00000000 - returned = 00000102 ) IRP_MJ_DEVICE_CONTROL [ DevObj=00000000, FileObject=80DFFC50, Parameters=00000000 00000000 00220018 00000000 ] http://www.microsoft.com/hwtest/bc/redir.asp?os=5.1.2600&major=0xc9&minor=0x224&lang=0x9 Break, Ignore, Zap, Remove, Disable all (bizrd)? b Breaking in... (press g<enter> to return to assert menu) nt!DbgBreakPoint: 80517a98 cc int 3 kd> u 0xF9D5C900 MyDrv!MyDrvDeviceControl [d:\project\test\mydrv\mydrv.c @ 238]: f9d5c900 55 push ebp
Driver Verifier NTSTATUS MyDrvDeviceControl( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { // LINE 238 … switch (ulIoControlCode) { case MYDRV_IOCTL_IOVERIFY: ntStatus = STATUS_TIMEOUT; pIrp -> IoStatus.Status = STATUS_SUCCESS; pIrp -> IoStatus.Information = 0; break; … } IoCompleteRequest(pIrp, IO_NO_INCREMENT); return ntStatus; }
소스레벨 디버깅 • 심볼패스 지정 • C:\xpddk\src\fastfat\fastfat.pdb 폴더직접지정 • C:\mysymbols 폴더로 심볼파일들 복사 • 소스패스 지정 • .srcpath c:\xpddk\src\fastfat
소스레벨 디버깅 • IFS Kit 의 fastfat.sys를 checked build
Deadlock Debugging • Hang 과 Deadlock • 어떤 쓰레드가? 어떤 동기화 객체를?
Deadlock Debugging • Hang • 프로세스 응답없음 • 쓰레드가 대기상태인 경우 • 쓰레드가 무한루프인 경우 • Hang example • 어떤 쓰레드가 어떤 이벤트를 기다림 • 버그에 의해 그 이벤트가 시그널되지 않음 Thread B KeSetEvent(kEvent) Thread A KeWaitForSingleObject(kEvent)
Deadlock Debugging • 대기중인 쓰레드 찾기 ( MyApp.exe & MyDrv.sys ) • kd> !process 0 7 • PROCESS 80ef0030 SessionId: 0 Cid: 07b8 Peb: 7ffdf000 ParentCid: 04a0 • DirBase: 020a6000 ObjectTable: e1138520 HandleCount: 328. • Image: wuauclt.exe • … • THREAD 80ef0da8 Cid 7b8.778 Teb: 7ffde000 Win32Thread: e1921100 WAIT: (WrUserRequest) • f2597ccc 804f82e4 80ef0e18 80ef0da8 804f24b2 nt!KiSwapContext+0x2e • f2597cd8 804f24b2 000024ff e1921100 00000000 nt!KiSwapThread+0x44 • … • PROCESS 81189910 SessionId: 0 Cid: 011c Peb: 7ffdf000 ParentCid: 01cc • DirBase: 07426000 ObjectTable: e1dde380 HandleCount: 373. • Image: msnmsgr.exe • 자신의 프로세스를 먼저 살펴보기 • 버그의 95% - 개발중인 자신의 모듈 • 버그의 4% - 자신의 모듈과 다른 모듈 충돌 • 버그의 1% - OS 버그
Deadlock Debugging PROCESS 80dddda8 SessionId: 0 Cid: 06cc Peb: 7ffdf000 ParentCid: 01cc DirBase: 0b26c000 ObjectTable: e151e3b0 HandleCount: 56. Image: MyApp.exe … THREAD 80de8610 Cid 6cc.2b0 Teb: 7ffde000 Win32Thread: e1500638 WAIT: (Executive) KernelMode Non-Alertable … ChildEBP RetAddr Args to Child f23dfb60 804f82e4 80de8680 80de8610 804f24b2 nt!KiSwapContext+0x2e f23dfb6c 804f24b2 00000000 f9d5c4c0 a9580f00 nt!KiSwapThread+0x44 f23dfb94 80627f2c 00000000 00000000 00000000 nt!KeWaitForSingleObject+0x1c0 f23dfbbc f9d5c9a3 f9d5c4c0 00000000 00000000 nt!VerifierKeWaitForSingleObject+0x54 f23dfc10 804e8185 80f56318 a9580f68 8069f524 MyDrv!MyDrvDeviceControl+0xa3 (CONV: stdcall) [d:\project\test\mydrv\mydrv.c @ 266] f23dfc20 80626d10 80de8820 8069f2f0 a9580f68 nt!IopfCallDriver+0x31 kd> .thread 80de8610 Implicit thread is now 80de8610 *** Call Stack 창의 내용이 위와 같이 바뀜
Deadlock Debugging • 대기중인 대상 찾기 • case MYDRV_IOCTL_EVENT1: • KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL ); • pIrp -> IoStatus.Status = STATUS_SUCCESS; // LINE 266 • pIrp -> IoStatus.Information = 0; • break; • case MYDRV_IOCTL_EVENT2: • KeSetEvent( &Event, IO_NO_INCREMENT, FALSE ); • pIrp -> IoStatus.Status = STATUS_SUCCESS; • pIrp -> IoStatus.Information = 0; • break;
Deadlock Debugging • Deadlock • 프로세스 응답없음 • 시스템 락킹 • Deadlock Example • 쓰레드 두개가 두 개의 락을 소유 시도 Thread 1 Acquire Lock A … Acquire Lock B Release Lock A Thread 2 Acquire Lock B … Acquire Lock A Release Lock B
Deadlock Debugging • 대기중인 쓰레드 찾기( MyApp.exe & MyDrv.sys ) kd> !process 0 0 MyApp.exe PROCESS 81570b90 SessionId: 0 Cid: 01e4 Peb: 7ffdf000 ParentCid: 01e8 DirBase: 0bc9c000 ObjectTable: e20a9d60 HandleCount: 44. Image: MyApp.exe kd> !process 81570b90 PROCESS 81570b90 SessionId: 0 Cid: 01e4 Peb: 7ffdf000 ParentCid: 01e8 DirBase: 0bc9c000 ObjectTable: e20a9d60 HandleCount: 44. Image: MyApp.exe VadRoot 813898a8 Vads 58 Clone 0 Private 175. Modified 81. Locked 0. ... THREAD 8158c9f8 Cid 1e4.3b0 Teb: 7ffde000 Win32Thread: e1a53660 WAIT: (Executive) KernelMode Non-Alertable f9fdf480 Mutant - owning thread 81116030 IRP List: 81397b90: (0006,0094) Flags: 00000000 Mdl: 00000000 Not impersonating ...
Deadlock Debugging ChildEBP RetAddr f2208bac 804f82e4 nt!KiSwapContext+0x2e (FPO: [EBP 0xf2208be0] [0,0,4]) f2208bb8 804f24b2 nt!KiSwapThread+0x44 (FPO: [0,0,2]) f2208be0 f9fdf9e4 nt!KeWaitForSingleObject+0x1c0 (FPO: [Non-Fpo]) f2208c34 804e8185 MyDrv!MyDrvDeviceControl+0xe4 (FPO: [Non-Fpo]) (CONV: stdcall) [d:\project\test\mydrv\mydrv.c @ 272] f2208c44 8055887c nt!IopfCallDriver+0x31 (FPO: [0,0,1]) f2208c58 805595a7 nt!IopSynchronousServiceTail+0x5e (FPO: [Non-Fpo]) f2208d00 80552468 nt!IopXxxControlFile+0x5a5 f2208d34 8052a421 nt!NtDeviceIoControlFile+0x28 (FPO: [Non-Fpo]) kd> .thread 8158c9f8 Implicit thread is now 8158c9f8 *** Call Stack 창의 내용이 위와 같이 바뀜
Deadlock Debugging case MYDRV_IOCTL_MUTEX1: KeWaitForSingleObject( &MutexA, Executive, KernelMode, FALSE, NULL ); interval1.QuadPart = -30000000; KeDelayExecutionThread( KernelMode, FALSE, &interval1 ); KeWaitForSingleObject( &MutexB, Executive, KernelMode, FALSE, NULL ); KeReleaseMutex( &MutexA, FALSE ); // LINE 272 KeReleaseMutex( &MutexB, FALSE ); kd> dd mydrv!MutexB f9fdf480 00080002 00000000 8158ca68 8158ca68 f9fdf490 81116040 81116040 81116030 00000100 kd> dt KMUTEX f9fdf480 +0x000 Header : _DISPATCHER_HEADER +0x010 MutantListEntry : _LIST_ENTRY [ 0x81116040 - 0x81116040 ] +0x018 OwnerThread : 0x81116030 +0x01c Abandoned : 0 '' +0x01d ApcDisable : 0x1 ''
Deadlock Debugging kd> !thread 0x81116030 THREAD 81116030 Cid 428.60c Teb: 7ffde000 Win32Thread: e20f6cb8 WAIT: (Executive) KernelMode Non-Alertable f9fdf4a0 Mutant - owning thread 8158c9f8 IRP List: 81396c10: (0006,0094) Flags: 00000000 Mdl: 00000000 ... ChildEBP RetAddr Args to Child f26ddbac 804f82e4 811160a0 81116030 804f24b2 nt!KiSwapContext+0x2e f26ddbb8 804f24b2 81116240 817b6bd8 81396c10 nt!KiSwapThread+0x44 f26ddbe0 f9fdfa59 00000000 00000000 00000000 nt!KeWaitForSingleObject+0x1c0 f26ddc34 804e8185 8120ec98 81396c10 8069f2f0 MyDrv!MyDrvDeviceControl+0x159 (CONV: stdcall) [d:\project\test\mydrv\mydrv.c @ 287] f26ddc44 8055887c 81412ac0 81396c80 81396c10 nt!IopfCallDriver+0x31 f26ddc58 805595a7 8120ec98 81396c10 81412ac0 nt!IopSynchronousServiceTail+0x5e f26ddd00 80552468 000000a0 00000000 00000000 nt!IopXxxControlFile+0x5a5 f26ddd34 8052a421 000000a0 00000000 00000000 nt!NtDeviceIoControlFile+0x28 kd> .thread 81116030 Implicit thread is now 81116030
Deadlock Debugging case MYDRV_IOCTL_MUTEX2: KeWaitForSingleObject( &MutexB, Executive, KernelMode, FALSE, NULL ); interval2.QuadPart = -30000000; KeDelayExecutionThread( KernelMode, FALSE, &interval2 ); KeWaitForSingleObject( &MutexA, Executive, KernelMode, FALSE, NULL ); KeReleaseMutex( &MutexB, FALSE ); // LINE 287 KeReleaseMutex( &MutexA, FALSE ); kd> dd mydrv!MutexA f9fdf4a0 00080002 00000000 811160a0 811160a0 f9fdf4b0 8158ca08 8158ca08 8158c9f8 00000100 kd> dt KMUTEX f9fdf4a0 +0x000 Header : _DISPATCHER_HEADER +0x010 MutantListEntry : _LIST_ENTRY [ 0x8158ca08 - 0x8158ca08 ] +0x018 OwnerThread : 0x8158c9f8 +0x01c Abandoned : 0 '' +0x01d ApcDisable : 0x1 ''