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

示例代码:

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;

示例代码:

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

内核模式下的文件操作相关推荐

  1. Linux内核态下的文件操作

    在VFS的支持下,用户态进程读写任何类型的文件系统都可以使用read和write着两个系统调用,但是在linux内核中没有这样的系统调用我们如何操作文件呢?我们知道read和write在进入内核态之后 ...

  2. OpenMP模式下多线程文件操作 (转)

    项目背景: 为了提升项目的运行效率,考虑多线程技术.最近OpenMP技术很热,咱也凑凑热闹,也为了充分发挥电脑硬件的能力. 硬件: 酷睿2双核 2.2GHz 3G 内存 软件: Visual Stud ...

  3. 内核模式下的字符串操作

    1)ASCII字符串和宽字符串    在应用程序中使用两种字符: a) char型字符串,负责记录ANSI字符集,它是指向一个char数组的指针,每个char型变量大小是一个字节,字符串是以0标志字符 ...

  4. Windows驱动开发 - 内核模式下的字符串操作

    1 ASCII字符串和宽字符串 char型,记录ansi字符集.每个字符一个字节.以0标志结束.在KdPrint中用%s输出. 宽字符型,wchar_t,描述unicode字符集的字符串,每个字符两个 ...

  5. Linux下对文件操作时出现乱码怎么办?

    Linux下对文件操作经常会遇见乱码问题,我在网上搜了一些解决方法,希望能对大家有所帮助. 如果你需要在Linux中操作windows下的文件,那么你可能会经常遇到文件编码转换的问题.Windows中 ...

  6. linux 返回非法指令,linux – ARM Cortex A7在内核模式下返回PMCCNTR = 0,在用户模式下返回非法指令(即使在PMUSERENR = 1之后)...

    我想在Raspberry Pi 2上读取循环计数寄存器(PMCCNTR),它有一个ARM Cortex A7内核.我为它编译了一个内核模块,如下所示: #include #include int in ...

  7. SpringBoot打开resources目录下的文件操作

    SpringBoot打开resources目录下的文件操作 背景 我想在SpringBoot项目中放入一个静态文件.json文件.然后在SpringBoot项目内可以打开并读取此json文件. [外链 ...

  8. linux下怎么批量命名文件,linux下的文件操作——批量重命名

    概述:在日常工作中,我们经常需要对一批文件进行重命名操作,例如将所有的jpg文件改成bnp,将名字中的1改成one,等等.文本主要为你讲解如何实现这些操作 1.删除所有的 .bak 后缀: renam ...

  9. 在windows内核模式下隐藏进程

    进程隐藏之内核实现 1.在内核模式下,系统为每个进程维护了一个EPROCESS结构体,系统所有的进程是通过EPROCESS结构体中的一个ActiveProcessLinks指向的双端链表连接起来的,通 ...

最新文章

  1. 计算机网络通信的仿真,计算机网络虚拟仿真技术研究与应用.doc
  2. echarts - 使用echarts过程中遇到的问题(pending...)
  3. openssl-1.0.1e for arm
  4. 互联网晚报 | 9月13日 星期一 | 美赞臣中国易主春华资本;美团外卖首次公开骑手配送时间算法;北京教培行业开展同业互助...
  5. PearProject 安装指南
  6. Android 建立Menu选单onOptionsItemSelected (转)
  7. sqlserver 迁移
  8. c语言c99标准_C语言的三套标准:C89、C99和C11
  9. 学生管理系统 c语言版
  10. 计算机毕业设计ssm高校学报管理系统lt10k系统+程序+源码+lw+远程部署
  11. Java实现医疗系统
  12. 上帝之眼——GIS技术的决定性作用
  13. mysql -省市区(市)
  14. 1304 佳佳的斐波那契(矩阵乘法)
  15. 语音助手——QU——语义角色标注及其应用
  16. Csapp 第三章阅读以及思考
  17. 隐形降权宝贝快速恢复攻略在此!
  18. Accelerating Video Object Segmentation with Compressed Video环境配置
  19. 细粒度分类:DBTNet(Deep Bilinear Transform)(一)论文解读
  20. neo4j Desktop桌面版的下载与使用(windows版本)【下】

热门文章

  1. 纤涂覆层材料的研究与总结
  2. 联想超融合,打通智慧医疗的“症结”
  3. 【原创】分享一些机器学习和深度学习的学习资料
  4. Supervisor 进程管理工具
  5. zabbix聚合图形创建脚本
  6. 安装Ruby和Rails运行环境
  7. 地球椭球体(Ellipsoid)、大地基准面(Datum)及地图投影(Projection)三者的基本概念
  8. DBA工具——DMV——通过sys.dm_exec_procedure_stats查看存储过程执行信息
  9. C++ VARIANT 学习小记录
  10. 逆向思维--魔兽世界封包分析(1)