驱动开发:通过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内核安全与驱动开发>. 编辑推荐 本书适合计算机安全软件从业人员.计算机相关专业院校学生以及有一定 ...
随机推荐
- Dapper.Lite 使用教程
以MySQL数据库为例 一. 安装 NuGet搜索Dapper.Lite并安装最新版本. NuGet搜索MySqlConnector并安装最新版本. 也可以使用MySql.Data库,但MySqlCo ...
- C# Task 多任务:C# 扩展TaskScheduler实现独立线程池,支持多任务批量处理,互不干扰,无缝兼容Task
先上源码: https://gitee.com/s0611163/TaskSchedulerEx 为什么编写TaskSchedulerEx类? 因为.NET默认线程池只有一个线程池,如果某个批 ...
- 无需代码绘制人工神经网络ANN模型结构图的方法
本文介绍几种基于在线网页或软件的.不用代码的神经网络模型结构可视化绘图方法. 之前向大家介绍了一种基于Python第三方ann_visualizer模块的神经网络结构可视化方法,大家可以直接点 ...
- OAuth2.0回调函数用html页面转发给controller
OAuth2.0授权中有个回调函数,就是请求授权服务后,它会将你需要的code(假设code就是你需要的数据)发送给你的回调函数(你对外开放的一个url地址用以接收参数) 注:这个回调函数有点讨厌为什 ...
- 【转载】内存基本概念-伙伴(Buddy)算法
简介 在Linux系统中,内存的分配与回收速率直接影响系统的存取效率.当内核频繁请求和释放不同大小的一组连续页框时,会导致许多外部空闲碎片,造成空间的浪费.使用伙伴算法可以有效地缓解该问题.伙伴关 ...
- 文件上传accept参数可接受的类型汇总
https://www.cnblogs.com/huihuihero/p/17012817.html 1 // 文件上传accept接受的文件类型 2 3 export const fileTypes ...
- KSP(坎巴拉)萌新感悟
1.为什么降落月球等无大气星球时减速为亚轨道之后便不再减速,等到快坠落的时候在满节流阀极限减速最省燃料? 因为我们的dv是确定的,燃料能给我们带来一定量的冲量,却因此可以带来不一定量的动量,显然速度越 ...
- php开发之文件下载的实现
前言 php是网络安全学习里必不可少的一环,简单理解php的开发环节能更好的帮助我们去学习php以及其他语言的web漏洞原理 正文 在正常的开发中,文件下载的功能是必不可少,比如我们在论坛看到好看图片 ...
- sublime_text4 2023最新版 激活教程
官网 Sublime HQ - Remarkable Software 东西在教学的时候还是挺好用的,就是要付费购买,穷,没钱 买不起,自己动手丰衣足食. 下载安装包 我现在最新版是4.4152 下面 ...
- Linux-用户管理-useradd-userdel-id