首页 > 代码库 > 内核模式下的文件操作

内核模式下的文件操作

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

 

示例代码:

  1. VOID);  
  2.  hFile;  
  3.     IO_STATUS_BLOCK iostatus;  
  4.  (!NT_SUCCESS(status))  
  5.     {  
  6. ));  
  7.     }  
  8.   
  9.     {  
  10. ));  
  11.     }  
  12.   
  13.   
  14.   
  15.   
  16.   
  17.     ZwClose(hFile);  
  18. }  
  19. 除了可以用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;

    示例代码:

    1. VOID);  
    2.  hFile;  
    3.     IO_STATUS_BLOCK iostatus;  
    4.   
    5.  (!NT_SUCCESS(status))  
    6. ));  
    7.   
    8. ));  
    9.   
    10. (FILE_BASIC_INFORMATION), FileBasicInformation);  
    11.    
    12.  (NT_SUCCESS(status))  
    13.     {  
    14. ));  
    15.     }  
    16.   
    17. (FILE_BASIC_INFORMATION),FileBasicInformation);  
    18.  (NT_SUCCESS(status))  
    19. ));  
    20.   
    21. }  
    22. 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
          );

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

      示例代码:

      1. #define BUFFER_SIZE 1024#pragma INITCODEVOID);  
      2.  hFile;  
      3.          IO_STATUS_BLOCK iostatus;  
      4.   
      5.   
      6.  pBuffer = ()ExAllocatePool(PagedPool, BUFFER_SIZE);  
      7.          RtlFillMemory(pBuffer, BUFFER_SIZE, );  
      8.   
      9.          status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus, pBuffer, BUFFER_SIZE, NULL, NULL);  
      10.   
      11.          RtlFillMemory(pBuffer, BUFFER_SIZE, );  
      12.   
      13.          ZwClose(hFile);  
      14.   
      15.          ExFreePool(pBuffer);  
      16. }  
      17. 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来实现。

        示例代码:

        1. #pragma INITCODEVOID);  
        2.    
        3.  hFile;  
        4.   
        5.          NTSTATUS status = ZwCreateFile(&hFile, GENERIC_READ, &objattr, &iostatus, NULL,   
        6.   
        7.          FILE_STANDARD_INFORMATION fsi;  
        8. (FILE_STANDARD_INFORMATION), FileStandardInformation);  
        9.    
        10.   
        11.           pBuffer = ()ExAllocatePool(PagedPool, ()fsi.EndOfFile.QuadPart);  
        12.   
        13. )fsi.EndOfFile.QuadPart, NULL, NULL);  
        14.          KdPrint((  
        15.   
        16. }  

     

     

内核模式下的文件操作