许多程序都是以HelloWorld开始的,本文也不例外。
程序以C语言为基础。代码如下:
/*
Name: NTDriver.h
Version: 0.10
Author: dir
Date: 22-09-09 23:42
Description:
*/
#ifndef __NTDRIVER__H__
#define __NTDRIVER__H__
#include <ntddk.h>
// 设备扩展
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName;
UNICODE_STRING ustrSymLinkName;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
#define DEVNAME L"//Device//MyDevice"
#define SYMLINKNAME L"//??//HelloWorld"
// 字符缓冲区大小
#define BUFFER_SIZE 256
// 函数声明
NTSTATUS
CreateDevice(IN PDRIVER_OBJECT pDriverObjcet);
VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject);
NTSTATUS
HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp);
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT pDriverObjcet,
IN PUNICODE_STRING pRegistryPath);
#endif
/*
Name: NTDriver.c
Version: 0.10
Author: dir
Date: 22-09-09 23:42
Description:
*/
#include "NTDriver.h"
// 声明函数在内存中的形式
#ifdef ALLOC_PRAGMA
#pragma alloc_text(ININ, CreateDevice)
#pragma alloc_text(ININ, DriverEntry)
#pragma alloc_text(PAGE, HelloDDKDispatchRoutine)
#pragma alloc_text(PAGE, HelloDDKUnload)
#endif
//
// 函数部分
//
// 创建设备
NTSTATUS
CreateDevice(IN PDRIVER_OBJECT pDriverObjcet)
{
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
UNICODE_STRING uDevName;
UNICODE_STRING uSymLinkName;
// 创建设备名
RtlInitUnicodeString(&uDevName, DEVNAME);
// 创建设备
status = IoCreateDevice(pDriverObjcet,sizeof(DEVICE_EXTENSION),
&uDevName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
if (!NT_SUCCESS(status))
{
return status;
}
// 初始化内存读写方式
pDevObj->Flags |= DO_BUFFERED_IO;
// 将驱动信息记录在扩展设备中
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
// 将设备名写入扩展设备
pDevExt->ustrDeviceName.MaximumLength = BUFFER_SIZE;
pDevExt->ustrDeviceName.Buffer = (PWSTR)ExAllocatePool(PagedPool, BUFFER_SIZE);
RtlCopyUnicodeString(&pDevExt->ustrDeviceName, &uDevName);
// 创建符号链接
RtlInitUnicodeString(&uSymLinkName, SYMLINKNAME);
IoCreateSymbolicLink(&uSymLinkName, &uDevName);
if (!NT_SUCCESS(status))
{
// 删除设备
IoDeleteDevice(pDevObj);
return status;
}
// 将符号链接写入扩展设备
pDevExt->ustrSymLinkName.MaximumLength = BUFFER_SIZE;
pDevExt->ustrSymLinkName.Buffer = (PWSTR)ExAllocatePool(PagedPool, BUFFER_SIZE);
RtlCopyUnicodeString(&pDevExt->ustrSymLinkName, &uSymLinkName);
return STATUS_SUCCESS;
}
// 卸载设备
VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
KdPrint(("[HelloDDK] Enter HelloDDKUnload/n"));
pDevObj = pDriverObject->DeviceObject;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
// 删除符号链接
IoDeleteSymbolicLink(&pDevExt->ustrSymLinkName);
// 删除设备
IoDeleteDevice(pDevExt->pDevice);
// 释放字符串空间
RtlFreeUnicodeString(&pDevExt->ustrSymLinkName);
RtlFreeUnicodeString(&pDevExt->ustrDeviceName);
KdPrint(("[HelloDDK] Leave HelloDDKUnload/n"));
}
// 消息派遣
NTSTATUS
HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
KdPrint(("[HelloDDK] Enter HelloDDKDispatchRoutine/n"));
// 完成IRP
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
KdPrint(("[HelloDDK] Leave HelloDDKDispatchRoutine/n"));
return status;
}
// 驱动入口
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT pDriverObjcet,
IN PUNICODE_STRING pRegistryPath)
{
NTSTATUS status;
KdPrint(("[HelloDDK] Enter DriverEntry/n"));
// 创建驱动设备对象
status = CreateDevice(pDriverObjcet);
if (!NT_SUCCESS(status))
{
return status;
}
// 注册其它驱动函数入口
pDriverObjcet->DriverUnload = HelloDDKUnload;
pDriverObjcet->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
pDriverObjcet->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
pDriverObjcet->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;
pDriverObjcet->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
KdPrint(("[HelloDDK] Leave DriverEntry/n"));
return status;
}
驱动不像普通的程序一样直接双击就可以运行。而程序的错误可能引起蓝屏(BSOD),所以驱动一般先在虚拟机里调试运行。
通过KMD加载、运行驱动。通过DebugView来查看输出信息。驱动加载后可以用WinObj来查看设备和符号链接。
运行效果图: