内核下的文件操作

内核下对文件创建和打开都是通过ZwCreateFile,这个内核函数返回一个文件句柄,文件的所有操作都是依靠这个句柄进行操作的。在文件操作完毕后,需要关闭这个句柄。

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

InitializedAttributes:返回的OBJECT ATTRIBUTES结构。
ObjectName:对象名称,用UNICODE STRING描述,这里设置的是文件名。
Attributes:一般设为OBJ_ CASE JINSENSTTIVE, 对大小写敏感。

另外,文件名必须是符号链接或者是设备名。符号链接的概念,已经在第4章中介绍
过。例如,盘符“c:” 就是一个符号链接。这里应该用“\??\c:” 代替,“c:\1.log”" 要写成
“\??\c:\1.log”。
其中,“\??\c:” 是符号链接,内核会将它转换成设备名“\Device\Harddisk\Volume1”。

#include <ntddk.h>

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	DbgPrint("驱动卸载成功");
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegPath)
{
	//在C盘创建一个文件
	HANDLE hFile = NULL;
	OBJECT_ATTRIBUTES objAttr = { 0 };
	UNICODE_STRING FileName;
	IO_STATUS_BLOCK ioStatus;
	NTSTATUS status = 0;
	pDriverObject->DriverUnload = DriverUnload;
	
	//路径 C:\1.log  符号名字需要这样写
	RtlInitUnicodeString(&FileName,L"\\??\\c:\\1.log");
		//初始化对象属性 是一个宏
	InitializeObjectAttributes(&objAttr,
							   &FileName, 
							   OBJ_CASE_INSENSITIVE,	//比较对象名时不区分大小写
							   0,
							   0);
	status = ZwCreateFile(  &hFile,			//返回来的文件句柄
							GENERIC_WRITE,
							&objAttr,
							&ioStatus,
							NULL,
							FILE_ATTRIBUTE_NORMAL,
							FILE_SHARE_READ,
							FILE_OPEN_IF,  //打开文件可以使用FILE_OPEN
							FILE_SYNCHRONOUS_IO_NONALERT,
							NULL,
							0
						);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("文件创建或者打开失败");
		return status;
	}

	ZwClose(hFile);
	return STATUS_SUCCESS;
}

打开文件还可以使用,相比ZwCreateFile,参数更加简化

NTSTATUS
ZwOpenFile (
	OUT PHANDLE FileHandle,
	IN ACCESS_MASK DesiredAccess,
	IN POBJECT_ATTRIBUTES ObjectAttributes,
	OUT PIO_STATUS_BLOCK IoStatusBlock,
	IN ULONG ShareAccess,
	IN ULONG OpenOptions
);

FileHandle:返回打开的文件句柄。
DesiredAccess:打开的权限,一般设为GENERIC_ALL。
ObjectAttributes: objectAttributes 结构。
loStatusBlock:指向-一个结构体的指针。该结构体指明打开文件的状态。
ShareAccess :共享的权限。可以是FILE_SHARE_READ或者
FILE_SHARE_WRITE。
OpenOptions:打开选项,一般 设为FILE_SYNCHRONOUS_IO_NONALERT.
返回值:指明文件是否被成打开。

ZwOpenFile( 
&hfile,
GENERIC_ALL,
&objectAttributes,
&iostatus, 
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT) ;

获取或修改文件的属性

获取和修改文件属性,包括获取文件大小、获取或修改文件指针位置、获取或修改文
件名、获取或修改文件属性(只读属性、隐藏属性)、获取或修改文件创建、修改日期等。
DDK提供了内核函数ZwSetInformationFile和ZwQueryInformationFile函数来进行获取和
修改文件属性。

设置文件信息

NTSYSAPI NTSTATUS ZwSetInformationFile(
  HANDLE                 FileHandle,
  PIO_STATUS_BLOCK       IoStatusBlock,
  PVOID                  FileInformation,
  ULONG                  Length,
  FILE_INFORMATION_CLASS FileInformationClass
);

FileHandle:文件句柄。
loStatusBlock:返回设置的状态。
FileInformation:依据FileInformationClass不同而不同。作为输入信息。
Length: FileInformation 数据的长度。
FileInformationClass:描述修改属性的类型。

查询文件信息

NTSYSAPI NTSTATUS ZwQueryInformationFile(
  HANDLE                 FileHandle,
  PIO_STATUS_BLOCK       IoStatusBlock,
  PVOID                  FileInformation,
  ULONG                  Length,
  FILE_INFORMATION_CLASS FileInformationClass
);

FileHandle:文件句柄。
loStatusBlock:返回设置的状态。
FileInformation:依据FileInformationClass不同而不同。作为输出信息。
Length: FileInformation 数据的长度。
FileInformationClass:描述修改属性的类型。

这两个函数的参数基本相同。其中FileInformationClass指定修改或者查询的类别。
(1)
当FileInformationClass是FileStandardInformation时,输入和输出的数据是FILE_STANDARD_INFORMATION (文件标准信息)结构体,描述文件的基本信息。

typedef struct FILE_STANDARD_INFORMATION {
	LARGE INTEGER AllocationSize; //	为文件分配的大小 (注意这个不是文件大小,而是占用簇所需要的大小)
	LARGE INTEGER EndofFile;			//距离文件结尾还有多少字节  打开文件就查询 可以通过这个值获得文件的大小
	ULONG NumberofLinks ;	//	有多少个链接文件
	BOOLEAN DeletePending ;	//是否准备删除
	BOOLEAN Directory;	//是否为目录
} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INPORMATION;

(2)
当FileInformationClass是FileBasicInformation 时,输入和输出的数据是FILE_
BASIC_ INFORMATION(文件基本信息)结构体,描述文件的基本信息。

typedef struct FILE BASIC INPORMATION {
	LARGE INTEGER CreationTime;	 //文件创建时间
	LARGE . INTEGER LastAccessTime;	//最后 访问时间
	LARGE INTEGER LastwriteTime;	//最后写时间
	LARGE INTEGER ChangeTime ;	//修改修改时间
	ULONG PileAttributest	//文件属性
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATTON;

其中,时间参数是从一个LARGE_INTEGER的整数,该整数代表从1601年经过多少
个100ns (纳秒)。FileAttributes 描述文件属性。FILE ATTRIBUTE NORMAL描述一般文
件。FILE_ATTRIBUTE_DIRECTORY描述是目录。FILE ATTRIBUTE_READONLY描述
该文件为只读。FILE_ ATTRIBUTE_HIDDEN代表隐含文件。FILE ATTRIBUTE _SYSTEM
代表系统文件。

(3)
当FileInformationClass 是FileNameInformation 时,输入和输出的数据是FILE_NAME_INFORMATION结构体,描述文名信息。

typedef struct FILE_NAME_INFORMATION{
	ULONG FileNameLength; //文件名长度
	WCHAR FileName[11]; // 文件名
} FILE_NAME_INFORMATTON, *PFILE_NAME_INFORMATION;

(4)
当FileInformationClass 是FilePositionInformation 时,输入和输出的数据是FILE_ POSITION_ INFORMATION结构体,描述文件名信息。


typedef struct FILE_POSITION_INFORMATION{
	LARGE_INTEGER CurrentByteOffset;//代表当前文件指针位置
} FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;

查询文件名

#include <ntddk.h>

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	DbgPrint("驱动卸载成功");
}


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegPath)
{
	//在C盘创建一个文件
	HANDLE hFile = NULL;
	OBJECT_ATTRIBUTES objAttr = { 0 };
	UNICODE_STRING FileName;
	IO_STATUS_BLOCK ioStatus;
	NTSTATUS status = 0;
	FILE_NAME_INFORMATION FileNameInfo = { 0 };

	pDriverObject->DriverUnload = DriverUnload;

	RtlInitUnicodeString(&FileName,L"\\??\\c:\\1.log");
	//初始化对象属性 主要提供了一个要打开的文件名
	InitializeObjectAttributes(&objAttr,
							   &FileName, 
							   OBJ_CASE_INSENSITIVE,	//比较对象名时不区分大小写
							   0,
							   0);
	//打开文件
	status = ZwCreateFile(  &hFile,
							GENERIC_READ,
							&objAttr,&ioStatus,
							NULL,
							FILE_ATTRIBUTE_NORMAL,
							0,
							FILE_OPEN,	//打开文件失败就报错
							FILE_SYNCHRONOUS_IO_NONALERT,
							0,
							0);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("文件打开失败");
		return status;
	}

	//查询文件信息
	status=ZwQueryInformationFile(hFile,
		&ioStatus,
		&FileNameInfo,	//根据最后一个参数的不同,这个参数就是不同结构的指针
		sizeof(FILE_NAME_INFORMATION), //最后一个参数对应接收的结构体大小。
		FileNameInformation);
	
	if (!FileNameInfo.FileName)
	{ 
		return STATUS_FILE_INVALID;
	}
	DbgPrint("文件名是:%S  文件名的长度:%x\n ", FileNameInfo.FileName,FileNameInfo.FileNameLength);
	ZwClose(hFile);
	return STATUS_SUCCESS;
}

文件写的操作

NTSYSAPI NTSTATUS ZwWriteFile(
  HANDLE           FileHandle,
  HANDLE           Event,
  PIO_APC_ROUTINE  ApcRoutine,
  PVOID            ApcContext,
  PIO_STATUS_BLOCK IoStatusBlock,
  PVOID            Buffer,
  ULONG            Length,
  PLARGE_INTEGER   ByteOffset,
  PULONG           Key
);

FilcHandle:文件打开的句柄。
Event:很少用到,一般设置为NULL。
ApcRoutine:很少用到,- -般设置为NULL。
ApcContext:很少用到,一般设置为NULL.
loStatusBlock:记录写操作的状态。其中,loStatusBlock.Infomation 记录实际写了
多少字节。
Buffer:从这个缓冲区开始往文件里写。)
Length:准备写多少字节。
ByteOffset:从文件的多少偏移地址开始写。
Key:很少用到,- -般设置为NULL。

#include <ntddk.h>

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	DbgPrint("驱动卸载成功");
}


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegPath)
{
	//在C盘创建一个文件
	HANDLE hFile = NULL;
	OBJECT_ATTRIBUTES objAttr = { 0 };
	UNICODE_STRING FileName;
	IO_STATUS_BLOCK ioStatus;
	NTSTATUS status = 0;
	FILE_NAME_INFORMATION FileNameInfo = { 0 };

	pDriverObject->DriverUnload = DriverUnload;

	RtlInitUnicodeString(&FileName,L"\\??\\c:\\1.log");
	//初始化对象属性 主要提供了一个要打开的文件名
	InitializeObjectAttributes(&objAttr,
							   &FileName, 
							   OBJ_CASE_INSENSITIVE,	//比较对象名时不区分大小写
							   0,
							   0);
	//打开文件
	status = ZwCreateFile(  &hFile,
		GENERIC_READ | GENERIC_WRITE,
							&objAttr,&ioStatus,
							NULL,
							FILE_ATTRIBUTE_NORMAL,
							0,
							FILE_OPEN,	//打开文件失败就报错
							FILE_SYNCHRONOUS_IO_NONALERT,
							0,
							0);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("文件打开失败");
		return status;
	}

	
	status=ZwWriteFile( hFile, 
						NULL,
						NULL,
						NULL, 
						&ioStatus, 
						"zheyangma", //写入的内容  也可以分配内存 然后填充内容
						6,			//写入的长度
						0, 
						0);

	if (!NT_SUCCESS(status))
	{
		DbgPrint("文件写入失败");
		
		ZwClose(hFile);
		return status;
	}

	
	ZwClose(hFile);
	return STATUS_SUCCESS;
}

文件读取

NTSYSAPI NTSTATUS ZwReadFile(
HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID Buffer,
ULONG Length,
PLARGE_INTEGER ByteOffset,
PULONG Key
);
在这里插入图片描述

练习:

在文件的末尾追加内容
#include <ntddk.h>

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	DbgPrint("驱动卸载成功");
}


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegPath)
{
	//在C盘创建一个文件
	HANDLE hFile = NULL;
	OBJECT_ATTRIBUTES objAttr = { 0 };
	UNICODE_STRING FileName;
	IO_STATUS_BLOCK ioStatus;
	NTSTATUS status = 0;
	FILE_NAME_INFORMATION FileNameInfo = { 0 };
	FILE_STANDARD_INFORMATION  fsi = { 0 };
	

	pDriverObject->DriverUnload = DriverUnload;

	RtlInitUnicodeString(&FileName,L"\\??\\c:\\1.log");
	//初始化对象属性 主要提供了一个要打开的文件名
	InitializeObjectAttributes(&objAttr,
							   &FileName, 
							   OBJ_CASE_INSENSITIVE,	//比较对象名时不区分大小写
							   0,
							   0);
	//打开文件
	status = ZwCreateFile(  &hFile,
		GENERIC_READ | GENERIC_WRITE,
							&objAttr,&ioStatus,
							NULL,
							FILE_ATTRIBUTE_NORMAL,
							0,
							FILE_OPEN,	//打开文件失败就报错
							FILE_SYNCHRONOUS_IO_NONALERT,
							0,
							0);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("文件打开失败");
		return status;
	}

	

	
	//查询文件大小
	ZwQueryInformationFile(hFile, &ioStatus, &fsi, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
	 
	
	//当前指针位置为文件尾。
	FILE_POSITION_INFORMATION fpi;
	fpi.CurrentByteOffset = fsi.EndOfFile;
	//设置文件指针
	ZwSetInformationFile(hFile, &ioStatus,&fpi , sizeof(FILE_POSITION_INFORMATION), FilePositionInformation);

	//把这个数组的内容追加到文件
	UCHAR arr[] = { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80 };
	status = ZwWriteFile(hFile,
		NULL,
		NULL,
		NULL,
		&ioStatus,
		arr, 
		17,			//写入的长度
		0,
		0);

	if (!NT_SUCCESS(status))
	{
		DbgPrint("文件写入失败");

		ZwClose(hFile);
		return status;
	}

	ZwClose(hFile);
	return STATUS_SUCCESS;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值