内核模式下的文件操作

xiaoxiao2021-02-27  178

1.文件的创建

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

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

 

FileHandle:返回打开文件的句柄

DesiredAccess: 一般指定为GENERIC_READ 或者 GENERIC_WRITE

ObjectAttributes:是OBJECT_ATTRIBUTES结构的地址,该结构包含要打开的文件名。

IoStatusBlock:指向一个IO_STATUS_BLOCK结构体,该结构接收ZwCreateFile操作的结果状态。

AllocationSize:是一个指针,指向一个64位整数,该数指定文件初始分配时的大小、该参数仅关系到创建或重写文件操作。如果忽略它,那么文件长度将从0开始,并随着写入而增长。

FileAttributes:指定新创建文件的属性,一般为0或FILE_ATTRIBUTE_NORMAL

ShareAccess:指定文件的共享方式,0或者FILE_SHARE_READ

CreateDisposition:指定当文件存在或不存在时,该如何处理

CreateOptions:FILE_SYNCHRONOUS_IO_NONALERT,指定控制打开操作和句柄使用的附加标志位。

EaBuffer:一个指针,指向可选的扩展属性区

EaLength:扩展属性区的长度

 

要创建的文件的文件名是通过第三个参数传入的。这个参数是一个OBJECT_ATTRIBUTES得结构。DDK提供了对OBJECT_ATTRIBUTES初始化的宏:

VOID    InitializeObjectAttributes(     OUT POBJECT_ATTRIBUTES  InitializedAttributes,     IN PUNICODE_STRING  ObjectName,//文件名    IN ULONG  Attributes,//一般为OBJ_CASE_INSENSITIVE,对大小写敏感    IN HANDLE  RootDirectory,//一般为NULL    IN PSECURITY_DESCRIPTOR  SecurityDescriptor //一般为NULL    );

 

示例代码:

 

[cpp] view plain copy  

VOID TetsCreateFile()  {      UNICODE_STRING string;      RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");        OBJECT_ATTRIBUTES objattr;      InitializeObjectAttributes(&objattr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL);         HANDLE hFile;      IO_STATUS_BLOCK iostatus;        NTSTATUS status = ZwCreateFile(&hFile, GENERIC_READ | GENERIC_WRITE, &objattr, &iostatus,                  NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);      if (!NT_SUCCESS(status))      {         KdPrint(("文件创建失败!\n"));      }      else      {         KdPrint(("文件创建成功!\n"));      }      //文件操作        //......        //关闭文件句柄      ZwClose(hFile);  }  

 

除了可以用ZwCreateFile函数打开文件,DDK还为我们提供了一个ZwOpenFile函数用来打开文件,以简化文件的打开操作。

NTSTATUS  ZwOpenFile(     OUT PHANDLE  FileHandle,     IN ACCESS_MASK  DesiredAccess, //打开权限,一般为GENERIC_ALL    IN POBJECT_ATTRIBUTES  ObjectAttributes,     OUT PIO_STATUS_BLOCK  IoStatusBlock,     IN ULONG  ShareAccess,     IN ULONG  OpenOptions//打开选项,一般为FILE_SYNCHRONOUS_IO_NONALERT    );

2.获取或修改文件属性

获取和修改文件属性,包括获取文件大小,获取或修改文件指针位置,获取或修改文件名,获取或修改文件属性(只读属性,隐藏属性),获取或修改文件创建,修改日期。

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

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

FileInformation:依据FileInformationClass不同而不同。

Length:FileInformation数据的长度

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_INFORMATION;

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

typedef struct FILE_BASIC_INFORMATION {   LARGE_INTEGER  CreationTime;   LARGE_INTEGER  LastAccessTime;   LARGE_INTEGER  LastWriteTime;   LARGE_INTEGER  ChangeTime;   ULONG  FileAttributes; //文件属性 } FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;

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

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

(4)   当FileInformationClass 是FilePositionInformation 时,输入和输出数据是FILE_POSITION_INFORMATION结构体,描述文件指针位置信息。

typedef struct FILE_POSITION_INFORMATION {   LARGE_INTEGER  CurrentByteOffset; //代表当期文件指针为止 } FILE_POSITION_INFORMATION, *PFILE_POSITION_INFORMATION;

示例代码:

 

[cpp] view plain copy  

VOID TetsFile()  {      UNICODE_STRING string;      RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");         OBJECT_ATTRIBUTES objattr;      InitializeObjectAttributes(&objattr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL);         HANDLE hFile;      IO_STATUS_BLOCK iostatus;         //打开文件      NTSTATUS status = ZwCreateFile(&hFile, GENERIC_READ, &objattr, &iostatus, NULL,       FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);           if (!NT_SUCCESS(status))      {         KdPrint(("文件打开失败!\n"));      }      else      {         KdPrint(("文件打开成功!\n"));            FILE_BASIC_INFORMATION fbi;               //查询文件基本信息         status = ZwQueryInformationFile(hFile, &iostatus, &fbi, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation);         if (NT_SUCCESS(status))      {         KdPrint(("查询文件属性成功!\n"));      }        //设置文件只读属性       fbi.FileAttributes |= FILE_ATTRIBUTE_READONLY;      status = ZwSetInformationFile(hFile, &iostatus, &fbi, sizeof(FILE_BASIC_INFORMATION),FileBasicInformation);        if (NT_SUCCESS(status))      {         KdPrint(("设置文件只读属性成功!\n"));      }      //关闭文件句柄      ZwClose(hFile);      }    }  

 

 

3.文件的写操作

NTSTATUS    ZwWriteFile(     IN HANDLE  FileHandle,     IN HANDLE  Event  OPTIONAL, //一般设为NULL     IN PIO_APC_ROUTINE  ApcRoutine  OPTIONAL, //一般设为NULL     IN PVOID  ApcContext  OPTIONAL, //一般设为NULL     OUT PIO_STATUS_BLOCK  IoStatusBlock, //记录实际写的字节数     IN PVOID  Buffer, //从这个缓冲区中开始往文件里写     IN ULONG  Length, //准备写多少字节     IN PLARGE_INTEGER  ByteOffset  OPTIONAL, //从文件的多少偏移开始写     IN PULONG  Key  OPTIONAL //一般设为NULL     );

IoStatusBlock:IoStatusBlock.Information记录实际写了多少字节。

示例代码:

 

[cpp] view plain copy  

#define BUFFER_SIZE 1024  #pragma INITCODE  VOID TetsFile()  {           UNICODE_STRING string;           RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");              OBJECT_ATTRIBUTES objattr;           InitializeObjectAttributes(&objattr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL);              HANDLE hFile;           IO_STATUS_BLOCK iostatus;              //打开文件           NTSTATUS status = ZwCreateFile(&hFile, GENERIC_WRITE, &objattr, &iostatus, NULL,        FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);                     //分配Buffer空间           PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool, BUFFER_SIZE);           RtlFillMemory(pBuffer, BUFFER_SIZE, 'A');           //写文件           status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus, pBuffer, BUFFER_SIZE, NULL, NULL);                     LARGE_INTEGER  ByteOffset;           ByteOffset.QuadPart = 1024i64; //设置文件指针偏移           RtlFillMemory(pBuffer, BUFFER_SIZE, 'B');              status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus, pBuffer, BUFFER_SIZE, &ByteOffset, NULL);           //关闭文件句柄           ZwClose(hFile);           //释放内存           ExFreePool(pBuffer);  }  

 

 

4.文件的读操作

NTSTATUS    ZwReadFile(     IN HANDLE  FileHandle,     IN HANDLE  Event  OPTIONAL,     IN PIO_APC_ROUTINE  ApcRoutine  OPTIONAL,     IN PVOID  ApcContext  OPTIONAL,     OUT PIO_STATUS_BLOCK  IoStatusBlock,     OUT PVOID  Buffer,     IN ULONG  Length,     IN PLARGE_INTEGER  ByteOffset  OPTIONAL,     IN PULONG  Key  OPTIONAL     );

如果需要读取整个文件,那么得知道文件的大小,我们可以用ZwQueryInformationFile来实现。

示例代码:

 

[cpp] view plain copy  

#pragma INITCODE  VOID TetsFile()  {           UNICODE_STRING string;           RtlInitUnicodeString(&string, L"\\??\\C:\\1.log");              OBJECT_ATTRIBUTES objattr;           InitializeObjectAttributes(&objattr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL);              HANDLE hFile;           IO_STATUS_BLOCK iostatus;              //打开文件           NTSTATUS status = ZwCreateFile(&hFile, GENERIC_READ, &objattr, &iostatus, NULL,        FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);              //获得文件的大小           FILE_STANDARD_INFORMATION fsi;           status = ZwQueryInformationFile(hFile, &iostatus, &fsi, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);              //分配Buffer空间           PUCHAR pBuffer = (PUCHAR)ExAllocatePool(PagedPool, (LONG)fsi.EndOfFile.QuadPart);                     //读文件           status = ZwReadFile(hFile, NULL, NULL, NULL, &iostatus, pBuffer, (LONG)fsi.EndOfFile.QuadPart, NULL, NULL);           KdPrint(("Read %d bytes\n", iostatus.Information));              //关闭文件句柄           ZwClose(hFile);           //释放内存           ExFreePool(pBuffer);  }   
转载请注明原文地址: https://www.6miu.com/read-10869.html

最新回复(0)