커널 디버깅하기

(무선)네트워크 2010. 1. 21. 12:07 Posted by 알 수 없는 사용자


요즘은 커널 디버깅을 하기위해 WinDBG를 많이 사용합니다.
그래서 커널 디버깅을 하기 위해 기본적으로 정리해야 할 개념들에 대해 정리해 보았습니다.

1. 디버깅 유형

  가. 라이브 디버깅

라이브 디버깅은 대상을 실행시켜 놓고 이를 Tracing하며 분석 하는 디버깅 기법입니다.
대상을 Tracing하며 분석하기 때문에 대상에 대한 이해가 보다 쉬우며, 직관적으로 다가갈 수 있습니다.

다음은 WinDBG를 이용하여 ndis.sys를 라이브디버깅하는 그림입니다.



  나. 덤프 디버깅
덤프디버깅은 시스템이 Crash 된 후 어느 지점에서 어떤 이유로 인해 시스템이 Crash됐는지 알아보고 이를 수정하는 디버깅 기법입니다. 보통 커널모드에서는 조금의 실수도 시스템 Crash로 이어지기 때문에 많이 쓰이는 디버깅 방법입니다.

다음 화면은 시스템 Crash로 인해 덤프디버깅 하는 그림입니다.


2. 심볼(Symbol)
  가. 심볼 개념
심볼파일은 어플리케이션, 혹은 드라이버 등을 개발하고 이를 링킹하는 작업이 이루어질 때, 생성되는 파일입니다. 심볼파일은 바이너리가 실행될때 필요하진 않지만, 디버깅 과정에서 아주 유용하게 사용되는 다양한 정보를 가지고 있습니다.

다음은 심볼이 포함하고 있는 정보입니다.

 전역변수
 지역변수
 함수이름
 EntryPoint
 FPO Data
 Source Linenumber

이러한 정보들은 바이너리를 디버깅 할 때 정보를 제공해 줌 으로써 디버깅작업을 좀 더 효율적으로 진행하게 도와줍니다.

  나. 심볼 유무에 따른 차이
NIDS는 심볼이 있고, vmmouse는 심볼이 없습니다.

NDIS를 디스어셈블링 한 결과입니다.

vmmouse를 디스어셈블링 한 결과입니다.

심볼이 있는경우는 심볼의 정보를 참조해서 함수라던지 이름이 잘 나오지만 심볼이 없는경우 offset값으로 판단을 하게 됩니다.

이렇게 심볼이 있는 바이너리를 디버깅 할 때와 심볼이 없는 바이너리를 디버깅 할 때 획득 할 수 있는 정보의 양이 달라지는 것을 확인할 수 있습니다. 이 말은 디버깅을 하려는 바이너리와 일치하는 심볼 파일이 있는지 확인을 해야 한다는 것을 의미합니다.
이런 이유로 라이브 디버깅과 덤프 디버깅 에 대하여 디버깅을 할 경우 심볼이 필요합니다.

3. 명령어

 가. BP VS BU
  (1)BP명령어
bp명령어는 직접적인 주소에 브레이크 포인트를 설치합니다. 그러므로 로딩되지 않은 모듈에는 브레이크 포인트를 설치하지 못합니다. 즉 로딩된 모듈에 브레이크포인트를 설치하고 디버깅 할 때에 주로 사용합니다. 그리고 Debuggee가 다시 시작될 경우 해당 주소에는 모듈의 내용이 맵핑되어 있지 않기 때문에 설치됐던 브레이크 포인트는 전부 사라지게 됩니다.

  (2)BU명령어
bp와는 달리 로딩되지 않은 모듈에 브레이크 포인트를 설치 할 수 있습니다. 이를 Unresolved BreakPoint 라고 부릅니다. 그리고 Debuggee가 다시 시작 될 경우 설치됐던 브레이크 포인트는 그대로 남아있게 됩니다. 

 나. 조건
  (1) j (if - else)

if – else 형식의 명령어로 조건이 맞을 때와 맞지 않을 때 각각에 대한 명령을 내릴 수 있습니다.

KD > bp 0x87ffb4e7 “j(MySymbol = 0) ‘’; ‘gc’”

 bp 0x87ffb4e7  0x87ffb4e7 브레이크 포인트를 설치
 j(MySymbol = 0)  if(MySymbol = 0)
 ‘’  if문이 참일 실행
 ‘gc’  if문이 거짓일 브레이크 포인트를 실행


  (2) z (while)
while문 형식의 명령어로 특정 조건을 만족할때까지 같은 작업을 반복할 수 있습니다.

KD > t;z(eax=0x875a4d00)

 t  트레이싱
 z(eax=0x875a4d00)  eax 0x875a4d00 일때까지