驱动开发:通过SystemBuf与内核层通信
内核层与应用层之间的数据交互是必不可少的部分,只有内核中的参数可以传递给用户数据才有意义,一般驱动多数情况下会使用SystemBuf缓冲区进行通信,也可以直接使用网络套接字实现通信,如下将简单介绍通过SystemBuf实现的内核层与应用层通信机制。
内核与应用层传递结构体,实现应用层用户传入一个结构体到内核,内核处理后返回一段字符串。
内核代码如下,代码已经备注。
#include <ntifs.h>
#include <windef.h>
#define My_Code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
// 通信结构体
typedef struct Hread
{
ULONG Flage;
ULONG Addr;
ULONG WriteBufferAddr;
ULONG Size;
ULONG Pid;
}_Hread, *PtrHread;
typedef struct _DEVICE_EXTENSION
{
UNICODE_STRING SymLinkName;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
// 驱动关闭提示
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pDevObj;
pDevObj = pDriverObject->DeviceObject;
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
UNICODE_STRING pLinkName = pDevExt->SymLinkName;
IoDeleteSymbolicLink(&pLinkName);
IoDeleteDevice(pDevObj);
}
// 默认派遣
NTSTATUS DefDispatchRoutine(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return status;
}
// 主派遣函数
NTSTATUS IoctlDispatchRoutine(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ULONG_PTR Informaiton = 0;
PVOID InputData = NULL;
ULONG InputDataLength = 0;
PVOID OutputData = NULL;
ULONG OutputDataLength = 0;
PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(pIrp); // Irp堆栈
InputData = pIrp->AssociatedIrp.SystemBuffer; // 输入堆栈
OutputData = pIrp->AssociatedIrp.SystemBuffer; // 输出堆栈
InputDataLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength; // 输入数据大小
OutputDataLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength; // 输出数据大小
ULONG Code = IoStackLocation->Parameters.DeviceIoControl.IoControlCode; // 控制码
switch (Code)
{
case My_Code:
{
PtrHread PtrBuff = (PtrHread)InputData;
ULONG RetFlage = PtrBuff->Flage;
ULONG RetAddr = PtrBuff->Addr;
ULONG RetBufferAddr = PtrBuff->WriteBufferAddr;
ULONG Size = PtrBuff->Size;
ULONG Pid = PtrBuff->Pid;
DbgPrint("读取文件标志:%d", RetFlage);
DbgPrint("读取写入地址:%x", RetAddr);
DbgPrint("读取缓冲区大小:%d", RetBufferAddr);
DbgPrint("读取当前大小:%d", Size);
DbgPrint("要操作进程PID: %d", Pid);
// 通过内存返回数据.
char *retBuffer = "hello lyshark";
memcpy(OutputData, retBuffer, strlen(retBuffer));
Informaiton = strlen(retBuffer) + 1;
Status = STATUS_SUCCESS;
// 通过内存返回数据,另一种通信方式.
/*
PVOID addr = (PVOID)"ok";
RtlCopyMemory(OutputData, addr, 4);
Informaiton = 4;
Status = STATUS_SUCCESS;
*/
break;
}
}
pIrp->IoStatus.Status = Status; // 设置IRP完成状态,会设置用户模式下的GetLastError
pIrp->IoStatus.Information = Informaiton; // 设置操作的字节
IoCompleteRequest(pIrp, IO_NO_INCREMENT); // 完成IRP,不增加优先级
return Status;
}
// 驱动入口
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
pDriverObject->DriverUnload = DriverUnload; // 注册驱动卸载函数
pDriverObject->MajorFunction[IRP_MJ_CREATE] = DefDispatchRoutine; // 注册派遣函数
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DefDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = DefDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_READ] = DefDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoctlDispatchRoutine;
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
// 创建设备名称的字符串
UNICODE_STRING devName;
RtlInitUnicodeString(&devName, L"\\Device\\MyDevice");
// 创建设备
status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
pDevObj->Flags |= DO_BUFFERED_IO; // 将设备设置为缓冲I/O设备
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; // 得到设备扩展
// 创建符号链接
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName, L"\\??\\MyDevice");
pDevExt->SymLinkName = symLinkName;
status = IoCreateSymbolicLink(&symLinkName, &devName);
return STATUS_SUCCESS;
}
客户端代码中只需要通过DeviceIoControl()发送控制信号即可,需要注意驱动需要安装并运行起来,否则无法获取到数据。
#include <Windows.h>
#include <iostream>
// 自定义的控制信号
#define My_Code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
// 通信结构体
typedef struct Hread
{
ULONG Flage;
ULONG Addr;
ULONG WriteBufferAddr;
ULONG Size;
ULONG Pid;
}_Hread, *PtrHread;
int main(int argc, char* argv[])
{
// 创建
HANDLE handle = CreateFileA("\\\\.\\MyDevice", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
unsigned char RetBufferData[20] = { 0 };
DWORD ReturnLength = 4;
_Hread buf;
buf.Flage = 2;
buf.Addr = 0x401234;
buf.WriteBufferAddr = 1024;
buf.Size = 100;
buf.Pid = 2566;
DeviceIoControl(handle, My_Code, &buf, 20, (LPVOID)RetBufferData, 4, &ReturnLength, 0);
for (size_t i = 0; i < 20; i++)
{
printf("返回数据: %d \n", RetBufferData[i]);
}
CloseHandle(handle);
getchar();
return 0;
}
运行这段代码我们看下返回效果:

驱动开发:通过SystemBuf与内核层通信的更多相关文章
- 驱动通信:通过PIPE管道与内核层通信
在本人前一篇博文<驱动开发:通过ReadFile与内核层通信>详细介绍了如何使用应用层ReadFile系列函数实现内核通信,本篇将继续延申这个知识点,介绍利用PIPE命名管道实现应用层与内 ...
- 驱动开发:通过ReadFile与内核层通信
驱动与应用程序的通信是非常有必要的,内核中执行代码后需要将其动态显示给应用层,但驱动程序与应用层毕竟不在一个地址空间内,为了实现内核与应用层数据交互则必须有通信的方法,微软为我们提供了三种通信方式,如 ...
- 字符设备驱动ioctl实现用户层内核层通信
测试代码实现 memdev.h #ifndef _MEMDEV_H_ #define _MEMDEV_H_ #include<linux/ioctl.h> #ifndef MEMDEV_M ...
- 驱动开发:通过Async反向与内核通信
在前几篇文章中给大家具体解释了驱动与应用层之间正向通信的一些经典案例,本章将继续学习驱动通信,不过这次我们学习的是通过运用Async异步模式实现的反向通信,反向通信机制在开发中时常被用到,例如一个杀毒 ...
- HarmonyOS USB DDK助你轻松实现USB驱动开发
HDF(Hardware Driver Foundation)驱动框架是HarmonyOS硬件生态开放的基础,为开发者提供了驱动加载.驱动服务管理和驱动消息机制等驱动能力,让开发者能精准且高效地开发驱 ...
- [内核驱动] miniFilter 内核层与应用程序通信
转载:http://blog.csdn.net/heyabo/article/details/8721611 转载:http://www.cnblogs.com/ljinshuan/archive/2 ...
- 驱动开发:内核层InlineHook挂钩函数
在上一章<驱动开发:内核LDE64引擎计算汇编长度>中,LyShark教大家如何通过LDE64引擎实现计算反汇编指令长度,本章将在此基础之上实现内联函数挂钩,内核中的InlineHook函 ...
- windows 驱动开发 MDL 内核层 用户层共享内存
参考资料 https://blog.csdn.net/wdykanq/article/details/7752909 http://blog.51cto.com/laokaddk/404584 内核层 ...
- 驱动开发:通过MDL映射实现多次通信
在前几篇文章中LyShark通过多种方式实现了驱动程序与应用层之间的通信,这其中就包括了通过运用SystemBuf缓冲区通信,运用ReadFile读写通信,运用PIPE管道通信,以及运用ASYNC反向 ...
- Windows内核安全与驱动开发
这篇是计算机中Windows Mobile/Symbian类的优质预售推荐<Windows内核安全与驱动开发>. 编辑推荐 本书适合计算机安全软件从业人员.计算机相关专业院校学生以及有一定 ...
随机推荐
- HanLP — HMM隐马尔可夫模型 -- 维特比(Viterbi)算法 --示例代码 - Java
Viterbi 维特比算法解决的是篱笆型的图的最短路径问题,图的节点按列组织,每列的节点数量可以不一样,每一列的节点只能和相邻列的节点相连,不能跨列相连,节点之间有着不同的距离,距离的值就不在 题目背 ...
- Eight HDU - 1043 (反向搜索 + 康拓展开 / A* + BFS / IDA* )
题目描述 简单介绍一下八数码问题: 在一个3×3的九宫格上,填有1~8八个数字,空余一个位置,例如下图: 1 2 3 4 5 6 7 8 在上图中,由于右下角位置是空的,你可以移动数字,比如可以将数字 ...
- C++ 的两种换行符区别
当我们在C++执行一个输出语句时,在输出语句最后可以使用 std::endl 或 \n 建立一个新行. 但这两种换行方式对程序有不同的影响. std::endl 它在建立一个新的行的同时,还会自动刷新 ...
- AtCoder Beginner Contest 176 (ABC水题,D题01BFS,E数组处理)
补题链接:Here A - Takoyaki 很容易看出 \(\frac{N + X - 1}{X} \times T\) B - Multiple of 9 给定一个很大的整数,问其是否是 \(9\ ...
- 特色国风数字孪生智慧大坝 3D 可视化
前言 水利兴,五谷丰.水利作为国民经济稳定和谐的重要部分,不仅有防洪减灾.农业灌溉.城市供水调水.渔业外贸.旅游航运.生态环境等综合应用,水电资源也是至关重要的可持续能源之一.大坝与水库.水电站等水利 ...
- 08.25北京站|阿里云Serverless 技术实践营( AI 专场)开放报名
活动简介 阿里云 Serverless 技术实践营(AI 专场)是一场以聚焦企业级 AIGC 应用开发与落地展开的主题活动,活动受众以关注 Serverless 和 AI 技术的开发者.企业决策人.云 ...
- 一、redis单例安装(linux)
系列导航 一.redis单例安装(linux) 二.redis主从环境搭建 三.redis集群搭建 四.redis增加密码验证 五.java操作redis 环境:centos7.5需要的安装包: re ...
- [tslint] Identifier 'loggedIn' is never reassigned; use 'const' instead of 'let'. (prefer-const)
- vue-cli 3.x 项目,如何增加对 jsx 的支持?vue-cli 3.x 项目,如何增加对 jsx 的支持?
https://segmentfault.com/q/1010000019655500
- com.alibaba.fastjson.JSONException: create instance error
很早之前在使用FashJson进行实体类转化的时候,如果json参数是多层都是一层对应一个单独的实体类, 今天在项目中想,使用内部类是不是也可以实现,且使用内部类封装性更好.当将json串使用fast ...