内核模式下的文件操作

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指定新创建文件的属性,一般为0FILE_ATTRIBUTE_NORMAL

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

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

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

 

示例代码:

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不同而不同。

LengthFileInformation数据的长度

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;

示例代码:

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

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

示例代码:

#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来实现。

示例代码:

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux内核文件操作函数可以帮助我们在内核态对系统中的文件进行读取、写入、打开、关闭等许多操作。下面介绍几个常用的文件操作函数及其使用案例。 1. open()函数 该函数用于打开文件,可以根据需要进行读写和创建等不同的操作。其函数原型如下: ``` #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); ``` flags参数用来指定打开文件时的模式,常用的模式包括: * O_RDONLY:只读模式 * O_WRONLY:只写模式 * O_RDWR:读写模式 * O_CREAT:文件不存在时创建文件 * O_APPEND:追加模式 mode参数用来指定创建文件时的权限,常用的权限包括: * S_IRUSR:用户具有读取权限 * S_IWUSR:用户具有写入权限 * S_IXUSR:用户具有执行权限 * S_IRGRP:组具有读取权限 * S_IWGRP:组具有写入权限 * S_IXGRP:组具有执行权限 * S_IROTH:其他用户具有读取权限 * S_IWOTH:其他用户具有写入权限 * S_IXOTH:其他用户具有执行权限 下面是一个使用open()函数打开并读取文件的例子: ``` #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int fd, n; char buf[1024]; fd = open("test.txt", O_RDONLY); if (fd < 0) { perror("open"); exit(EXIT_FAILURE); } n = read(fd, buf, 1024); if (n < 0) { perror("read"); exit(EXIT_FAILURE); } printf("The content of test.txt is:\n%s", buf); close(fd); return 0; } ``` 2. read()函数 该函数用于从文件中读取数据。其函数原型如下: ``` #include <unistd.h> ssize_t read(int fd, void *buf, size_t count); ``` fd参数是文件描述符,buf参数是读取数据的缓冲区,count参数是要读取的字节数。 下面是一个使用read()函数读取文件的例子: ``` #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int fd, n; char buf[1024]; fd = open("test.txt", O_RDONLY); if (fd < 0) { perror("open"); exit(EXIT_FAILURE); } n = read(fd, buf, 1024); if (n < 0) { perror("read"); exit(EXIT_FAILURE); } printf("The content of test.txt is:\n%s", buf); close(fd); return 0; } ``` 3. write()函数 该函数用于将数据写入文件中。其函数原型如下: ``` #include <unistd.h> ssize_t write(int fd, const void *buf, size_t count); ``` fd参数是文件描述符,buf参数是要写入的数据的缓冲区,count参数是要写入的字节数。 下面是一个使用write()函数写入文件的例子: ``` #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int fd, n; char buf[1024] = "This is a test for write() function.\n"; fd = open("test.txt", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) { perror("open"); exit(EXIT_FAILURE); } n = write(fd, buf, sizeof(buf)); if (n < 0) { perror("write"); exit(EXIT_FAILURE); } close(fd); return 0; } ``` 4. close()函数 该函数用于关闭文件。其函数原型如下: ``` #include <unistd.h> int close(int fd); ``` fd参数是文件描述符。 下面是一个使用close()函数关闭文件的例子: ``` #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(void) { int fd, n; char buf[1024]; fd = open("test.txt", O_RDONLY); if (fd < 0) { perror("open"); exit(EXIT_FAILURE); } /* do something */ close(fd); return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值