《Windows内核安全与驱动开发》 5.1&5.2 内核与应用方面的编程
《Windows内核安全与驱动开发》阅读笔记 -- 索引目录
《Windows内核安全与驱动开发》 5.1&5.2 内核与应用方面的编程
一、生成控制设备
- 如果一个驱动需要和应用程序通信,那么首先要生成一个_____。
- ____和____构成了整个操作系统的基本框架。
- ____暴露给了应用层,应用层可以像操作__一样操作它。
- 一般而言,用于和应用程序的设备往往用来"控制"这个内核驱动,所以往往称之为____。
- 作为一个控制设备,一般需要____,而普通设备可以不要。
二、控制设备的名字和符号链接
- 控制设备需要一个____,这样它才会暴露出来,供其他程序打开与之通信。
- 应用层是无法直接通过____来打开设备对象的,为此必须要建立一个暴露给应用层的____。
- 设备名的前缀____,符号链接的前缀为____,在应用层符号链接的前缀为_____。
三、分发函数与请求处理
- 标准分发函数的第一个参数是____,第二个参数是_____。
- 在分发函数中处理请求的第一步是_____,使用API函数_____。
- 利用____来获取主功能号。
- 设置____主要用于返回输出时。
- ____用于记录这个请求的完成状态。
- ____用于结束这个请求。
四、在应用层中打开与关闭设备
- 打开设备使用API函数____。文件的路径就是____的路径,但是其在应用层来看,是以___开头的,注意C语言需要转义。
- 关闭设备使用API函数____。
五、设备控制请求
- CTL_CODE是一个宏,我们要做的是直接利用这个宏来生成一个自己的____。
- CTL_CODE第一个参数是____,我们与任何硬件没关系,可以直接定义为未知类型(FILE_DEVICE_UNKNOWN)。
- CTL_CODE第二个参数是____,范围为____。
- CTL_CODE第三个参数METHOD_BUFFERED是____,输入/输出缓冲区会在__与__之间拷贝。
- CTL_CODE最后一个参数是____,因为要写入数据,因此为FILE_WRITE_DATA。
- 除了打开设备和关闭设备之外,中间增加了使用____发送请求的过程。
六、内核中对应的处理
- 在处理设备控制请求时,还有如下任务要完成缓冲区是irp->AssicatedIrp.SystemBuffer的前提是,这是一个__方式的设备控制请求。
- 获得____。
- 如果有输入缓冲区,必须获取输入缓冲区的____和____。
- 如果有输出缓冲区,必须获得输出缓冲区的____和____。
- 缓冲区是irp->AssociatedIrp.SystemBuffer的前提是,这是一个____方式的设备控制请求。
- 只说缓冲区,未说输入还是输出缓冲区,是因为在控制设备中,输入和输出缓冲区是____的,是同一个___。
答案
一、生成控制设备
- 设备对象
- 设备对象 分发函数
- 设备对象 文件
- 控制设备对象 CDO
- 设备名称
二、控制设备的名字和符号链接
- 名称
- 设备名称 符号链接
- \device\[设备名称] \??\[符号链接] \\.\[符号链接]
三、分发函数与请求处理
- 设备对象指针 irp请求
- 获得请求的当前栈空间(Current Stack Location)IoGetCurrentIrpStackLocation
- irpsp->MajorFunction
- irp->IoStatus.Information
- irp->IoStatus.Status
- IoCompleteRequest
四、在应用层中打开与关闭设备
- CreateFile 符号链接 \\.\
- CloseHandle
五、控制设备请求
- 设备请求功能号
- 设备类型
- 生成这个功能号的核心数字 (0x7ff,0xfff]
- 缓冲 用户 内核
- 操作需要的权限
- DeviceIoControl
六、内核中对应的处理
- 功能号 指针 长度 指针 长度
- 缓冲
- 共享 指针
R3与R0通信实例
一、R0层代码
/*********
作者:OneTrianee
编写时间:2019/12/8
编译环境:Win10+vs2019+"Empty WDM Driver"
代码作用:R0与R3通讯的R0层代码,只负责接收R3层传过来的字符串
参考资料:《Windows内核安全与驱动开发》
注意事项:无
***********/
#include <ntifs.h>
#include <wdmsec.h> // IoCreateDeviceSecure 函数原型
#include <ntddk.h> PDEVICE_OBJECT g_cdo = NULL; // 控制设备
#define CWK_CDO_SYB_NAME L"\\??\\sdfjkfsjdfsdfjkls" // 在R0的链接符号 // 从应用层给驱动发送一个字符串。
#define CWK_DVC_SEND_STR \
(ULONG)CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
0x911,METHOD_BUFFERED, \
FILE_WRITE_DATA) // 从驱动读取一个字符串
#define CWK_DVC_RECV_STR \
(ULONG)CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
0x912,METHOD_BUFFERED, \
FILE_READ_DATA) // 默认的GUID,辅助粘贴即可
const GUID CWK_GUID_CLASS_MYCDO =
{ 0x17a0d1e0L, 0x3249, 0x12e1, {0x92,0x16, 0x45, 0x1a, 0x21, 0x30, 0x29, 0x06} }; //
//提供一个卸载函数,删除符号链接与控制设备
//
VOID UnDriver(PDRIVER_OBJECT driver)
{
UNICODE_STRING cdo_syb = RTL_CONSTANT_STRING(CWK_CDO_SYB_NAME); // 符号链接字符串
ASSERT(g_cdo != NULL);
IoDeleteSymbolicLink(&cdo_syb); //删除 符号链接
IoDeleteDevice(g_cdo); // 删除 控制设备
KdPrint(("卸载驱动成功"));
} //
// 分发函数
//
NTSTATUS cwkDispatch(IN PDEVICE_OBJECT dev, IN PIRP irp) { //
// 获取当前irp栈空间
//
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp); NTSTATUS status = STATUS_SUCCESS;
ULONG ret_len = ; // 请求长度 //
// 循环处理发送给 g_cdo 的请求
// 如果不是发送给 g_cdo,则明显错误
//
while (dev == g_cdo) {
if (irpsp->MajorFunction == IRP_MJ_CREATE || irpsp->MajorFunction == IRP_MJ_CLOSE) {
// 生成和关闭请求,一律跳过即可
break;
}
if (irpsp->MajorFunction == IRP_MJ_DEVICE_CONTROL) { // 处理 DeviceIoControl
PVOID buffer = irp->AssociatedIrp.SystemBuffer; // 缓冲区地址
ULONG inlen = irpsp->Parameters.DeviceIoControl.InputBufferLength; // 输入缓冲区长度
ULONG outlen = irpsp->Parameters.DeviceIoControl.OutputBufferLength; // 输出缓冲区长度
ULONG len; //
// 根据前面定义好的设备请求功能号,
// 详细判断输入还是输出.
// 我们在这里只判断输入
//
switch (irpsp->Parameters.DeviceIoControl.IoControlCode) {
case CWK_DVC_SEND_STR:
ASSERT(buffer != NULL);
ASSERT(inlen > );
ASSERT(outlen == );
DbgPrint((char*)buffer);
// 已经打印过,则可以认为这个请求已经处理成功,放行即可
break;
case CWK_DVC_RECV_STR:
default:
// 到这里的请求都是不接收的(我们没设置接收)。
// 未知的请求一律返回非法参数错误
status = STATUS_INVALID_PARAMETER;
break;
}
}
break;
} //
// 不是发送给 g_cdo,明显错误
//
irp->IoStatus.Information = ret_len; // 填写返回信息
irp->IoStatus.Status = status; // 填写返回结果
IoCompleteRequest(irp, IO_NO_INCREMENT); // 完成请求
return status;
} //入口函数,相当于main。
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
NTSTATUS status;
UCHAR mem[] = { };
ULONG i;
//
// 生成一个控制设备。
// 然后生成符号链接。
//
UNICODE_STRING sddl = RTL_CONSTANT_STRING(L"D:P(A;;GA;;;WD)"); // 通用[直接复制即可]
UNICODE_STRING cdo_name = RTL_CONSTANT_STRING(L"\\Device\\adjdask"); // 设备名
UNICODE_STRING cdo_syb = RTL_CONSTANT_STRING(CWK_CDO_SYB_NAME); // 符号链接 //
// 生成一个设备对象。
//
status = IoCreateDevice(
driver,
, &cdo_name,
FILE_DEVICE_UNKNOWN,
,
FALSE,
&g_cdo);
if (!NT_SUCCESS(status))
return status; //
// 生成链接符号并与设备绑定
//
IoDeleteSymbolicLink(&cdo_syb); // 为防止冲突,先预先删除
status = IoCreateSymbolicLink(&cdo_syb, &cdo_name); // 将链接符号与设备绑定
if (!NT_SUCCESS(status)) {
IoDeleteDevice(g_cdo); // 删除设备
return status;
} //
// 将所有的分发函数设置为自定义的
//
for (i = ; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
driver->MajorFunction[i] = cwkDispatch;
} // 支持动态删除 && 清除控制设备的初始化标记
driver->DriverUnload = UnDriver;
g_cdo->Flags &= ~DO_DEVICE_INITIALIZING; return STATUS_SUCCESS;
}
二、R3层代码
/*********
作者:OneTrianee
编写时间:2019/12/8
编译环境:WinXp+VC6.0+"console"
代码作用:R0与R3层通信中R3层的代码,负责向R0层传递字符串。
参考资料:《Windows内核安全与驱动开发》
注意事项:原版很多宏在Vc6.0环境下都没有找到,在Vs2019中找到然后单独定义即可。
***********/ #include "stdafx.h" #include <stdio.h>
#include <tchar.h> #include <windows.h>
#define CTL_CODE(DeviceType, Function, Method, Access) ( ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
#define CWK_DEV_SYM L"\\\\.\\sdfjkfsjdfsdfjkls" // 从应用层给驱动发送一个字符串。
#define CWK_DVC_SEND_STR \
(ULONG)CTL_CODE( \
0x00000022, \
0x911,, \
FILE_WRITE_DATA) // 从驱动读取一个字符串
#define CWK_DVC_RECV_STR \
(ULONG)CTL_CODE( \
FILE_DEVICE_UNKNOWN, \
0x912,METHOD_BUFFERED, \
FILE_READ_DATA) int main(int argc, char* argv[])
{
HANDLE device = NULL;
ULONG ret_len;
int ret = ;
// 定义发送信息
char* msg = { "hello dirver, this is a message form app" }; // 打开设备,每次要操作驱动对象时,先以此为例子打开设备
device = CreateFileW(CWK_DEV_SYM, GENERIC_READ | GENERIC_WRITE, , , OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, );
if (device == INVALID_HANDLE_VALUE)
{
printf("coworker demo: Open device failed.\r\n");
return -;
}
else
printf("coworker demo: Open device successfully.\r\n"); if (!DeviceIoControl(device, CWK_DVC_SEND_STR, msg, strlen(msg) + , NULL, , &ret_len, )) {
printf("coworker demo: Send message failed.\r\n");
ret = -;
}
else
printf("coworker demo: Send message successfully.\r\n"); CloseHandle(device); return ;
}
《Windows内核安全与驱动开发》 5.1&5.2 内核与应用方面的编程的更多相关文章
- Windows内核安全与驱动开发
这篇是计算机中Windows Mobile/Symbian类的优质预售推荐<Windows内核安全与驱动开发>. 编辑推荐 本书适合计算机安全软件从业人员.计算机相关专业院校学生以及有一定 ...
- 《windows内核安全与驱动开发》ctrl2cap中的ObReferenceObjectByName疑问
国内有关于windows内核驱动这块的书籍实在是甚少,不过好在<windows内核安全与驱动开发>这本书还算不错(内容方面),但是不得不说这本书在许多地方存在着一些细节上的问题.比如我今天 ...
- 《Windows内核安全与驱动开发》 7.1&7.2&7.3 串口的过滤
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 7.1&7.2&7.3 串口的过滤 一.设备绑定的内核API ...
- 《Windows内核安全与驱动开发》阅读笔记 -- 索引目录
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 一.内核上机指导 二.内核编程环境及其特殊性 2.1 内核编程的环境 2.2 数据类型 2.3 重要的数据结构 2.4 函数调 ...
- 《Windows内核安全与驱动开发》 2.3 重要的数据结构
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 2.3 重要的数据结构 一.驱动对象 Windows内核采用__的编程方式 ...
- 《Windows内核安全与驱动开发》 3.1 字符串操作
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 3.1 字符串操作 一.字符串的初始化 1. 判断下列代码为什么会蓝屏? U ...
- 《Windows内核安全与驱动开发》 3.2 内存与链表
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 3.2 内存与链表 1. 尝试生成一个链表头并将其初始化. 2. 尝试向内存 ...
- 《Windows内核安全与驱动开发》4.1 文件操作
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发>4.1 文件操作 从 C:\a.txt 中读取一部分内容并利用 DbgPrin ...
- 《Windows内核安全与驱动开发》4.3 时间与定时器
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发>4.3 时间与定时器 一.获取自系统启动以来的毫秒数 /* 函数作用:求自操 ...
- 《Windows内核安全与驱动开发》 4.4 线程与事件
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 4.4 线程与事件 一.开辟一个线程,参数为(打印内容+打印次数),利用线程 ...
随机推荐
- 记一次C#调用C++踩过的坑
一般来说,C#调用C++生产的dll,如下: C++的项目要设置为"导出dll的项目",而且导出的函数,一般为: extern "C" __declspec(d ...
- 读书笔记——《MySQL DBA 工作笔记》
关于前言 作者在前言中提出的一些观点很具有参考价值, 梳理完整的知识体系 这是每一个技术流都应该追逐的,完整的知识体系能够使我们对知识的掌握更加全面,而不仅仅局限于点 建立技术连接的思维,面对需求,永 ...
- C函数库ctype.h概况
1 字符测试函数 1> 函数原型均为int isxxxx(int) 2> 参数为int, 任何实参均被提升成整型 3> 只能正确处理处于[0, 127]之间的值 2 字符映射函数 1 ...
- Keepalived+LVS DR模式高可用架构实践
Keepalived最初是为LVS设计,专门监控各服务器节点的状态(LVS不带健康检查功能,所以使用keepalived进行健康检查),后来加入了VRRP(虚拟路由热备协议(Virtual Route ...
- iSCSI 共享存储
iSCSI(Internet Small Computer System Interface,发音为/ˈаɪskʌzi/),Internet小型计算机系统接口,又称为IP-SAN,是一种基于 ...
- csps模拟测试57
T1 天空龙 大神题,考察多方面知识,例如:快读 附上考试代码,以供后人学习 应某迪要求,我决定多写一点. 正如文化课有知识性失分和非知识性失分一样,OI也同样存在. 但非知识性失分往往比知识性失分更 ...
- jdbc 加载数据库驱动如何破坏双亲委托模式
导读 通过jdbc链接数据库,是每个学习Java web 方向的人必然一开始会写的代码,虽然现在各路框架都帮大家封装好了jdbc,但是研究一下jdbc链接的套路还是很意义 术语以及相 ...
- 2019年10月13日 计算机英语习题 wangqingchao
Match the explanations in Column B with words and expressions in Columna. (搭配每组中意义相同的词或短语) Types of ...
- ToolStrip控件左右拖拽移动效果实现
1.主窗体下部添加一个Panel乘放ToolStrip控件以实现ToolStrip在窗体下部定位.2.当ToolStrip控件中子控件超出屏幕时,拖动控件可以实现滑动效果.拖动到控件边缘距窗体边缘1/ ...
- Java设计模式之单利模式(Singleton)
单利模式的应用场景: 单利模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例.并提供一个全局反访问点.单利模式是创建型模式.单利模式在生活中应用也很广泛,比如公司C ...