内核模式下的文件操作 (Windows 驱动开发技术详解)

 这篇文章 是根据张帆老师 一书 《Windows 驱动开发技术详解》 写出的

买这本书 很久了  一直 都感觉看视频好一些   偶然 翻了这本书  发现真的是神书

然后 先说文件的创建

文件创建 也就是  

NTSTATUS ZwCreateFile(
  _Out_    PHANDLE            FileHandle,
  _In_     ACCESS_MASK        DesiredAccess,
  _In_     POBJECT_ATTRIBUTES ObjectAttributes,
  _Out_    PIO_STATUS_BLOCK   IoStatusBlock,
  _In_opt_ PLARGE_INTEGER     AllocationSize,
  _In_     ULONG              FileAttributes,
  _In_     ULONG              ShareAccess,
  _In_     ULONG              CreateDisposition,
  _In_     ULONG              CreateOptions,
  _In_opt_ PVOID              EaBuffer,
  _In_     ULONG              EaLength
);

第一个参数 是 返回打开文件的句柄  

第二个 是指定的操作 一般是   对文件的描述  读是 GENERIC_READ  然后写的话 是 GENERIC_WRITE  

第三个参数 是 OBJECT_ATTRIBUTES的地址   这个结构包含了 要打开的文件名 

第四个参数是 指向一个IO_STATUS_BLOCK结构  该结构接收的是  zwcreatfile 的操作结果状态 

然后第五个 参数是 一个指针 指向初始文件分配大小如果是0  那么文件长度 从0 开始  并随着 写入而增加  

第六个 是 0或者FILE_ATTRIBUFE_NORMAL   指定新创建文件的属性 

第七个 指定文件的属性  0 或者FILE_SHARE_READ  指定共享属性

第八个 是 指定文件存在或不存在 怎么处理  FILE_OPEN 就是 打开文件 如果错误 就返回失败  FILE_OVERWRITE_IF 

第九个是 指定 控制打开的操作   一般是FILE_SYNCHRONOUS_IO_NONALERT

第十个是 一个指针  可以指向 可选的扩展属性区

第十一个 是扩展属性区的长度

然后根据 第三个长度 可以 用 initializeObjectAttributes  来初始化 

然后文件的打开 可以用上面的 也可以用 zwopenfile  参数的话 就不一一介绍了

可以用 zwsetinformationfile 来获取文件属性  可以用 zwquertinformationfile 来修改文件属性

然后也可以用文件写的话 可以用 ZwWritefile  然后 读的话 可以用 zwreadfile  

然后下面就是代码实例

#include<ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	KdPrint(("驱动开始卸载!")); 

}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
	OBJECT_ATTRIBUTES object;
	IO_STATUS_BLOCK io;
	HANDLE hfile;
	UNICODE_STRING log;
	//初始化字符串
	RtlInitUnicodeString(&log, L"\\??\\C:\\1.log");
	//初始化objectattributes 
	InitializeObjectAttributes(&object, &log, OBJ_CASE_INSENSITIVE, NULL, NULL);
	//创建文件
	NTSTATUS NT = ZwCreateFile(&hfile,
		GENERIC_WRITE,
		&object,
		&io,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ,
		FILE_OPEN_IF,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);
      //如果第二个参数 换成GENERIC_READ   第八个参数 换成 FILE_OPEN 的话  那么这个就是打开程序了
	if (NT_SUCCESS(NT))
	{
		KdPrint(("文件创建成功!"));

	}
	else
	{
		KdPrint(("文件创建失败!"));

	}
	ZwClose(hfile);
}

然后下面的话 是 ZwOpenFile  

这个其实还是蛮简单的  就注意第二个参数  是打开的权限 一般设为 GENERIC_ALL 

然后 我们编写代码 如下  

#include<ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	KdPrint(("驱动开始卸载!")); 

}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
	OBJECT_ATTRIBUTES object;
	IO_STATUS_BLOCK io;
	HANDLE hfile;
	UNICODE_STRING log;
	//初始化字符串
	RtlInitUnicodeString(&log, L"\\??\\C:\\1.log");
	//初始化objectattributes 
	InitializeObjectAttributes(&object, &log, OBJ_CASE_INSENSITIVE, NULL, NULL);
	//创建文件
/*	NTSTATUS NT = ZwCreateFile(&hfile,
		GENERIC_WRITE,
		&object,
		&io,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ,
		FILE_OPEN_IF,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);*/
	NTSTATUS NT = ZwOpenFile(&hfile,
		GENERIC_ALL,
		&object,
		&io,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		FILE_SYNCHRONOUS_IO_NONALERT);
      //如果第二个参数 换成GENERIC_READ   第八个参数 换成 FILE_OPEN 的话  那么这个就是打开程序了
	if (NT_SUCCESS(NT))
	{
		KdPrint(("文件打开成功!"));

	}
	else
	{
		KdPrint(("文件打开失败!"));

	}
	ZwClose(hfile);
	driver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

然后下面的是  修改或 获取文件属性  获取 和修改的函数 参数其实差不多 唯一要注意的是 第三个 参数 

算是一个输出数据 或者输入数据 里面存储这   有三个不同的结构  根据结构不同 输出的也不同

第一个结构体是 FILEStandardInformation    

  为文件分配的大小 然后有多少文件链接  是否准备删除 是否为目录  

第二个   是FilebasicInformation  

文件创建的时间  最后访问时间 最后写时间  修改修改时间 文件属性

第三个是filenameInformation  这个是

文件长度  文件名  。

第四个是FilePositionInformation  

里面就有一个当前文件指针的位置 

然后  演示 ZwQueryInformationFile 函数 查询 修改文件属性 

#include<ntddk.h>
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	KdPrint(("驱动开始卸载!")); 

}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
	OBJECT_ATTRIBUTES object;
	IO_STATUS_BLOCK io;
	HANDLE hfile;
	UNICODE_STRING log;
	//初始化字符串
	RtlInitUnicodeString(&log, L"\\??\\C:\\1.log");
	//初始化objectattributes 
	InitializeObjectAttributes(&object, &log, OBJ_CASE_INSENSITIVE, NULL, NULL);
	//创建文件
      NTSTATUS NT = ZwCreateFile(&hfile,
		GENERIC_READ,
		&object,
		&io,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		0,
		FILE_OPEN,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);
	if (NT_SUCCESS(NT))
	{
		KdPrint(("文件打开成功!"));

	}
	else
	{
		KdPrint(("文件打开失败!"));
		ZwClose(hfile);
		driver->DriverUnload = DriverUnload;
		return STATUS_SUCCESS;

	}
	FILE_STANDARD_INFORMATION fsi;
	NT = ZwQueryInformationFile(hfile,
		&io,
		&fsi,
		sizeof(FILE_STANDARD_INFORMATION),
		FileStandardInformation);
	if (NT_SUCCESS(NT))
	{
		
		KdPrint(("file length:%u\n", fsi.EndOfFile.QuadPart));

	}
	else
	{
		KdPrint(("获取文件信息失败!"));
	}
	FILE_POSITION_INFORMATION fpi;
	fpi.CurrentByteOffset.QuadPart = 100i64;
	NT = ZwSetInformationFile(hfile,
		&io,
		&fpi,
		sizeof(FILE_POSITION_INFORMATION),
		FilePositionInformation);
	if (NT_SUCCESS(NT))
	{
		KdPrint(("文件指针已经确定!"));
	}
	ZwClose(hfile);
	driver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

 

下面就是文件的读写操作  

直接撸代码把  这里面的参数 都挺简单明了的

#include<ntddk.h>
#define BUFFER_SIZE 1024
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	KdPrint(("驱动开始卸载!")); 

}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
	OBJECT_ATTRIBUTES object;
	IO_STATUS_BLOCK io;
	HANDLE hfile;
	UNICODE_STRING log;
	//初始化字符串
	RtlInitUnicodeString(&log, L"\\??\\C:\\1.log");
	//初始化objectattributes 
	InitializeObjectAttributes(&object, &log, OBJ_CASE_INSENSITIVE, NULL, NULL);
	//创建文件
      NTSTATUS NT = ZwCreateFile(&hfile,
		GENERIC_WRITE,
		&object,
		&io,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_WRITE,
		FILE_OPEN_IF,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);
	if (NT_SUCCESS(NT))
	{
		KdPrint(("文件打开成功!"));

	}
	else
	{
		KdPrint(("文件打开失败!"));
		ZwClose(hfile);
		driver->DriverUnload = DriverUnload;
		return STATUS_SUCCESS;

	}
	PUCHAR pbuffer = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE);//在堆中分配内存
	RtlFillMemory(pbuffer, BUFFER_SIZE, 0xaa);
	KdPrint(("我们要写入%d字节", BUFFER_SIZE));
	ZwWriteFile(hfile, NULL, NULL, NULL, &io, pbuffer, BUFFER_SIZE, NULL, NULL);
	KdPrint(("实际写入了%d 字节", io.Information));
	RtlFillMemory(pbuffer, BUFFER_SIZE, 0xbb);
	KdPrint(("我们要追加写入%d字节", BUFFER_SIZE));
	LARGE_INTEGER number;//这个是倒数第二个参数  表示 文件从那里写
	number.QuadPart = 1024i64;
	ZwWriteFile(hfile, NULL, NULL, NULL, &io, pbuffer, BUFFER_SIZE, &number, NULL);
	KdPrint(("这个实际写了%d字节", io.Information));
	ZwClose(hfile);
	driver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}
#include<ntddk.h>
#define BUFFER_SIZE 1024
VOID DriverUnload(PDRIVER_OBJECT driver)
{
	KdPrint(("驱动开始卸载!")); 

}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
	OBJECT_ATTRIBUTES object;
	IO_STATUS_BLOCK io;
	HANDLE hfile;
	UNICODE_STRING log;
	//初始化字符串
	RtlInitUnicodeString(&log, L"\\??\\C:\\1.log");
	//初始化objectattributes 
	InitializeObjectAttributes(&object, &log, OBJ_CASE_INSENSITIVE, NULL, NULL);
	//创建文件
      NTSTATUS NT = ZwCreateFile(&hfile,
		GENERIC_READ,
		&object,
		&io,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ,
		FILE_OPEN,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);
	if (NT_SUCCESS(NT))
	{
		KdPrint(("文件打开成功!"));

	}
	else
	{
		KdPrint(("文件打开失败!"));
		ZwClose(hfile);
		driver->DriverUnload = DriverUnload;
		return STATUS_SUCCESS;

	}
	FILE_STANDARD_INFORMATION fsi;
	NT = ZwQueryInformationFile(hfile,
		&io,
		&fsi,
		sizeof(FILE_STANDARD_INFORMATION),
		FileStandardInformation);
	KdPrint(("这次我们想读%d 字节",fsi.EndOfFile.QuadPart));
	PUCHAR pbuffer = (PUCHAR)ExAllocatePool(PagedPool, (LONG)fsi.EndOfFile.QuadPart);//在堆中分配内存
	ZwReadFile(hfile,
		NULL,
		NULL,
		NULL,
		&io,
		pbuffer,
		(LONG)fsi.EndOfFile.QuadPart,
		NULL,
		NULL);
	KdPrint(("这次真正读了%d bytes\n", io.Information));
	ZwClose(hfile);
	ExFreePool(pbuffer);
	driver->DriverUnload = DriverUnload;
	return STATUS_SUCCESS;
}

 

这里是效果图 。。。

在xp下 完美运行 其它 不好说 最好在  搞个快照 看看  

不要脸的 挂个原创 嘿嘿。。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值