커널 디버거(WinDbg) 설치하기

준비물 : WinDbg v6.3.17.0
PC 두 대 + 널 모뎀 (시리얼) 케이블 또는
PC 한 대 + VMware

참고 : 김창훈님의 「VMWARE를 통한 커널 디버그 설정방법」

▶ 개요

커널 디버깅을 하기위해 먼저 커널 디버거를 설치해 보도록 합니다. 소트프 아이스(이하 소아)라고 하는 걸출한(?) 커널 디버거도 있으나 여기서는 마이크로소프트에서 무료로 제공하는 WinDbg(영어로 ‘윈드백’이라고 발음한다고 함)를 사용하겠습니다. 소아아는 다르게 WinDbg은 두 대의 시스템을 필요로 한다고 되어 있으나, 최근(?) PC의 성능이 비약적으로 발전함에 따라 VMware와 같은 프로그램을 이용하여 소프트웨어의 힘만으로 한 대의 PC 안에 또 하나의 가상의 PC를 구동할 수 있게 되었습니다. 이에 따라 시스템이 두 대가 필요하다는 전제는 무너져 버렸지요. 저 같이 가난한 학생들에게는 희소식이 아닐 수 없습니당(사실, 전 PC가 두 대 있습니다. -_-;; 메인 PC는 함부로 다룰 수가 없어서... 세컨 PC는 죽어나죠~ ^^;). 그럼 이제 본격적으로 설치해 보도록 합시다. PC 두 대를 이용하는 것과 PC 한 대를 이용하는 것으로 나눠서 설명할 텐데, 먼저 PC 두 대를 이용하는 것입니다. 앗, 먼저 한 가지 용어에 대한 정의가 있어야 겠군요. 디버깅을 당하는 PC를 타겟 PC 또는 디버기(debuggee)라고 하고 디버깅을 행하는 PC를 호스트 PC 또는 디버거(debugger)라고 합니다.

▶ 방법 ① PC 두 대 + 널 모뎀 (시리얼) 케이블

WinDbg 설명서에도 나와있는 지극히 정상적인 방법으로 널 모뎀 케이블이 추가로 필요합니다. 5m짜리를 2-3천원 줬던 것 같습니다. 일단 두 대의 PC를 널 모뎀 케이블로 연결 합니다. 두 PC의 시리얼(COM) 포트 연결이 제대로 되었는지는 다음과 같이 확인해 볼 수 있습니다. “시작 -> 프로그램 -> 보조 프로그램 -> 통신 -> 하이퍼터미널”을 실행합니다. 그러면 다음 화면을 보실 수 있습니다.

그림 1

그러면 위와 같이 이름에 ‘Test’라고 입력하고 확인을 합니다.

그림 2

연결에 사용할 모뎀을 선택하는 데 자신이 연결한 COM 포트 번호를 지정합니다.

그림 3

다른 것은 손 댈 것이 없고 ‘비트/초’를 적당한 속도(최고 115200bps, 저는 57600으로 해야 되더군요. ㅜㅜ)로 설정합니다. 이 속도는 호스트와 타겟 모두 같아야 합니다. 그러면 이와 같이 하이퍼터미널 설정을 마치면 다음과 같은 화면이 나타납니다.

그림 4

호스트와 타겟 모두 이렇게 하이퍼터미널을 띄워 놓고 호스트 또는 타겟에서 키보드로 문자를 입력해 봅니다. 그러면 다음과 같이 상대편 PC의 화면에 그대로 나타날 것입니다.

그림 5

만약, 그대로 나타나지 않는 다면 문제가 있는 것이므로 먼저 이것부터 해결해야 WinDbg를 설치하든지 말든지 하겠지요~? ^^; 이제 COM 포트 연결은 제대로 되었으니 실제로 셋팅을 해볼까요~ 먼저 호스트 PC에서의 설정입니다. 먼저 WinDbg를 설치한 후 실행을 시킵니다. WinDbg 화면이 뜨면 먼저 심볼 설정부터 하도록 합니다. “심볼이 무엇이냐?”라고 물으시면 저도 모릅니다. -_- 다면 알고 있는 것이라면, 디버그 모드로 링크를 하면 xxx.pdb 파일이 생성되는 데 이것이 심볼 파일이라는 것. 그리고 이 심볼 파일 덕분에 우리는 디버깅시, 내가 원하는 함수에 브레이크포인트(이하 브포)를 걸 때, bp 00401234가 아닌 bp MyFunc이 가능해지고, 내가 살펴보고자 하는 변수를 볼 때, dd 00402345가 아닌 dd MyVal이 가능해진다는 정도. ㅡ,ㅡ 아무튼 하는게 좋으니까 하도록 합시다. ^^;;; “File -> Symbol File Path ..."를 선택합니다.

그림 6

“Symbol path”를 위와 같이 입력합니다. 여기서의 심볼 설정은 우리가 살펴보고자 하는 어플리케이션의 심볼이 아니라 운영 체제 자체, 즉 Windows의 심볼입니다. 예전에는 Windows를 판매할 때 리소스 킷(?)과 같은 CD에 그 운영체제의 심볼 파일을 넣어서 배포했다고 하는군요. 하지만 요즘은 서비스 팩이나 핫 픽스 등으로 인해 심볼 파일도 바뀌어야 하는데 그때그때마다 타겟 PC의 Windows 버전 상태를 체크해서 심볼 파일을 설치하는 것이 어렵기 때문에 마이크로소프트에서는 심볼 서버라는 것을 운영하고 있습니다. 설정은 다음과 같습니다.

srv*C:\WebSymbols*http://msdl.microsoft.com/download/symbols

이렇게 설정을 하면 WinDbg는 먼저 C:\WebSymbols 에 타겟 PC의 운영 체제에 맞는 심볼 파일이 있는지 검사하고 없으면 심볼 서버에서 다운받아 C:\WebSymbols 에 보관해 놓습니다.

※ 주의 : C:\WebSymbols 디렉토리는 사용자가 직접 만들어 놓아야 합니다. WinDbg가 만들어 주지 않습니다. 이것땜에 한참 삽질했죠. ㅜㅜ
---> 최근 버전에서는 자동으로 만들어 주는 것 같습니다.

심볼 설정을 마쳤으면 "File -> Kernel Debug..."를 선택합니다.

그림 7

통신 포트와 속도를 알맞게 기입한 후 확인을 누릅니다.

그림 8

그러면 위와 같이 타겟 PC가 연결되기를 기다립니다. 이렇게 호스트 PC를 애타게 기다리게 해놓고 이제 타겟 PC의 설정을 해보도록 합시다. 호스트 PC의 설정도 간단하지만 타겟 PC는 더더욱 간단합니다.

그림 9

C 드라이브 루트 디렉토리에 있는 boot.ini 파일을 수정해야 하는데, 위 그림의 6번 줄과 같이 한 줄을 추가한 후 시스템을 재부팅하면 끝입니다. 재부팅을 하게 되면 운영 체제를 선택하는 메뉴가 나올 건데 거기서 아래의 우리가 추가한 메뉴를 선택하면 되는 것입니다. 선택을 한 후 운영 체제를 시작하면 눈 빠지게 기다리던 호스트에서 반응을 보입니다.

그림 10

아래 상태 표시줄에는 연결 안되었다고 나오지만 실제로는 연결 된 것입니다. 그럼 이제 타겟 PC에 브레이크를 걸어 볼까요? Ctrl+Break 또는 "Debug -> Break"를 선택하시면 다음과 같이 브레이크가 걸립니다.

그림 11

역시 커널 디버가 답게 타겟 PC의 시스템 자체가 멈추어 버립니다. 브레이크가 걸린 후 심볼을 로딩하는 것이 보이는 군요. 왜 두 번이나 하지? -_-;; 아무튼, 이제 WinDbg 설치는 끝났습니다. 이제 VMware를 이용한 방법을 알아볼까요~

▶ 방법 ② PC 한 대 + VMware

WinDbg은 “named pipe”라는 것을 이용하여 가상 머신과 통신할 수 있습니다. 먼저 VMware 설정을 해봅시다. 우선 가상 머신에 Windows를 설치해야겠죠. “Virtual Machine Settings -> Hardware” 탭을 보면 다음과 같이 기본으로는 시리얼 포트가 설정되어 있지 않습니다.

그림 12

시리얼 포트를 추가하기 위해 [Add]를 클릭합니다.

그림 13

여기서 "Serial Port"를 선택하고 [다음]을 클릭합니다.

그림 14

"Output to named pipe"를 선택하고 [다음]을 클릭.

그림 15

여기서는 "Named pipe"의 이름만 자신이 원하는 것으로 바꿔줍니다. 여기서는 "vm_com"으로 하였습니다. [마침]을 클릭하면 다음과 같이 시리얼 포트가 설정된 것을 확인할 수 있습니다.

그림 16

"I/O mode -> Yield CPU on poll"이 무엇을 의미하는지는 잘 모르겠군요. 참고 글에 체크가 되어 있길래 저도 그렇게 했습니다. ^^;; 이제 VMware의 외부적인 설정은 끝났고 이제 가상 머신의 Windows를 기동합니다.

그림 17

부팅이 완료되면 그림 9와 같이 boot.ini 파일을 수정하고 재부팅하면 됩니다. 여기서는 속도를 115200bps로 잡아도 잘 동작하는군요~ 그럼 일단 재부팅을 해볼까요~?

그림 18

여기서 엔터를 누르지말고 그대로 둡니다. 아직 호스트 PC 설정이 안되었기 때문이죠. 호스트 PC는 WinDbg를 실행시키는 PC라는 거 알고 계시죠? 가상 PC가 아닌 자신의 실제 PC가 호스트 PC인데 여기서 WinDbg를 실행해야 합니다. 그러나 이전처럼 프로그램 메뉴에 등록되어 있는 WinDbg를 실행시켜서는 가상 PC와 파이프로 연결될 수 없습니다. 파이프로 연결되기 위해서는 WinDbg 실행시 옵션을 붙여줘야 합니다. 실행할 때마다 이렇게 옵션을 붙여주는 것은 귀찮으므로 아예 다음과 같이 단축 아이콘을 하나 더 만들고 이름을 바꿉니다.

그림 19

여기서는 WinDbg 단축 아이콘을 복사하여 WinDbg_pipe라고 이름을 붙였습니다. 그런 다음 속성을 열고 다음과 같이 수정합니다.

그림 20

“대상”에 실행 파일 경로 뒤에 위와 같이 옵션을 붙여 줍니다. 이제 새로 생성한 WinDbg_pipe로 실행하면 pipe를 이용하여 가상 머신을 디버깅할 수 있습니다. 실제로 실행해 보도록 합시다.

그림 21

다시 WinDbg의 애타는 기다림이 시작되었습니다. 그림 18에서 멈추어 있던 타겟 PC를 메뉴 중 ([디버거 사용 가능]이라고 되어 있는) 아래 항목을 선택한 후 엔터를 누릅니다. 그러면 WinDbg는 다음과 같이 반응이 옵니다.

그림 22

앗, 그전에 심볼 설정을 해야 하는데... 저같은 경우엔 이전에 설정해 놓은게 있어서 그게 적용이 된 것 같습니다. PC 두 대를 이용한 방법을 참고하세요. 이제 “Ctrl+Break”를 눌러 타겟 PC에 브레이크를 걸어 볼까요.

그림 23

▶ 심볼 테스트

이로써 커널 디버깅 환경이 구축되었습니다. 짝짝짝~! 끝내기 전에 심볼이 제대로 로드되었는지 간단하게 테스트를 해보도록 합시다. 먼저 심볼 경로가 제대로 설정되어 있는지 확인해 봅시다. 주의: 이 작업은 브레이크를 걸어놓은 상태에서 할 수 있습니다.

그림 24

.sympath 이 명령은 현재 설정된 심볼 경로를 보여줍니다. 다시 한번 말씀드리는데 여기서 로컬 경로를 C:\WebSymbols 으로 설정하였는데, 이 디렉토리는 사용자가 반드시 만들어 놓아야 합니다. 심볼 서버로부터 심볼 파일을 정상적으로 받아왔다면 이 디렉토리 아래에 많은 폴더와 파일들이 생길 것입니다. 다음으로는 실제로 심볼이 로드되었는지를 확인해 봅시다.

그림 25

NTDLL 모듈과 nt 모듈의 심볼이 로드되었다는 것을 알 수 있습니다. 다른 모듈에 대해서는 (deferred)라고 나오는데, 이것은 모듈은 로드되었지만 그에 해당하는 심볼은 로드되지 않았다는 것을 나타냅니다. deferred, 말 그대로 ‘연기된’입니다. WinDbg는 모듈이 로드될 때마다 그에 따른 모든 심볼을 로드하지 않습니다. 그렇게 되면 자꾸 심볼 로딩에 시간이 많이 빼앗기기 때문이죠. 심볼이 필요할 때 사용자가 명시적으로 부르면 되는 것입니다. 이것을 “Deferred Symbol Loading”이라고 합니다. 그럼 아직 로드되지 않은 심볼을 로드되도록 해봅시다. 위 그림을 보면 hal 심볼이 아직 로드되지 않았군요. 이 심볼을 로드하도록 합니다.

그림 26

hal 심볼이 로드되었습니다. 확인해 보도록 하지요.

그림 27

이제 구체적으로 어떤 모듈에 어떤 심볼이 있는지 확인해 보도록 합시다. NTDLL을 보도록 하지요.

그림 28

▶ 맺음말

이쯤하면 커널 디버깅 환경이 구축되었으니 다음 글에서는 저번에 얘기했던 주제를 다루도록 하겠습니다~! 앗, 그리구 WinDbg를 설치하면 포함되어 있는 도움말 파일이 있는데, 꽤 도움이 많이 됩니다(그래서 도움말인가...-_-). 궁금하신건 왠만하면 거기에 다 있을 듯 하네요. 그럼 이만~~