C++ 第一个驱动程序

驱动入口


// NTSTATUS : (LONG) 0~0X7FFFFFFF 正确状态,0X80000000~0XFFFFFFFF 错误状态。参考:https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55

/* PDRIVER_OBJECT : 驱动对象结构体指针 **********************************
typedef struct _DRIVER_OBJECT {
  CSHORT             	Type;				// ?
  CSHORT            	Size;				// ?
  PDEVICE_OBJECT     	DeviceObject;		// 指向设备对象的指针
  ULONG              	Flags;				// ?
  PVOID              	DriverStart;		// ?
  ULONG              	DriverSize;			// ?
  PVOID              	DriverSection;		// ?
  PDRIVER_EXTENSION  	DriverExtension;	// 指向驱动程序扩展的指针
  UNICODE_STRING     	DriverName;			// ?
  PUNICODE_STRING    	HardwareDatabase;	// 指向注册表 \Registry\Machine\Hardware 路径的指针
  PFAST_IO_DISPATCH  	FastIoDispatch;		// 指向驱动快速 I/O 入口点结构体指针
  PDRIVER_INITIALIZE 	DriverInit;			// DriverEntry 入口点指针
  PDRIVER_STARTIO    	DriverStartIo;		// StartIo 入口点指针
  PDRIVER_UNLOAD     	DriverUnload;		// Unload 入口点指针
  PDRIVER_DISPATCH   	MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];		// IRP(派遣函数) 入口点指针
  		-----------------------------------------------------
		IRP_MJ_CLEANUP :关闭设备
		IRP_MJ_CLOSE :关闭文件句柄
		IRP_MJ_CREATE :打开设备
		IRP_MJ_DEVICE_CONTROL :对用户模式或内核模式客户程序可用的控制操作
		IRP_MJ_FILE_SYSTEM_CONTROL :文件系统控制
		IRP_MJ_FLUSH_BUFFERS :写输入缓冲区或丢弃输入缓冲区
		IRP_MJ_INTERNAL_DEVICE_CONTROL :内核模式客户程序可用的控制操作
		IRP_MJ_PNP :即插即用管理
		IRP_MJ_POWER :电源管理
		IRP_MJ_QUERY_INFORMATION :得到信息
		IRP_MJ_READ :读取数据
		IRP_MJ_SET_INFORMATION :设置信息
		IRP_MJ_SHUTDOWN :系统关闭
		IRP_MJ_SYSTEM_CONTROL :系统管理与测试
		IRP_MJ_WRITE :写数据
		------------------------------------------------------
} DRIVER_OBJECT, *PDRIVER_OBJECT;	
****************************************/

/* PUNICODE_STRING : Unicode 字符串结构体
typedef struct _UNICODE_STRING {
  USHORT Length;			// 字符串长度
  USHORT MaximumLength;		// 分配给缓冲区的大小
  PWSTR  Buffer;			// 指向宽字符串的指针
} UNICODE_STRING, *PUNICODE_STRING;
*/
NTSTATUS DriverEntry(
	IN PDRIVER_OBJECT DriverObject,
	IN PUNICODE_STRING RegistryPath
){
	// 输出日志
	DbgPrint("DriverEntry start.");

	// 指定驱动卸载函数
	DriverObject->DriverUnload = (PDRIVER_UNLOAD)你的卸载函数;
	
	// 指定派遣函数
	DriverObject->MajorFunction[IRP_MJ_CREATE] = 你的 IRP_MJ_CREATE 派遣函数名
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = 你的 IRP_MJ_CLOSE 派遣函数名
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = 你的 IRP_MJ_DEVICE_CONTROL 派遣函数名

	// 等等...(如:创建设备)
}

创建设备

/* 设备对象 ********************************
typedef struct _DEVICE_OBJECT {
  CSHORT                   Type;					// 固定值 3,表示这个对象是一个设备对象
  USHORT                   Size;					// 设备对象字节大小
  LONG                     ReferenceCount;			// 相关联的设备被打开的句柄数量
  struct _DRIVER_OBJECT    *DriverObject;			// 驱动对象指针
  struct _DEVICE_OBJECT    *NextDevice;				// 指向下一个设备对象的指针(属于同一个驱动)
  struct _DEVICE_OBJECT    *AttachedDevice;			// 挂载设备指针
  struct _IRP              *CurrentIrp;				// 当前IRP
  PIO_TIMER                Timer;					// 计时器指针
  ULONG                    Flags;					// 设备操作类型
  ULONG                    Characteristics;			// 设备附加信息
  __volatile PVPB          Vpb;						// 
  PVOID                    DeviceExtension;
  DEVICE_TYPE              DeviceType;
  CCHAR                    StackSize;
  union {
    LIST_ENTRY         ListEntry;
    WAIT_CONTEXT_BLOCK Wcb;
  } Queue;
  ULONG                    AlignmentRequirement;
  KDEVICE_QUEUE            DeviceQueue;
  KDPC                     Dpc;
  ULONG                    ActiveThreadCount;
  PSECURITY_DESCRIPTOR     SecurityDescriptor;
  KEVENT                   DeviceLock;
  USHORT                   SectorSize;
  USHORT                   Spare1;
  struct _DEVOBJ_EXTENSION *DeviceObjectExtension;
  PVOID                    Reserved;
} DEVICE_OBJECT, *PDEVICE_OBJECT;
*********/
NTSTATUS CreateDevice(IN PDRIVER_OBJECT DriverObject){
	// 定义返回值
	NTSTATUS status;
	
	// 初始化设备名
	RtlInitUnicodeString(&接收设备名的变量,L"\\Device\\设备名");

	// 创建设备
	status = IoCreateDevice(
    	DriverObject,						// 指向驱动对象的指针
    	0,									// 设备扩展分配的字节数
   	 	&(UNICODE_STRING)设备名变量,			// 设备名
    	FILE_DEVICE_UNKNOWN,				// 设备类型,参考:https://docs.microsoft.com/zh-cn/windows-hardware/drivers/kernel/specifying-device-types
    	0,									// 驱动设备附加信息
    	TRUE,								// 设备对象是否独占设备
    	&(PDEVICE_OBJECT)设备对象变量			// 设备对象指针 
  	);if(!NT_SUCCESS(status)){KdPrint(("IoCreateDevice error."));return status;}

	// 初始化符号链接名
	RtlInitUnicodeString(&符号链接名变量,L"\\??\\符号链接名");
	
	// 创建符号链接
	status = IoCreateSymbolicLink(&符号链接名变量,&设备对象变量);
	if(!NT_SUCCESS(status)){DbgPrint("IoCreateSymbolicLink error.");return status;}

	return STATUS_SUCCESS;
}

卸载驱动

NTSTATUS DriverUnload(IN PDRIVER_OBJECT DriverObject){
	// 输出日志
	DbgPrint("DriverUnload start.");

	// 删除符号链接
	IoDeleteSymbolicLink(&符号链接名变量);

	// 删除设备
	IoDeleteDevice(设备对象变量);
}

派遣函数

/* _IRP:表示一个 I/O 请求包 ************************
参考:https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_irp?redirectedfrom=MSDN
	typedef struct _IRP {
	  CSHORT                    Type;
	  USHORT                    Size;
	  PMDL                      MdlAddress;					// 指向描述用户缓冲区的MDL的指针
	  ULONG                     Flags;
	  union {
	    struct _IRP     *MasterIrp;		// 指向IRP中主IRP的指针
	    __volatile LONG IrpCount;
	    PVOID           SystemBuffer;	// 指向系统空间缓冲区的指针。
	  } AssociatedIrp;
	  LIST_ENTRY                ThreadListEntry;
	  IO_STATUS_BLOCK           IoStatus;					// 驱动程序在调用IoCompleteRequest之前存储状态和信息
	  KPROCESSOR_MODE           RequestorMode;				// UserMode 或 KernelMode
	  BOOLEAN                   PendingReturned;			// 驱动程序是否已经将IRP标记为pending
	  CHAR                      StackCount;					
	  CHAR                      CurrentLocation;
	  BOOLEAN                   Cancel;						// IRP 是否要被取消
	  KIRQL                     CancelIrql;
	  CCHAR                     ApcEnvironment;
	  UCHAR                     AllocationFlags;
	  PIO_STATUS_BLOCK          UserIosb;
	  PKEVENT                   UserEvent;
	  union {
	    struct {
	      union {
	        PIO_APC_ROUTINE UserApcRoutine;
	        PVOID           IssuingProcess;
	      };
	      PVOID UserApcContext;
	    } AsynchronousParameters;
	    LARGE_INTEGER AllocationSize;
	  } Overlay;
	  __volatile PDRIVER_CANCEL CancelRoutine;				// IRP 取消函数的入口点,NULL 表示 IRP 不会被取消
	  PVOID                     UserBuffer;					// 输出缓冲区
	  union {
	    struct {
	      union {
	        KDEVICE_QUEUE_ENTRY DeviceQueueEntry;		
	        struct {
	          PVOID DriverContext[4];
	        };
	      };
	      PETHREAD     Thread;
	      PCHAR        AuxiliaryBuffer;
	      struct {
	        LIST_ENTRY ListEntry;
	        union {
	          struct _IO_STACK_LOCATION *CurrentStackLocation;
	          ULONG                     PacketType;
	        };
	      };
	      PFILE_OBJECT OriginalFileObject;
	    } Overlay;
	    KAPC  Apc;
	    PVOID CompletionKey;
	  } Tail;
} IRP;
********************************/

/* IO_STATUS_BLOCK:IRP 调用 IoCompleteRequest 之前 I/O 请求的最终状态 ***
typedef struct _IO_STATUS_BLOCK {
  union {
    NTSTATUS Status;			// I/O 请求的完成状态,参考:https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
    PVOID    Pointer;			// 保留
  } DUMMYUNIONNAME;
  ULONG_PTR Information;		// I/O 请求传输的字节数
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
*****************/

// 对应 IRP_MJ_CREATE 、 IRP_MJ_CLOSE
NTSTATUS dpc_CAC(IN PDEVICE_OBJECT pDevObj,IN PIRP pIRP){
	// 将 IRP 返回给 I/O 管理器
	IoCompleteRequest(
		pIRP,				// IRP 指针
		IO_NO_INCREMENT		// 线程优先级,IO_NO_INCREMENT :不增加优先级
		    /*
				IO_NO_INCREMENT			    		不增加优先级
				IO_CD_ROM_INCREMENT                 光驱设备增加的优先级
				IO_DISK_INCREMENT                   磁盘设备增加的优先级
				IO_KEYBOARD_INCREMENT               键盘设备增加的优先级
				IO_MOUSE_INCREMENT                  鼠标设备增加的优先级
				IO_NAMED_PIPE_INCREMENT             命名管道增加的优先级
				IO_NETWORK_INCREMENT                网络设备增加的优先级
				IO_PARALLEL_INCREMENT               并口设备增加的优先级
				IO_SERIAL_INCREMENT                 串口设备增加的优先级
				IO_SOUND_INCREMENT                  声卡设备增加的优先级
				IO_VIDEO_INCREMENT                  视频设备增加的优先级
				SEMAPHORE_INCREMENT                 信号灯增加的优先级
			*/
	);

	// 设置 I/O 请求状态
	pIRP->IoStatus.Status = STATUS_SUCCESS;

	// 设置 I/O 请求传输的字节数
	pIRP->IoStatus.Information = 0;

	return STATUS_SUCCESS;
}

// 对应 IRP_MJ_DEVICE_CONTROL
#define IRP_TEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)	// #define 最好放在最上方,我这里为了方便看就放在了这里。
NTSTATUS myIrpControl(IN PDEVICE_OBJECT pDevObj,IN PIRP pIRP){
	// 获取 IRP 对应的 I/O 堆栈指针
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIRP);

	// 得到输入缓冲区大小
	ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;

	// 得到输出缓冲区大小
	ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;

	// 得到 IOCTL 码(用于写在下面的 switch 中,避免代码臃肿)
	ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
	
	// 捕获 I/O 操作类型(MajorFunction)
	switch (code){
		case IRP_TEST:
		// do somethings
		default:
		break;
	}
}

.exe 请求派遣函数

int _tmain(int argc, _TCHAR* argv[])
{
	// 连接设备
	HANDLE hDevice = CreateFile(
		L"\\\\.\\设备符号链接名",
		GENERIC_READ | GENERIC_WRITE,			// 访问设备的方式
		FILE_SHARE_READ | FILE_SHARE_WRITE,		// 设备共享方式
		NULL,									// 保留
		OPEN_EXISTING,							// 如果设备不存在,函数返回失败
		FILE_ATTRIBUTE_NORMAL,					// 设备没有设置其他属性
		NULL									// 保留
	);if(hDevice == INVALID_HANDLE_VALUE){cout << "CreateFile error : " << GetLastError() << endl;}

	// 向设备发送 I/O 请求
	DWORD ReturnLength = 0;
	DWORD status = DeviceIoControl(
			hDevice,					// 设备句柄
			CTL_CODE(					// 操作控制代码
				FILE_DEVICE_UNKNOWN,
				0x800,
				METHOD_BUFFERED,
				FILE_ANY_ACCESS),
			NULL,						// 指向输入缓冲区的指针
			NULL,						// 输入缓冲区大小
			NULL,						// 指向输出缓冲区的指针
			NULL,						// 输出缓冲区大小
			&ReturnLength,				// 必须要有,否则程序卡死
			NULL						// 指向 OVERLAPPED 结构体的指针
		);

	getchar();
	return 0;
}

完整代码

#include <ntddk.h>


UNICODE_STRING name_device;			// 设备名
UNICODE_STRING name_symbol;			// 符号链接
PDEVICE_OBJECT deviceObj;			// 设备对象

// 对应 IRP_MJ_DEVICE_CONTROL
NTSTATUS myIrpControl(IN PDEVICE_OBJECT pDevObj, IN PIRP pIRP) {
	// 获取 IRP 对应的 I/O 堆栈指针
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIRP);

	// 捕获 I/O 操作类型(MajorFunction)
	switch (stack->MajorFunction) {
	case IRP_MJ_DEVICE_CONTROL:
	{
		// 捕获 I/O 控制码
		switch (stack->Parameters.DeviceIoControl.IoControlCode) {
			case CTL_CODE(
				FILE_DEVICE_UNKNOWN,		// 设备类型
				0x800,						// 函数代码,不能大于 4095(推荐使用 0 - 2047)
				METHOD_BUFFERED,       		// 访问内存的方式
				FILE_ANY_ACCESS				// 权限
			): {
				KdPrint(("应用程序调用了我"));
			}
			default:
				break;
		}
	}
	case IRP_MJ_CREATE:
		break;
	case IRP_MJ_CLOSE:
		break;
	default:
		break;
	}
}

// 对应 IRP_MJ_CREATE 、 IRP_MJ_CLOSE
NTSTATUS dpc_CAC(IN PDEVICE_OBJECT pDevObj, IN PIRP pIRP) {
	// 将 IRP 返回给 I/O 管理器
	IoCompleteRequest(
		pIRP,				// IRP 指针
		IO_NO_INCREMENT		// 线程优先级,IO_NO_INCREMENT :不增加优先级
	);

	// 设置 I/O 请求状态
	pIRP->IoStatus.Status = STATUS_SUCCESS;

	// 设置 I/O 请求传输的字节数
	pIRP->IoStatus.Information = 0;

	return STATUS_SUCCESS;
}

NTSTATUS CreateDevice(IN PDRIVER_OBJECT DriverObject) {
	// 定义返回值
	NTSTATUS status;

	// 初始化设备名
	RtlInitUnicodeString(&name_device, L"\\Device\\LYSM_device");

	// 创建设备
	status = IoCreateDevice(
		DriverObject,							// 指向驱动对象的指针
		0,										// 设备扩展分配的字节数
		&name_device,							// 设备名
		FILE_DEVICE_UNKNOWN,					// 设备类型
		0,										// 驱动设备附加信息
		TRUE,									// 设备对象是否独占设备
		&deviceObj								// 设备对象指针 
	); 
	if (!NT_SUCCESS(status)) { 
		KdPrint(("IoCreateDevice error:%X",status));
		return status;
	}

	// 初始化符号链接名
	RtlInitUnicodeString(&name_symbol, L"\\??\\LYSM_symbol");

	// 创建符号链接
	status = IoCreateSymbolicLink(&name_symbol, &name_device);
	if (!NT_SUCCESS(status)) { 
		DbgPrint("IoCreateSymbolicLink error:%X",status); 
		return status; 
	}

	return STATUS_SUCCESS;
}

NTSTATUS DriverUnload(IN PDRIVER_OBJECT DriverObject) {
	// 定义返回值
	NTSTATUS status;
	
	// 输出日志
	DbgPrint("DriverUnload start.");

	// 删除符号链接
	status = IoDeleteSymbolicLink(&name_symbol);
	if (!NT_SUCCESS(status)) {
		DbgPrint("IoDeleteSymbolicLink error:%X",status); 
		return status; 
	}

	// 删除设备
	IoDeleteDevice(deviceObj);

	return STATUS_SUCCESS;
}


extern "C" NTSTATUS DriverEntry(
	IN PDRIVER_OBJECT DriverObject,
	IN PUNICODE_STRING RegistryPath
) {
	// 定义返回值
	NTSTATUS status;

	// 输出日志
	DbgPrint("DriverEntry start.");

	// 指定驱动卸载函数
	DriverObject->DriverUnload = (PDRIVER_UNLOAD)DriverUnload;
	
	// 指定派遣函数
	DriverObject->MajorFunction[IRP_MJ_CREATE] = dpc_CAC;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = dpc_CAC;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = myIrpControl;

	
	// 创建设备
	status = CreateDevice(DriverObject);
	if(!NT_SUCCESS(status)) { DbgPrint("CreateDevice error:%X",status); return status; }

	return STATUS_SUCCESS;
}

在这里插入图片描述
回家打游戏去咯 ε≡٩(๑>₃<)۶

0.基础的基础 |-学习WIN64驱动开发的硬件准备 |-配置驱动开发环境 ------------------------------ 1.驱动级HelloWorld |-配置驱动测试环境 |-编译和加载内核HelloWorld ------------------------------ 2.内核编程基础 |-WIN64内核编程的基本规则 |-驱动程序与应用程序通信 |-内核里使用内存 |-内核里操作字符串 |-内核里操作文件 |-内核里操作注册表 |-内核里操作进线程 |-驱动里的其它常用代码 ------------------------------ 3.内核HOOK与UNHOOK |-系统调用、WOW64与兼容模式 |-编程实现突破WIN7的PatchGuard |-系统服务描述表结构详解 |-SSDT HOOK和UNHOOK |-SHADOW SSDT HOOK和UNHOOK |-INLINE HOOK和UNHOOK ------------------------------ 4.无HOOK监控技术 |-无HOOK监控进线程启动和退出 |-无HOOK监控模块加载 |-无HOOK监控注册表操作 |-无HOOK监控文件操作 |-无HOOK监控进线程句柄操作 |-使用对象回调监视文件访问 |-无HOOK监控网络访问 |-无HOOK监视修改时间 ------------------------------ 5.零散内容 |-驱动里实现内嵌汇编 |-DKOM隐藏进程+保护进程 |-枚举和隐藏内核模块 |-强制结束进程 |-强制读写进程内存 |-枚举消息钩子 |-强制解锁文件 |-初步探索PE32+格式文件 ------------------------------ 6.用户态HOOK与UNHOOK |-RING3注射DLL到系统进程 |-RING3的INLINE HOOK和UNHOOK |-RING3的EAT HOOK和IAT HOOK ------------------------------ 7.反回调 |-枚举与删除创建进线程回调 |-枚举与删除加载映像回调 |-枚举与删除注册表回调 |-枚举与对抗MiniFilter |-枚举与删除对象回调
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值