C , C++/Kernel

Windows Driver 개발환경 셋팅과 간단한 디버그 프린트 출력

string_ 2024. 7. 2. 19:36

Windows Driver?

Windows 운영 체제와 하드웨어 간의 통신을 가능하게 하는 소프트웨어 구성요소이며

운영 체제의 커널 모드에서 실행되며 하드웨어 장치의 기능을 제어하고 관리할 수 있다.

 

주로 하드웨어 장치의 작동을 제어하며 키보드, 마우스, 프린터  동작을 제어하는

각각의 드라이버들이 시스템에 존재한다.

 

운영체제와 하드웨어 간의 인터페이스를 제공하므로 응용 프로그램이 하드웨어를 직접 제어하지 않고

운영체제를 통해 간접적으로 제어할 수 있다.

 

입출력 (I/O) 요청을 처리하여 운영 체제와 하드웨어 간의 데이터 전송을 관리한다.

일반적으로. sys 확장자를 가진다.

 

 

Driver 개발 시 고려 사항

드라이버는 커널 모드에서 실행되므로 오류가 발생하면 시스템 전체가

불안정해질 수 있으므로 철저한 테스트와 디버깅이 필요하며 여러 환경에서 충분한 테스트 후 배포 작업을

진행하여야 한다.

(유저모드에서는 Excepction -> 프로그램 종료 루틴으로 끝나지만 커널모드에선 BSOD가 발생한다)

 

또한 드라이버는 높은 권한으로 실행되기에 보안 취약점이 있을 경우 악의적인 사용자가 이를 이용하여

악용될 수 있는 가능성도 있어서 보안성에 신경을 써야 한다.

 

1. VisualStudio 설치

워크로드에서 C++ 를 사용한 데스크톱 개발을 선택

 

C++ 데스크톱 개발 선택

 

개별 구성 요소에서 하단 라이브러리를 선택하여 설치

완화 라이브러리 및 빌드 도구 설치

 

개별 구성요소 선택

 

 

 

2. 윈도우 버전에 맞게 SDK를 설치

 

VS 설치 중 SDK도 같이 설치가 가능해서 SDK도 같이 설치해 준다.

 

 

 

3. WDK 설치

윈도우 버전에 맞게 WDK를 설치한다.

필자는 Windows 10, version 2004용 WDK를 설치하였음

 

정확한 건 해당 MSDN 문서를 참고해서 직접 설치해 보면 될 것 같다.

https://learn.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk

 

 

Kernel Mode Driver, Empty (KMDF)

 

정상적으로 WDK를 설치하면 커널모드 드라이버 프로젝트를 생성할 수 있는 항목란이 생긴다.

Kernel Mode Driver, Empty (KMDF)를 선택하여 프로젝트를 생성한다.

 

프로젝트 속성

프로젝트 속성 -> SDK 버전, 도구 집합 맞게 버전이 선택되어 있는지 확인

 

 

진입점 함수 변경

 

링커 -> 고급 설정에서 진입점 함수를 DriverEntry -> EntryPoint로 변경해 주었다.

 

#include <ntdef.h>
#include <ntifs.h>
#include <ntddk.h>
#include <windef.h>
#include <ntstrsafe.h>

extern "C" NTSTATUS EntryPoint(PDRIVER_OBJECT driver_obj, PUNICODE_STRING registry_path) {
	UNREFERENCED_PARAMETER(driver_obj);
	UNREFERENCED_PARAMETER(registry_path);
	DbgPrintEx(0, 0, "Driver Loaded!\n");
	return STATUS_SUCCESS;
}

 

코드를 간단히 번역하면 다음과 같다.

 

extern "C" 는 C++ 컴파일러에게 이 함수가 C 스타일의 이름 맹글링을 사용하도록 하게 한다.

PDRIVER_OBJECT driver_obj는 드라이버 객체에 대한 포인터로 드라이버의 상태와 진입점을 관리하는 변수,

PUNICODE_STRING registry_path는 드라이버 레지스트리 경로를 가리키는 유니코드 문자열 포인터 변수이다.

 

	UNREFERENCED_PARAMETER(driver_obj);
	UNREFERENCED_PARAMETER(registry_path);

 

해당 코드는 주어진 매개변수가 함수 내에서 사용되지 않음을 나타내고 경고를 방지하기 위해 사용된다.

 

https://learn.microsoft.com/ko-kr/windows-hardware/drivers/ddi/wdm/nf-wdm-dbgprintex

DbgPrintEx(0, 0, "Driver Loaded!\n");

 

DbgPrintEx 루틴은 커널 디버거에 문자열을 보내는 함수이다.

이는 해당 드라이버가 성공적으로 로드되었음을 확인하기 위한 용도로 작성하였다.

 

정상적으로 빌드한 모습

 

Windows 환경에서 커널모드 드라이버를 로드하려면 디지털 서명이 필요하므로

직접 만든 드라이버를 로드하려면 테스트서명 모드 부팅을 통해 로드하거나

합법적인 인증서를 직접 MicroSoft로부터 받아야 드라이버를 로드할 수 있다.

 

디버그 프린트 출력 확인

'C , C++ > Kernel' 카테고리의 다른 글

Windows 수동으로 Driver Entry 찾기  (0) 2025.03.10
Hyper-V windbg 원격 디버깅 설정  (0) 2025.03.09