内核模式下的文件操作
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);
- hFile;
- IO_STATUS_BLOCK iostatus;
- (!NT_SUCCESS(status))
- {
- ));
- }
- {
- ));
- }
- 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);
- hFile;
- IO_STATUS_BLOCK iostatus;
- (!NT_SUCCESS(status))
- ));
- ));
- (FILE_BASIC_INFORMATION), FileBasicInformation);
- (NT_SUCCESS(status))
- {
- ));
- }
- (FILE_BASIC_INFORMATION),FileBasicInformation);
- (NT_SUCCESS(status))
- ));
- }
- 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记录实际写了多少字节。
示例代码:
- #define BUFFER_SIZE 1024#pragma INITCODEVOID);
- hFile;
- IO_STATUS_BLOCK iostatus;
- pBuffer = ()ExAllocatePool(PagedPool, BUFFER_SIZE);
- RtlFillMemory(pBuffer, BUFFER_SIZE, );
- status = ZwWriteFile(hFile, NULL, NULL, NULL, &iostatus, pBuffer, BUFFER_SIZE, NULL, NULL);
- RtlFillMemory(pBuffer, BUFFER_SIZE, );
- 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 INITCODEVOID);
- hFile;
- NTSTATUS status = ZwCreateFile(&hFile, GENERIC_READ, &objattr, &iostatus, NULL,
- FILE_STANDARD_INFORMATION fsi;
- (FILE_STANDARD_INFORMATION), FileStandardInformation);
- pBuffer = ()ExAllocatePool(PagedPool, ()fsi.EndOfFile.QuadPart);
- )fsi.EndOfFile.QuadPart, NULL, NULL);
- KdPrint((
- }