주식회사하제소프트 (www.hajesoft.co.kr) 강사이봉석
과정소개 윈도우응용프로그램, 윈도우서비스프로그램, 윈도우디바이스드라이버를개발하는개발자들로하여금고급디버깅기술을제공하는 윈도우디버거 (WinDBG) 사용방법을익히게하여, 고급시스템프로그래머를양성하는데있습니다 윈도우디버거 (WinDBG) 를사용하는개발자는실무에서고급시스템프로그래머가갖추어야할중요한디버깅지식을습득함과동시에시간과비용을최대한아끼는프로그래밍습관과우수한결과물을만들어낼수있습니다
강사약력 본강사 ( 이봉석 ) 는기업교육 ( 삼성첨단기술센터, LG러닝센터, MDS테크놀러지 ) 과사설교육등에서 13년강사이력을가지고있으며, 현재주식회사하제소프트대표이사를역임하고있습니다. 저서로는, 윈도우디바이스드라이버, 실전윈도우디바이스드라이버, 고급개발자들만이알고있던디바이스드라이버구조와원리, 그리고제작노하우, 실전윈도우 CE 가이드, USB 너뭐니 가있습니다. 주식회사하제소프트는 17년간업체들이필요로하는윈도우디바이스드라이버, 리눅스디바이스드라이버그리고훰웨어를개발, 제공하는업체입니다.
과정진행목차 WinDBG 환경준비 Visual Studio 2015, WDK(Windows Driver Kit), WinDBG WinDBG 심볼설정 마이크로프로세서 Calling 규약 x86 CPU 에서 C 함수호출과어셈블리어연관성분석 x64 CPU 에서 C 함수호출과어셈블리어연관성분석 WinDBG 로칼디버깅 응용프로그램, 서비스프로그램디버깅 BSOD(BlueScreen Of Death) 커널덤프파일 커널덤프파일생성설정및덤프분석 WinDBG 원격디버깅 서비스프로그램, 커널디바이스드라이버디버깅 하드웨어와관련된 WinDBG 주요명령어 PCI, USB 버스를사용하는하드웨어를다룰때, 유용한 WinDBG 확장명령어를소개합니다 WinDBG 확장모듈 확장기능을제공하는모듈구현
5 강 WinDBG 원격디버깅 하제소프트 WinDBG 가설치된 PC 입니다 1394, USB, 시리얼, 이더넷을사용해서연결됩니다 디버깅할대상의 PC 입니다 Serial Debugger PC Ethernet Target PC(Debuggee PC) Ethernet 연결은윈도우 8 부터지원됩니다 Debugger PC 는윈도우드라이버를통해서통신합니다 Target PC 는윈도우드라이버를사용하지않고커널이직접하드웨어를접근합니다. OnBoard 하드웨어
주의!!!! * 가상머쉰을사용하는경우 HostIP 주소설정 하제소프트 Oracle Virtual Box 를사용해서가상머쉰을생성하고 Windows 10 을설치한뒤, 로컬컴퓨터와 WinDBG 를연결할때사용하는 BCDEDIT 명령어의 HostIP 주소는다음의주소를사용해야합니다
가상머쉰을사용해도되고, 실제 Target PC 를사용해도됩니다 ^^ 하제소프트 2.5 서비스원격디버깅 원격디버깅기능을사용해서 Win32 서비스프로그램을디버깅하도록합니다 예재는 3 강 3.4 절에서사용했던예재를수정합니다 서비스가처음시작될때부터트레이스 (Trace) 를해봅니다
2.5.1 서비스코드수정 서비스가처음시작될때부터트레이스 (Trace) 를하기위해서시작코드부분에 DebugBreak() 함수를호출하는문장을추가합니다. 이후다시서비스를빌드합니다 하제소프트
심볼파일은프로그램빌드디렉토리에만들어집니다 하제소프트 2.5.2 준비 서비스프로그램 (WinDbgTestService_Exam.exe) 과로더프로그램 (WinDbgTestServiceLoader_Exam.exe) 을함께 Target PC로복사합니다 실행모듈이실행되는 Target PC 에는프로그램소스가존재하지않기때문에, WinDBG 프로그램을동작하는호스트 PC 의심볼폴더로서비스프로그램심볼을복사해야합니다 (WinDbgTestService_Exam.pdb) 심볼파일을복사합니다
WinDBG 원격디버깅이진행중이어야합니다 하제소프트 2.5.3 프로그램실행 모든설정이준비되었다면, Target PC에준비된예재프로그램을실행합니다. 관리자권한으로실행해야합니다 (WinDbgTestServiceLoader_Exam.exe) 서비스프로그램이정상적으로실행되면, 미리추가한 DebugBreak() 함수호출코드때문에원격디버거로제어가넘어갑니다
프로그램실행 DebugBreak() 제어가 WinDBG 로넘어옴
먼저심볼설정이되어있어야합니다.reload /a 1 GO(F5 키 ) 5 4 BreakPoint(F9 키 ) 2 서비스프로그램소스파일을찾아서엽니다 3
2.5.4 트레이스 (Trace) 수정해야하는논리적인오류가들어있는위치의소스코드를확인하여, Break Point 를설정합니다 (F9키) 프로그램을재개 (F5 키 ) 합니다 요위치가적당하겠죠
Locals Window( 창 ) 1 2 지역변수의값을 0 => 1 로바꿔야합니다 GO(F5 키 ) 4 3 5 이와같이성공적으로수정된것을확인할수있습니다
2.6 커널드라이버 하제소프트 원격디버깅연습 윈도우가지원하는키보드클래스드라이버 (KBDCLASS) 가가지고있는심볼중에서키입력을처리하는함수의심볼을사용해서원격디버깅을연습합니다 마우스데이타를필터링하는예재 FilterExam 드라이버를작성하여, 커널디버깅을할때, 자주사용되는명령어들을연습합니다
2.6.1 커널드라이버소개 이강의는디바이스드라이버를제작하는강의가아니 기때문에, WinDBG 원격디버깅할때필요로하는정 도의지식만전달합니다
2.6.1.1 가상메모리와물리메모리 윈도우가사용하는주소공간은가상메모리입니다. 가상메모리공간은물리 메모리공간으로매핑됩니다 ( 그림은 32 비트머쉰의경우를가정합니다 ) 4KB Alignment 가상페이지 #0 12bit 예약 XXX 물리페이지 #3 가상페이지 #1 XXX 가상페이지 #2 Empty 물리페이지 #7 가상페이지 #3 XXX 물리페이지 #5 가상페이지 #4 Empty 가상페이지 #5 가상페이지 #6 Empty XXX 물리페이지 #0 가상페이지 #7 XXX 물리페이지 #1 가상메모리공간 PTE(PDE) Page Table Entry 물리메모리공간
가상주소 81518222 = 가상페이지 81518, 오프셋 222 로나뉩니다 가상페이지와매핑된물리페이지정보를확인합니다 하제소프트 명령어!pte Extension Command 가상주소와연결된물리페이지정보를출력합니다 가상주소!pte 81518222 = 81518 가상페이지 Page Table Entry(PTE) 정보 12bit 예약 = 2918 물리페이지 가상주소 81518XXX = 물리주소 2918XXX
가상메모리를데이터로확인해보겠습니다 하제소프트 명령어 db 명령어!db Command 가상메모리를 Data Byte 단위로보기 (dw, dd, dq 각각 2, 4, 8 바이트보기 ) Extension Command 물리메모리를 Data Byte 단위로보기 (dw, dd, dq 각각 2, 4, 8 바이트보기 ) 가상주소 내용이같습니다 물리주소
2.6.1.2 하드웨어트리 윈도우는동작중인하드웨어를루트노드 (Root Node) 로부터자식노드까지 트리형태의자료구조 ( 하드웨어트리 ) 를사용해서관리합니다루트노드 HTREE\ROOT\0 ROOT\volmgr\0000 ROOT\ACPI_HAL\0000 ACPI\PNP0A03\0 ACPI_HAL\PNP0C08\0
하드웨어트리를확인합니다 명령어!devnode Extension Command 하드웨어트리를보여줍니다!devnode 0 1 모 1 부모 1 자식 1 부모 1 자식 1 자식 1 부모 1 자식 1 자식 2 부모 1 자식 2 부모 1 자식 3 부모 1 자식 4
예를들어, Disk 서비스가사용하는디바이스노드를선택해보았습니다 하제소프트 Disk 서비스가사용하는디바이스노드를찾습니다!devnode 0 1 disk 같은내용입니다 선택된디바이스노드의 Main Service(Function) 는 Disk 입니다
2.6.1.3 디바이스스택 디바이스스택은보다적극적인드라이버의연결관계를보여줍니다 하나의디바이스노드는하나의디바이스스택을가리킵니다 ( 인스턴스 Path) HTREE\ROOT\0 루트노드 ROOT\volmgr\0000 ROOT\ACPI_HAL\0000 ACPI\PNP0A03\0 Filter 는선택적요소입니다 하나의디바이스스택 Filter Function Filter Physical
Disk 서비스가 Function 역할을하는디바이스노드의디바이스스택을확인합니다 하제소프트 디바이스스택을확인합니다 명령어 Extension Command!devstack 디바이스스택을보여줍니다 PDO(Physical Device Object) 주소값을사용합니다 디바이스스택, 그리고관련된드라이버들 Filter(\Driver\partmgr) Function(\Driver\disk) Physical
2.6.1.4 드라이버와디바이스스택 드라이버는 서비스 형식으로관리됩니다 struct _DRIVER_OBJECT DriverName( \Driver\Example ) Service (Example) Service Manager 가상메모리 파일
드라이버는 _DRIVER_OBJECT, 디바이스는 _DEVICE_OBJECT 가추상화합니다그림처럼각각의자료구조는서로를가리키도록설계됩니다. 하제소프트 하나의드라이버는최소한하나의디바이스를관리합니다 struct _DRIVER_OBJECT DriverName( \Driver\Disk ) DeviceObject struct _DEVICE_OBJECT DriverObject NextDevice AttachedDevice
하나의디바이스스택은둘이상의디바이스로구성됩니다 struct _DEVICE_OBJECT DriverObject NextDevice AttachedDevice(0) 디바이스스택 (_DEVICE_OBJECT) struct _DEVICE_OBJECT DriverObject NextDevice AttachedDevice(895f9ba8) Physical Device Object(PDO) 각각의디바이스는 AttachedDevice 필드를 struct _DEVICE_OBJECT DriverObject NextDevice AttachedDevice(899165c8) 통해서상위디바이스에대한주소를가지고 있습니다
외부에서전달되는모든명령은디바이스스택의최상위디바이스로전달됩니다. 이어서최상위 디바이스의의지에따라서다른계층의디바이스로명령이전달됩니다 _DEVICE_OBJECT 응용프로그램 디바이스스택 Top Driver Middle Driver Lower Driver Create 명령처리기 Create 명령처리기 Create 명령처리기 IO Subsystem Kernel Close 명령처리기 Read 명령처리기 Close 명령처리기 Read 명령처리기 Close 명령처리기 Read 명령처리기 Write 명령처리기 Write 명령처리기 Write 명령처리기 주소 주소 주소 주소 주소 주소 MajorFunction 배열 (Dispatch Routines)
2.6.1.5 드라이버명령처리기 디스크 (Disk) 드라이버의명령처리기를확인합니다 struct _DRIVER_OBJECT MajorFunction[ ] Disk MajorFunction[ ] Create 명령처리기주소 Close 명령처리기주소 Read 명령처리기주소 Write 명령처리기주소 Internal Device Control 명령처리기주소
디스크 (Disk) 드라이버의명령처리기를확인합니다 하제소프트 kd>!devnode 0 1 disk DevNode 0x8bf71ca8 for PDO 0x8bf6f030 ServiceName is "disk kd>!devstack 0x8bf6f030!DevObj!DrvObj!DevExt ObjectName 8c54b590 \Driver\partmgr 8c54b648 8c54b980 \Driver\disk 8c54ba38 DR0 8bf6f030 \Driver\storahci 8bf6f0e8 00000018 ServiceName is "disk" disk 드라이버가사용되는디바이스노드검색 disk 드라이버의디바이스 (_DEVICE_OBJECT) 찾기 kd> dt _DEVICE_OBJECT 8c54b980 ntdll!_device_object +0x000 Type : 0n3 +0x002 Size : 0x548 +0x004 ReferenceCount : 0n0 +0x008 DriverObject : 0x8bff87d8 _DRIVER_OBJECT +0x00c NextDevice : (null) +0x010 AttachedDevice : 0x8c54b590 _DEVICE_OBJECT. kd> dt _DRIVER_OBJECT 0x8bff87d8 ntdll!_driver_object +0x000 Type : 0n4 +0x002 Size : 0n168 +0x004 DeviceObject : 0x8c54b980 _DEVICE_OBJECT +0x01c DriverName : _UNICODE_STRING "\Driver\disk" +0x038 MajorFunction : [28] 0x886e3370 long CLASSPNP!ClassGlobalDispatch+0 kd> dd0x8bff87d8+0x38 8bff8810 886e3370 812f13ca 886e3370 886e3370 8bff8820 886e3370 812f13ca 812f13ca 812f13ca MajorFunction[ ] 배열 disk 드라이버 (_DRIVER_OBJECT) 찾기 disk 드라이버 (_DRIVER_OBJECT) 내용확인 MajorFunction[ ] 배열내에명령처리기 주소중하나를선정해서 Break Point 를 설정해봅니다 IRP_MJ_READ 명령처리기의주소입니다 (0x886e3370)
디스크 (Disk) 드라이버의명령처리기 (IRP_MJ_READ) 에 Break Point 를설정합니다 IRP_MJ_READ 명령처리기의주소입니다 (0x886e3370) 명령어 u Command Disassembly 코드를보여줍니다 GO(F5 키 ) u @eip EIP 레지스터가가리키는주소의내용부터 Disassembly 코드를보여줍니다 임의의디스크접근행위는 Break Point 로제어가넘어갑니다
콜스택을확인합니다 중단점을해제하고마무리합니다 현재콜스택을확인합니다 의미있는상위드라이버
주식회사하제소프트 (www.hajesoft.co.kr) 강사이봉석