x64 0环与3环通信

一:了解通信机制

注意:
一:3环程序一般带有窗口,传递信息windows把msg结构体传送给3环的窗口句柄,然后程序根据msg结构信息做出回应。
流程示例: 鼠标点击窗口任意按钮—》由Windows封装成msg结构体----》给到应用程序窗口winpro—》得到对应的处理函数
二: 0环的驱动接收信息示例:使用windows定义的函数(如:CreateFileW,DeviceIoControl)—》产生IRP结构体----》设备—》得到对应的处理函数
提示:对应的处理函数都是由用户自己定义。

二:应用层–3环代码示例

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "hstring.h"
#include <windows.h>
#include "tlhelp32.h"
//#define DEVICE_NAME L"\\Device\\MirSun"  在三环搜索不到0环的设备名
#define SYMBOLICLINK_NAME L"\\\\.\\MirSunLnk"
#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x888,METHOD_BUFFERED,FILE_ANY_ACCESS)
//CTL_CODE(设备类型),Function(功能2-13位),Method(I/O访问内存使用方式),Access(访问限制,14-15位)。
//Method我们驱动选取的是:缓冲区方式读写(DO_BUFFERED_IO)对应METHOD_BUFFERED
//Function(功能2-13位)0x888和驱动写成一致
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x999,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IN_BUFFER_MAXLENGTH 4   //传给0环最大的长度
#define OUT_BUFFER_MAXLENGTH 4  //接收0环数据的最大长度

int main()
{
	// 打开设备,获取设备的句柄
	HANDLE hDevice = CreateFileW(SYMBOLICLINK_NAME, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	DWORD ErrorCode = GetLastError();
	if (hDevice == INVALID_HANDLE_VALUE)
	{
		printf("获取设备句柄失败 %d.\n", ErrorCode);
		getchar();
		return 1;
	}
	else
	{
		printf("获取设备句柄成功.\n");
	}
	// 通信机制
	DWORD ThreeInBuffer = 0x123456;//传给三环的数据
	DWORD ZeroOutBuffer = {0};//0环传过来的数据 放入这个位置
	DWORD ZeroOutLength;//0环传过来的数据长度
	DeviceIoControl(hDevice, OPER2, &ThreeInBuffer, IN_BUFFER_MAXLENGTH, &ZeroOutBuffer, OUT_BUFFER_MAXLENGTH, &ZeroOutLength, NULL);
	printf("ZeroOutBuffer: %08X ZeroOutLength: %08X\n", ZeroOutBuffer, ZeroOutLength);
	// 关闭设备对象
	CloseHandle(hDevice);
	getchar();
	return 0;
	
}

三:驱动层–0环代码示例

#include <ntddk.h>

#define DEVICE_NAME L"\\Device\\MirSun"   //设备名称宏
#define SYMBOLICLINK_NAME L"\\??\\MirSunLnk" //设备别名 给三环用

#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x888,METHOD_BUFFERED,FILE_ANY_ACCESS)//0x7FF系统占用
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x999,METHOD_BUFFERED,FILE_ANY_ACCESS)

// 跟三环程序一样  申明函数
VOID DriverUnload(PDRIVER_OBJECT pDriver);
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp);

// 入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegPath)
{
	NTSTATUS status;
	ULONG uIndex = 0;
	PDEVICE_OBJECT pDeviceObj = NULL; // 设备对象指针
	UNICODE_STRING DeviceName; // 设备名,0环用
	UNICODE_STRING SymbolicLinkName; // 符号链接名,3环用

	// 初始化设备名称
	RtlInitUnicodeString(&DeviceName, DEVICE_NAME);//填充DeviceName结构体 最大长度 使用长度 字符串指针
	// 创建设备并给设备对象赋值 
	status = IoCreateDevice(pDriver, 0, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObj);

	if (status != STATUS_SUCCESS)
	{
		IoDeleteDevice(pDeviceObj);//删除设备对象
		DbgPrint("创建设备失败.\n");
		return status;
	}
	DbgPrint("创建设备成功.\n");
	// 设置交互数据的方式
	//三种  缓冲区方式读写(DO_BUFFERED_IO)  (物理页)直接方式读写(DO_DIRECT_IO) pDevObj->Flags即不设置 :
	pDeviceObj->Flags |= DO_BUFFERED_IO;
	// 创建符号链接
	RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICLINK_NAME);//初始化UnicodeString
	IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);//把0环设备名和三环设备别名锁定一起
	// 设置分发函数
	pDriver->MajorFunction[IRP_MJ_CREATE] = IrpCreateProc;
	pDriver->MajorFunction[IRP_MJ_CLOSE] = IrpCloseProc;
	pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControlProc;
	// 设置卸载函数
	pDriver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

// 卸载驱动
VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	UNICODE_STRING SymbolicLinkName;
	// 删除符号链接,删除设备
	RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICLINK_NAME);
	IoDeleteSymbolicLink(&SymbolicLinkName);
	IoDeleteDevice(pDriver->DeviceObject);
	DbgPrint("驱动卸载成功\n");
}

// 不设置这个函数,则Ring3调用CreateFile会返回1
// IRP_MJ_CREATE 处理函数
NTSTATUS IrpCreateProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	DbgPrint("应用层发送CreateFileW.\n");
	pIrp->IoStatus.Status = STATUS_SUCCESS;// 状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Information = 0;//不返回信息
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);// 传递给下一层
	return STATUS_SUCCESS; // 返回给3环程序 3环用 GetLastError()获取
}

// IRP_MJ_CLOSE 处理函数
NTSTATUS IrpCloseProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	DbgPrint("应用层发送CloseHandle.\n");
	pIrp->IoStatus.Status = STATUS_SUCCESS;// 状态如果不设置,Ring3返回值是失败
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

// IRP_MJ_DEVICE_CONTROL 处理函数
NTSTATUS IrpDeviceControlProc(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
	DbgPrint("应用层发送IrpDeviceControl.\n");
	NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
	PIO_STACK_LOCATION pIrpStack;
	ULONG ControlCodeDate;//对应CTL_CODE 第二个参数的值
	PVOID pZeroBufferThree;
	ULONG ThreeInLength;
	ULONG ZeroOutLength;
	ULONG ReadThreeDate;// 读取缓冲区数据
	ULONG WriteZero;// 写入数据到缓冲区

	
	ReadThreeDate = 0;
	WriteZero = 0x12345678;
	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);// 获取IRP需要数据部分结构体
	ControlCodeDate = pIrpStack->Parameters.DeviceIoControl.IoControlCode;	// 获取控制码
	pZeroBufferThree = pIrp->AssociatedIrp.SystemBuffer;	// 获取缓冲区地址(输入输出是同一个)
	ThreeInLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;	// 3环发送数据的长度
	ZeroOutLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;	//0环指定长度

	switch (ControlCodeDate)
	{
	case OPER1:
	{
		DbgPrint("IrpDeviceControlProc -> OPER1...\n");
		pIrp->IoStatus.Information = 0;
		status = STATUS_SUCCESS;
		break;
	}
	case OPER2:
	{
		DbgPrint("IrpDeviceControlProc -> OPER2 输入字节数: %d\n", ThreeInLength);//打印三环输入字节
		DbgPrint("IrpDeviceControlProc -> OPER2 输出字节数: %d\n", ZeroOutLength);
		memcpy(&ReadThreeDate, pZeroBufferThree, 4);		// 获取缓冲区数据并赋值给ReadThreeDate
		DbgPrint("IrpDeviceControlProc -> OPER2 ReadThreeDate: %x\n", ReadThreeDate);//打印三环写入缓冲区的数据
		memcpy(pZeroBufferThree, &WriteZero, 4);//向缓冲区写入数据
		pIrp->IoStatus.Information = 4; // 返回四字节
		status = STATUS_SUCCESS;
		break;
	}
	}

	
	pIrp->IoStatus.Status = status;// 状态如果不设置,Ring3返回值是失败
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

四:调式结果如下

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值