한땀한땀 정성들인 코딩
윈도우 드라이버 개발하기 본문
반응형
윈도우 서비스를 만들었으면 테스트 환경을 준비해 준다.
- window XP sp3 x64 (VM 환경)
- window 7 이상부터는 드라이버 인증서가 필요하다.
1. wdk 커널 빌드 환경
- cmd를 관리자 권한으로 실행한 뒤 bin폴더 아래에 있는 setenv.bat을 실행한다.
- 드라이버 빌드환경에 맞게(i386, amd64) 옵션을 줘서 진행한다.
- 소스가 존재하는 폴더에 들어가 build를 하면 된다.
2. 유저모드 (window console application)
- 미리 컴파일된 헤더로 프로젝트를 생성
2.1 서비스 생성(드라이버 로드용)
bool _util_load_sysfile(cahr *theDriverName)
{
char aPath[1024];
char aCurrentDirectory[515];
SC_HANDLE sh = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if(!sh)
{
return false;
}
GetCurrentDirectory(512, aCurrentDirectory);
_snprintf(aPath, 1022, "%s\\%s.sys", aCurrentDirectory, theDriverName);
SC_HANDLE rh = CreateService(sh, theDriverName, theDriverName, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, aPath,
NULL,
NULL,
NULL,
NULL,
NULL);
if(!rh){
if(GetLastError() == ERROR_SERVICE_EXISTS){
rh = OpenService(sh, theDriverName, SERVICE_ALL_ACCESS);
if(!rh){
CloseServiceHandle(sh);
return false;
}
else{
CloseServiceHandle(sh);
return false;
}
}
if(rh){
if(0 == StartService(rh, 0, NULL)){
if(ERROR_SERVICE_ALREDY_RUNNING == GetLastError()){
}
else{
CloseServiceHandle(sh);
CloseServiceHandle(rh);
return false;
}
}
CloseServiceHandle(sh);
CloseServiceHandle(rh);
}
return true;
}
}
- OpenSCManager
- CreateService or OpenService
- StartService ...
2.2 드라이버 통신용으로 프로젝트 하나 더 생성
#include "stdafx.h"
#include "Windows.h"
int main()
{
HANDLE hDevice;
hDevice = CreateFile(L"\\\\.\\MyDevice",
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hDevice == ((HANDLE)-1)) {
printf("handle fail \n");
return -1;
}
printf("handle success : %d\n", hDevice);
CloseHandle(hDevice);
return 0;
3. 드라이버 코드 simple.sys
#include "ntddk.h"
#include "wdm.h"
const WCHAR deviceLinkBuffer[] = L"\\DosDevices\\MyDevice";
const WCHAR deviceNameBuffer[] = L"\\Device\\MyDevice";
PDEVICE_OBJECT g_RootkitDevice;
NTSTATUS OnStubDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){
Irp -> IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
VOID OnUnload( IN PDRIVER_OBJECT DriverObject ){
UNICODE_STRING Name;
DbgPrint("OnUnload called\n");
RtlInitUnicodeString(&Name, deviceLinkBuffer);
IoDeleteSymbolicLink(&Name);
IoDeleteDevice(DriverObject->DeviceObject);
DbgPrint("Unload complete!\n");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT myDriver, IN PUNICODE_STRING theRegistryPath){
NTSTATUS ntStatus;
UNICODE_STRING deviceNameUnicodeString;
UNICODE_STRING deviceLinkUnicodeString;
int i;
for(i=0; i<IRP_MJ_MAXIMUM_FUNCTION;i++){
myDriver->MajorFunction[i] = OnStubDispatch;
}
myDriver->DriverUnload = OnUnload;
RtlInitUnicodeString(&deviceNameUnicodeString, deviceNameBuffer);
RtlInitUnicodeString(&deviceLinkUnicodeString, deviceLinkBuffer);
ntStatus = IoCreateDevice(myDriver, 0, &deviceNameUnicodeString, FILE_DEVICE_UNKNOWN,0, TRUE, &g_RootkitDevice);
if(NT_SUCCESS(ntStatus)){
ntStatus = IoCreateSymbolicLink(&deviceLinkUnicodeString, &deviceNameUnicodeString);
}
return STATUS_SUCCESS;
}
MAKEFILE
TARGETNAME=simple
TARGETPATH=.\sys
TARGETTYPE=DRIVER
SOURCES=device-test.c
SOURCES
!INCLUDE $(NTMAKEENV)\makefile.def
- IRP 테이블에 myDriver->MajorFunction[i] = OnStubDispatch; 이런식으로 read, write, ioctl 함수를 대체.
- 즉 winapi중 하나인 ReadFile을 호출하면 매핑해논 드라어버의 IRP가 호출된다.
- BOOL ReadFile( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped );
check!
NTSTATUS OnStubDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){
Irp -> IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
유저 프로세스에서 ReadFile 호출 시 STATUS_SUCCESS 리턴하는지 확인
반응형