Windows/DeviceDriver 2021. 4. 20. 01:32

3. 간단한 드라이버와 디버깅


디버깅을 위한 준비

  • 가상 머신에서 호스트와의 파일 공유가 원활하도록 공유 폴더를 지정해둔다.

  • 가상 머신, WinDbg, 비주얼 스튜디오 프로그램을 실행한다.

빌드

  • 새 프로젝트 생성에서 Empty WDM Driver를 선택한다.

  • 프로젝트명은 sample로 설정하였다.

  • Driver Files에서 sample.inf가 존재하는데, 아직 사용하지 않으므로 지워준다.

  • 소스 파일에 sample.c 파일을 생성한다.

    sample.c

    #include <ntddk.h>
    
    NTSTATUS DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegistryPath)
    {
      pDrvObj = pDrvObj;
      pRegistryPath = pRegistryPath;
      return STATUS_UNSUCCESSFUL;
    }
  • x64 환경에서 빌드한다.

    • 그대로 빌드하면 에러가 발생하므로, 프로젝트 설정의 C/C++ - Code Generation - Spectre Mitigation 속성을 Disabled로 변경한다.
  • 솔루션의 경로인 sample에서 x64\Debug\로 이동하면 다음과 같은 파일들을 볼 수 있다.

    • sample.sys

      • 타겟 PC에 위치해야 하는 샘플 드라이버 파일이다.

      • 가상 머신의 공유 폴더로 옮긴 뒤, 가상 머신 내부의 C:\sample\ 경로로 옮겨준다.

    • sample.pdb

      • 호스트 PC에 위치해야 하는 샘플 드라이버 심볼 파일이다.


드라이버 실행 및 디버깅

  • 가상 머신에서 관리자 권한으로 CMD를 실행시킨다.

    • 서비스 생성

      sc create sample binpath=c:\sample\sample.sys type=kernel start=demand
  • WinDbg에서 Break를 클릭하고, 아래 명령줄에 다음을 입력하여 sample 드라이버 모듈의 DriverEntry 함수에 브레이크 포인트를 건다.

    bp sample!DriverEntry
    • 디바이스가 아직 로딩되지 않았기 때문에, 다음 메시지가 출력되는게 정상이다.

      Bp expression 'sample!DriverEntry' could not be resolved, adding deferred bp
    • g를 입력하거나 Go를 클릭하여 가상 머신을 다시 running 상태로 만들어준다.

  • 가상 머신에서 드라이버를 로딩하기 위해 관리자 권한의 CMD에서 다음을 입력한다.

    sc start sample
    • TESTSIGNING 모드에서만 정상적으로 작동된다.

    • 가상 머신이 Break 되어 조작이 불가능한 것을 볼 수 있다.

  • WinDbg를 확인해보면 브레이크 포인트로 설정한 함수의 코드를 볼 수 있고, 메뉴의 View 탭에서 콜스택이나 변수들에 대한 정보 등 많은 것을 확인할 수 있다.

    • Step into, Step over 등의 trace도 가능하다. 굉장히 강력한 디버깅 툴이다.

    • Go를 누르든 Step over로 진행하든 아무튼 디버깅을 마치고 가상 머신의 CMD로 가보면 다음과 같은 메시지가 출력되어 있다.

      [SC] StartService 실패 31:
      
      시스템에 부착된 장치가 작동하지 않습니다.
      • 이는 DriverEntry 함수가 STATUS_UNSUCCESSFUL을 반환하기 때문이다.