win10 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;
}