梦织未来Windows驱动编程 第06课 驱动对磁盘文件的操作
代码部分:
实现一个文件C:\\text.txt,并读取写入内容到文件,然后将文件设置为只读,并隐藏文件。代码如下:
//MyCreateFile.c
//2016.07.22
#include <ntddk.h> NTSTATUS MyCreateFile()
{
HANDLE hFile; NTSTATUS Status = STATUS_SUCCESS; UNICODE_STRING usFileName;
OBJECT_ATTRIBUTES FileObjAttr;
IO_STATUS_BLOCK IoStatusBlock; memset (&FileObjAttr, , sizeof(OBJECT_ATTRIBUTES)); RtlInitUnicodeString (&usFileName, L"\\??\\c:\\test.txt");
InitializeObjectAttributes(&FileObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); //OBJ_CASE_INSENSITIVE 大小写不敏感 Status = ZwCreateFile (&hFile,
GENERIC_ALL,
&FileObjAttr,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF, //如果没有文件,创建文件。如果有文件,直接打开
FILE_NON_DIRECTORY_FILE, //不是目录
NULL,
);
if (!NT_SUCCESS(Status))
{
return Status;
} KdPrint(("Create File Success!")); ZwClose (hFile); return Status;
} NTSTATUS MyOpenFile()
{
HANDLE hFile; UNICODE_STRING usFileName;
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES FileObjAttr;
IO_STATUS_BLOCK IoStatusBlock; RtlInitUnicodeString (&usFileName, L"\\??\\c:\\test.txt");
memset (&FileObjAttr, , sizeof(OBJECT_ATTRIBUTES)); InitializeObjectAttributes(&FileObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenFile(&hFile,
GENERIC_ALL,
&FileObjAttr,
&IoStatusBlock,
FILE_SHARE_READ,
FILE_NON_DIRECTORY_FILE);
if (!NT_SUCCESS(Status))
{
KdPrint(("Open File Failed:0x%X", Status));
return Status;
} KdPrint(("Open File Success!")); ZwClose(hFile); return Status;
} NTSTATUS MyZwSetInfomationFile()
{
HANDLE hFile; UNICODE_STRING usFileName;
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES FileObjAttr;
IO_STATUS_BLOCK IoStatusBlock;
FILE_BASIC_INFORMATION fbi; RtlInitUnicodeString (&usFileName, L"\\??\\c:\\test.txt");
memset (&FileObjAttr, , sizeof(OBJECT_ATTRIBUTES)); InitializeObjectAttributes(&FileObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenFile(&hFile,
GENERIC_ALL,
&FileObjAttr,
&IoStatusBlock,
FILE_SHARE_READ,
FILE_NON_DIRECTORY_FILE);
if (!NT_SUCCESS(Status))
{
KdPrint(("Open File Failed:0x%X", Status));
return Status;
} KdPrint(("Open File Success!")); Status = ZwQueryInformationFile (hFile, &IoStatusBlock, &fbi, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); //查看FileBasicInformation
if (!NT_SUCCESS(Status))
{
KdPrint(("Query Information Error code: %X", Status));
ZwClose (hFile);
return Status;
} KdPrint(("CreationTime:0x%X Attributes:0x%X", fbi.CreationTime, fbi.FileAttributes));
fbi.FileAttributes |= FILE_ATTRIBUTE_HIDDEN; //隐藏文件
fbi.FileAttributes |= FILE_ATTRIBUTE_READONLY; //只读属性 Status = ZwSetInformationFile (hFile, &IoStatusBlock, &fbi, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation);
if (!NT_SUCCESS(Status))
{
KdPrint(("Set Information Error:0x%X", Status));
ZwClose(hFile);
return Status;
} ZwClose(hFile); return Status;
} NTSTATUS MyReadFile()
{
HANDLE hFile; UNICODE_STRING usFileName;
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES FileObjAttr;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER ReadBuffer; char strBuffer[] = {}; RtlInitUnicodeString (&usFileName, L"\\??\\c:\\test.txt");
memset (&FileObjAttr, , sizeof(OBJECT_ATTRIBUTES)); InitializeObjectAttributes(&FileObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenFile(&hFile,
GENERIC_ALL,
&FileObjAttr,
&IoStatusBlock,
FILE_SHARE_READ,
FILE_NON_DIRECTORY_FILE);
if (!NT_SUCCESS(Status))
{
KdPrint(("Open File Failed:0x%X", Status));
return Status;
} KdPrint(("Open File Success!"));
ReadBuffer.QuadPart = ; Status = ZwReadFile(hFile, NULL, NULL, NULL, &IoStatusBlock, (PVOID)strBuffer, , &ReadBuffer, NULL); //从文件的0位置读取16个字节到strBuffer
if (!NT_SUCCESS(Status))
{
KdPrint(("ReadFile Failed, Error Code:0x%X", Status));
ZwClose(hFile);
return Status;
} KdPrint(("strBuffer:<%s>", strBuffer)); ZwClose(hFile);
return Status;
} NTSTATUS MyWriteFile()
{
HANDLE hFile; UNICODE_STRING usFileName;
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_ATTRIBUTES FileObjAttr;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER WriteBuffer; char strBuffer[] = "ahuakndkaj.;'?"; RtlInitUnicodeString (&usFileName, L"\\??\\c:\\test.txt");
memset (&FileObjAttr, , sizeof(OBJECT_ATTRIBUTES)); InitializeObjectAttributes(&FileObjAttr, &usFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenFile(&hFile,
GENERIC_ALL,
&FileObjAttr,
&IoStatusBlock,
FILE_SHARE_READ,
FILE_NON_DIRECTORY_FILE);
if (!NT_SUCCESS(Status))
{
KdPrint(("Open File Failed:0x%X", Status));
return Status;
} KdPrint(("Open File Success!")); WriteBuffer.QuadPart = ; Status = ZwWriteFile(hFile, NULL, NULL, NULL, &IoStatusBlock, (PVOID)strBuffer, , &WriteBuffer, NULL); //将strBuffer中的前16个字节写入文件,从文件的0位置开始写
if (!NT_SUCCESS(Status))
{
KdPrint(("WriteFile Failed, Error Code:0x%X", Status));
ZwClose(hFile);
return Status;
} ZwClose(hFile);
return Status;
} VOID MyUnload(PDRIVER_OBJECT pDriverObject)
{
KdPrint(("Unload MyCreateFile.sys Success"));
} NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
pDriverObject->DriverUnload = MyUnload; MyOpenFile();
MyCreateFile();
MyOpenFile(); MyReadFile();
MyWriteFile();
MyReadFile(); MyZwSetInfomationFile(); return STATUS_SUCCESS;
}
MyCreateFile.c
文件的操作函数有:
ZwCreateFile //创建文件或者打开文件
ZwOpenFile //打开文件
ZwQueryInformationFile //查看文件信息
ZwSetInformationFile //设置文件信息
ZwReadFile //读取文件
ZwWriteFile //写入文件
创建或打开文件ZwCreateFile:
NTSTATUS ZwCreateFile(
_Out_ PHANDLE FileHandle, //文件句柄
_In_ ACCESS_MASK DesiredAccess, //访问权限,一般为GENERIC_ALL,即所有权限
_In_ POBJECT_ATTRIBUTES ObjectAttributes, //文件对象的属性,需要用InitializeObjectAttributes来初始化
_Out_ PIO_STATUS_BLOCK IoStatusBlock, //用于接收返回信息
_In_opt_ PLARGE_INTEGER AllocationSize,
7 _In_ ULONG FileAttributes, //FILE_ATTRIBUTE_NORMAL
_In_ ULONG ShareAccess, //FILE_SHARE_READ
_In_ ULONG CreateDisposition, //FILE_OPEN_IF 如果没有文件,创建文件。如果有文件,直接打开
_In_ ULONG CreateOptions, //FILE_NON_DIRECTORY_FILE 不是目录
_In_opt_ PVOID EaBuffer, //NULL
_In_ ULONG EaLength //
);
其中的第三个参数ObjectAttributes需要使用函数InitializeObjectAttributes来初始化,函数参数:
VOID InitializeObjectAttributes(
[out] POBJECT_ATTRIBUTES InitializedAttributes, //文件对象指针
[in] PUNICODE_STRING ObjectName, //文件路径及名称
[in] ULONG Attributes, //flag,一般是OBJ_CASE_INSENSITIVE(大小写不敏感)
[in] HANDLE RootDirectory, //根目录,如果ObjectName是绝对路径的话,那么根目录就是NULL
[in, optional] PSECURITY_DESCRIPTOR SecurityDescriptor //默认为NULL
);
打开文件函数ZwOpenFile:
NTSTATUS ZwOpenFile(
_Out_ PHANDLE FileHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_ ULONG ShareAccess,
_In_ ULONG OpenOptions //和ZwCreateFile的CreateOptions参数相同. FILE_NON_DIRECTORY_FILE 不是目录
);
获取文件属性函数ZwQueryInformationFile:
NTSTATUS ZwQueryInformationFile(
_In_ HANDLE FileHandle,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_Out_ PVOID FileInformation, //接收文件相应FileInformationClass信息的结构
_In_ ULONG Length, //FileInformation的大小
_In_ FILE_INFORMATION_CLASS FileInformationClass //指定获取文件什么信息(FileInformation)的枚举值
);
设置文件属性函数ZwSetInformationFile:
NTSTATUS ZwSetInformationFile(
_In_ HANDLE FileHandle,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_ PVOID FileInformation,
_In_ ULONG Length,
_In_ FILE_INFORMATION_CLASS FileInformationClass
);
读取文件函数ZwReadFile:
NTSTATUS ZwReadFile(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_Out_ PVOID Buffer, //保存读取到的
_In_ ULONG Length, //从文件读取多少个字节
_In_opt_ PLARGE_INTEGER ByteOffset, //从文件的哪个位置开始读取,传入一个LARGE_INTEGER的指针
_In_opt_ PULONG Key //NULL
);
写入文件函数ZwWriteFile:
NTSTATUS ZwWriteFile(
_In_ HANDLE FileHandle,
_In_opt_ HANDLE Event,
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
_In_ PVOID Buffer,
_In_ ULONG Length,
_In_opt_ PLARGE_INTEGER ByteOffset,
_In_opt_ PULONG Key
);
有些地方可能现在还不太清楚,以后再回来补吧。
操作部分:
启动并按章MyCreateFile.sys驱动后,C盘生成了test.txt的文件

这个文件是只读的,并且是隐藏的:

test.txt文件中写着“ahuakndkaj.;'? "

DbgView输出:

0. 没有相应文件时,MyOpenFile里 ZwOpenFile打开文件失败
1. MyCreateFile里 ZwCreateFile创建文件成功
2. MyOpenFile里 ZwOpenFile打开文件成功
3. MyReadFile里 ZwOpenFile打开文件成功
4. MyReadFile里 ZwReadFile读取文件失败 这时文件中还没有数据
5. MyWriteFile里 ZwOpenFile打开文件成功 没输出错误 说明ZwWriteFile也成功了
6. MyReadFile里 ZwReadFile读取文件成功
7. MyReadFile里 读取到了数据
8. MyZwQueryInfomationFile里 打开文件成功
9. 获取文件属性成功 没输出错误 说明MyZwSetInfomationFile也成功了
10. 驱动卸载成功
梦织未来Windows驱动编程 第06课 驱动对磁盘文件的操作的更多相关文章
- 梦织未来Windows驱动编程 第03课 驱动的编程规范
最近根据梦织未来论坛的驱动教程学习了一下Windows下的驱动编程,做个笔记备忘.这是第03课<驱动的编程规范>. 驱动部分包括基本的驱动卸载函数.驱动打开关闭读取写入操作最简单的分发例程 ...
- 梦织未来Windows驱动编程 第05课 小结(读取另一驱动,遍历所有驱动)
读取另一驱动 驱动通过"\\Driver\\XueTr"获取到了XueTr工具的驱动,并Hook了XueTr驱动的分发函数. 具体的驱动代码如下: //FilterDriver.c ...
- 梦织未来Windows驱动编程 第04课 驱动相关的数据结构
- 《天书夜读:从汇编语言到windows内核编程》五 WDM驱动开发环境搭建
(原书)所有内核空间共享,DriverEntery是内核程序入口,在内核程序被加载时,这个函数被调用,加载入的进程为system进程,xp下它的pid是4.内核程序的编写有一定的规则: 不能调用win ...
- Linux设备驱动编程之复杂设备驱动
这里所说的复杂设备驱动涉及到PCI.USB.网络设备.块设备等(严格意义而言,这些设备在概念上并不并列,例如与块设备并列的是字符设备,而PCI.USB设备等都可能属于字符设备),这些设备的驱动中又涉及 ...
- (转)Windows驱动编程基础教程
版权声明 本书是免费电子书. 作者保留一切权利.但在保证本书完整性(包括版权声明.前言.正文内容.后记.以及作者的信息),并不增删.改变其中任何文字内容的前提下,欢迎任何读者 以任何形式(包括 ...
- Windows游戏编程之从零开始d
Windows游戏编程之从零开始d I'm back~~恩,几个月不见,大家还好吗? 这段时间真的好多童鞋在博客里留言说或者发邮件说浅墨你回来继续更新博客吧. woxiangnifrr童鞋说每天都在来 ...
- 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)
这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...
- 驱动编程思想之初体验 --------------- 嵌入式linux驱动开发之点亮LED
这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...
随机推荐
- Docker版本
第一次接触到安装docker的时候,网上的 安装 有 lxc-docker, docker-engine, docker.io, docker-ce 这些包,肯定会有些迷糊.读完这篇文章你就清楚了. ...
- SPI编程
#include <stdio.h>#include <wiringPi.h>#include <wiringPiSPI.h> int main(void){ un ...
- Pillow的安装和使用
需要把一段文字转换成图片,我找到了PIL(Python Imaging Library)库,专门干这个用的.还有一个Pillow是“friendly PIL fork”,于是我选择了后者. 安装过程稍 ...
- P1168 中位数(对顶堆)
题意:维护一个序列,两种操作 1.插入一个数 2.输出中位数(若长度为偶数,输出中间两个较小的那个) 对顶堆 维护一个小根堆,一个大根堆,大根堆存1--mid,小根堆存mid+1---n 这样堆顶必有 ...
- mysql中group by分组
为了测试group by语句,我们首先创建一个表: 然后向表内添加数据: 然后我们查看一下表的内容 接着我们分别按照性别和年龄对这个表进行分组; 我们可以看到表内的数据没有原表的多了,原因就是分组有去 ...
- Java基础笔记(十二)——方法
方法:实现一个功能. 方法声明: 访问修饰符 返回类型 方法名(参数列表){ //方法体 } 访问修饰符:public.private.protect.default 返回类型:void——无返 ...
- 《SQL 进阶教程》 自连接分组排序:练习题1-2-2
分组排序 SELECT d1.district, d1. NAME, (SELECT COUNT(d2.price) FROM district_products d2 WHERE d2.price ...
- screen命令常用参数使用
screen简要说明 screen 会话命令可以保持本地和服务器断开后,程序继续在服务器上运行,并且运行结束后,输出最后的结果.功能结果相当于 nohup command &,但是功能远比no ...
- scala数据类型
# Scala数据类型 ## 1.数值类型 ### 1.1 与Java一样Scala也有8种数值类型 * Byte * Char * Short * Int * Long * Float * Doub ...
- Spring学习(六)整合web开发
https://www.cnblogs.com/Leo_wl/p/4459274.html 1.加载Spring核心配置文件 //1.加载Spring配置文件,根据创建对对象 ApplicationC ...