응용프로그램을 디버깅하다보면 항상 고정된 위치에 응용프로그램이 로딩되어야 할 필요가 있는데요, 최신의 리눅스에는 해킹 방지를 위해 ASLR(Address Space Layout Randomization) 기능이 활성화되어 있어서 실행할 때마다 항상 다른 위치에 응용프로그램이 로딩됩니다. ㅠㅠ 좋은 기능이긴 한데... 디버깅시에는 크게 도움이 안되지요. ㅠㅠ

이 기능을 비활성화하려면 다음과 같이 파일을 추가하면 됩니다.

$> sudo vi /etc/sysctl.d/01-disable-aslr.conf

kernel.randomize_va_space = 0

아우 디버깅이 빨리 끝나야할텐데... 걱정이네요. ㅠㅠ

그럼 좋은 밤 되세요. ^^

지난번에 VMware와 IDA를 이용해서 MBR부터 윈도우 부팅과정을 따라가는 방법에 대한 글을 올렸는데요, Ilho님께서 WinDBG를 이용해서 부팅과정을 따라가는 방법도 있다고 알려주셔서 실험해봤습니다. ^^

일단 디버거가 붙은 시점은 32비트 부트매니져가 시작되는 시점이더라구요. MBR부터 따라가지 못하는 점은 조금 아쉽지만... 강력한 장점은 윈도우 심볼을 로드할 수 있어서 따라가기 편하다는 겁니다. @0@)-b (llho님 감사드려요 ㅠㅠ)

VMware 설정

일단, 부팅과정을 따라가려면 VMware에 시리얼을 추가해야 하는데요, VMware의 왼쪽 편에 있는 "Edit vritual machine settings"를 클릭하여 뜬 "Virtual Machine Settings" 창에서 왼쪽 아래에 있는 "Add"을 누르면 됩니다. 그러면 "Add Hardware Wizard"창이 표시되는데, "Serial Port" 항목을 선택한 뒤 "Next"를 누릅니다.

이제 시리얼 포트 타입과 옵션을 설정할 차례인데요, "Serial Port Type""Output to named pipe"로 하고 "Named pipe"의 이름은 "\.\pipe\com_1", "This end is the server", "The other end is a virtual machine", "Connect at power on"로 각각 선택해주시면 됩니다(좀 항목이 많은데 아래 그림을 참고하세요 ^^;;). 그리고 시리얼 포트가 생성되면 마지막으로 "Virtual Machine Settings" 창의 오른쪽 아래에 있는 "Yield CPU on poll"을 클릭해주시면 VMware의 설정은 끝납니다.


<VMware 시리얼 포트 등록 화면 1>


<VMware 시리얼 포트 등록 화면 2>


윈도우 7 설정

다음으로... 윈도우 7에 부트 디버그 옵션을 설정해야 하는데요, cmd.exe를 관리자 권한으로 실행해서 bcdedit.exe로 옵션을 설정해줘야 합니다. cmd.exe를 실행한 다음 아래처럼 입력해주면 됩니다.

주의: bcdedit로 부트 디버그 설정을 하고 나면 재부팅 후 디버그가 붙기 전까지는 부팅 시작이 아주 늦게 시작되더군요(한 1분쯤 기다려야 부팅이 시작되었던듯...). ㅠㅠ 실제로 사용하시는 윈도우에 실험삼아 하셨다가는 큰일이 날수도 있으니 주의하시기 바랍니다. ㅠㅠ

bcdedit /bootdebug {bootmgr} on
bcdedit /bootdebug on
bcdedit /debug {bootmgr} on 
bcdedit /debug on 
bcdedit /set {bootmgr} debugtype serial
bcdedit /set {bootmgr} baudrate 115200
bcdedit /set {bootmgr} debugport 1

그리고 재부팅을 하면 부팅이 시작되지 않고 디버거가 붙기를 기다립니다. 이제 WinDBG만 설정해주면 디버깅 준비가 모두 끝납니다.

WinDBG 설정

WinDBG는 마이크로소프트에서 제공하는 디버거로 유저 모드 디버깅과 커널 모드 디버깅을 모두 지원합니다. 그리고 윈도우 자체를 디버깅할 때 심볼을 자동으로 로드해주는 강력한 기능이 있기 때문에 윈도우를 분석하는데 정말 좋은 툴이라고 생각합니다. ^^;;;

WinDBG는 마이크로소프트 사의 페이지에서 다운받을 수 있으며, 다운 받은 설치 파일을 실행하면 끝납니다. 설치가 끝나면 이제 옵션을 주어 VMware의 시리얼 포트와 연결되도록 해야 하는데요, 먼저 windbg.exe 파일을 끌어서 바로가기를 만듭니다. 그리고 속성을 클릭해서 아래 화면처럼 대상의 내용을 수정해 줍니다. -k부터 주욱 입력해주시면 됩니다. ^^;;;

C:\WinDDK\7600.16385.1\Debuggers\windbg.exe -k com:port=\\.\pipe\com_1,baud=115200,pipe,reconnect


<WinDBG 설정 화면>


자, 입력까지 끝났으면 이제 바로가기를 클릭하여 windbg를 실행합니다. 그러면 창이 뜨고 아래처럼 "Waiting to reconnect..."라는 메시지가 표시될 텐데요, VMware를 시작하면 디버거가 연결되고 윈도우가 실행됩니다. 이 상태로는 원하는 부트 디버깅을 할 수 없으니 WinDBG 창에서 Control+break를 눌러서 중단 시킵니다. 그리고 아래로 넘어가서 심볼 경로 설정과 브레이크 포인트 설정을 해줍니다.

Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
Copyright (c) Microsoft Corporation. All rights reserved.

Waiting for pipe \\.\pipe\com_1
Waiting to reconnect...

WinDBG 심볼 설정 및 브레이크 포인트 설정하기

그럼 먼저 심볼을 로드할 수 있게 설정해보겠습니다. 심볼 경로는 "File" -> "Symbol File Path"를 클릭해서 지정해 줄 수 있으며, 아래처럼 입력해주면 웹에서 찾아 알아서 심볼을 다운로드 해줍니다. 굳이 윈도우 버전에 따라서 심볼을 찾느라 고생하지 않아도 된다는 거지요. ^^;;;

srv*c:\symbols.pub*http://msdl.microsoft.com/download/symbols

심볼 경로를 지정해줬으니 이번에는 bootmgr부터 디버깅을 하기 위해 WinDBG의 커맨드 창에서 아래처럼 입력해줍니다.

sxe ibp
sxe ld:bootmgr

다 입력했으면 VMware를 재시작 한 뒤에 WinDBG의 커맨드 창에서 .restart를 입력해서 재시작합니다. 그리고 잠시 기다리면 VMware와 연결되서 bootmgr부터 디버깅이 가능합니다. ^^)-b


<Bootmgr 디버깅 화면>



그럼 즐거운 디버깅(?)하세요 ;)

아아... 점점 프로젝트 마감은 다가오고... 책임의 압박은 슬슬 강해지는 이 시점에서... 어쩌다보니 버그 하나를 발견하게 되었습니다. ㅠㅠ 그것도 다들 보는 앞에서 "제대로" 말이지요. ㅠㅠ 그래서 빼도 박도 못하고 제가 디버깅을 맡아서 하게 되었는데... 얼래? 생각보다 이게 간단한 문제가 아닌겁니다. ㅠㅠ

재현성은 확실한데 시간이 1시간쯤 걸려서 아무리 바쁘게 움직여도 하루에 10번 재현하기가 쉽지 않더군요. 디버깅에 쏟은 시간을 따지면... 지난주 금요일부터해서 꼬박 3일간(야근까지 포함)을 투자했는데요, 실제로 버그의 원인은 아주 단순한데 있었습니다. ㅠㅠ 전형적인 커뮤니케이션 오류로 인한 버그라고 할까요? ㅠㅠ

잠시 설명을 하자면... 블럭들을 관리하는 블럭 풀이 있는데 이 블럭 풀은 4바이트짜리 구조체로 이루어져 있습니다. 그리고 그 안에는 A라는 필드가 있는데요, 이 필드 값은 무조건 0이라고 합의 된 상태였습니다. 아니, 합이 된듯한 상태라고 하는게 맞을 것 같습니다. 실제로 안그런 코드가 있었으니... ㅠㅠ

블럭 풀에서 파라미터로 넘어온 블럭과 같은 블럭을 삭제하는 코드는 위의 합의된 내용을 바탕으로 모든 필드가 일치하는 블럭을 찾도록 되어 있었는데요, 블럭 구조체에서 A는 블럭의 속성을 나타내지만, ID로는 사용되지 않는 필드였기 때문에 호출하는 쪽에서 A 필드의 값을 dummy로 넘겨버린거죠. ㅠㅠ

이 Dummy Data 때문에 블럭 풀에서 제거되었어야 할 블럭이 제거되지 않아서 여러 곳에 같은 블럭이 할당되어 사용되었고, 이로 인해 문제가 발생했던 겁니다. ㅠㅠ 아아... 그런데 이런게 왜 내가 테스트할 때 나올까요? ㅠㅠ

문제를 해결하는 코드를 넣고 테스트를 돌린 뒤 새벽 바람을 맞으며 퇴근하는데... 어찌나 씁쓸하던지... 눈물이 앞을 가리더군요. ㅠㅠ 이 문제가 빙산의 일각이 아니길 바라면서 한자 끄적여 봅니다.

다들 좋은 밤 되세요 ㅠㅠ 
제가 운영하는 OS 개발 사이트(http://www.mint64os.pe.kr)에 어떤 분께서 Object File을 coff 형식으로 생성할 수 있는 방법이 있느냐고 물어보시더라구요.

사실 제가 gcc의 각종 옵션에 익숙치 않아서....(매번 기본 옵션으로만 쓰다보니.. ^^;;;;) 구글 신님께 여쭤봤는데... 디버그 정보와 함께 오브젝트 파일을 coff 파일로 생성하는 옵션을 발견했습니다.

gcc -gcoff main.c

뭐, 당연한 거지만 gcc가 coff 파일을 지원해야 가능합니다. ^^;;;
보다 자세한 내용은 http://www.hanb.co.kr/network/view.html?bi_id=1382 내용을 참고하세요 ;)

ps) 혹시 디버그 정보 없이 coff 파일 형식으로 오브젝트 파일을 생성하는 옵션 아시는분 있으세요? ㅠㅠ

+ Recent posts