ZwCreateFile -> ZwReadFile/ZwWriteFile (读文件/写文件)
读文件:
ZwReadFile(
//ZwCreateFile得到的文件句柄,如果是内核句柄,这创建文件和读取文件并不需要在同一个进程,是通用的.
_In_ HANDLE FileHandle,
//事件,用户异步完成读时,这里填 NULL
_In_opt_ HANDLE Event,
//回调例程,用于异步完成读时.这里填 NULL
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
_In_opt_ PVOID ApcContext,
//返回结果状态
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
//缓冲区,当读文件成功,内容会被保存在这个缓冲区中
_Out_writes_bytes_(Length) PVOID Buffer,
//描述缓冲区的长度,也是试图读取文件的长度
_In_ ULONG Length,
//要读取内容在文件中的偏移,一般不要设置为 NULL,文件句柄不一定支持直接读取当前的偏移
_In_opt_ PLARGE_INTEGER ByteOffset,
//读取文件时的附加信息,一般不使用,设置为 NULL
_In_opt_ PULONG Key
);
函数执行成功后返回 STATUS_SUCCESS .只要读取到字符,不管是否符合指定长度都返回成功,即使试图读取长度超过文件长度.
电子书教材没有写出完整的代码,简直了.最终实现复制文件的完整代码如下,原始文件是1.txt,目标文件是2.txt:
#include
VOID DriverUnload(PDRIVER_OBJECT driver){
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path){
//设置读取到文件保存数据的缓冲区
PVOID Buffer = ExAllocatePoolWithTag(NonPagedPool, 4*1024, 2333);
//返回状态 读写共用
IO_STATUS_BLOCK iostatus = { 0 };
//保存读取文件的偏移,以便下次从这里读取
LARGE_INTEGER offset = { 0 };
//实际读取的长度
ULONG length = 0;
//这个变量是全部函数返回共用的
NTSTATUS status;
//创建文件,oldfile newfile 先打开两个文件..
HANDLE yuanwenjian = NULL;
HANDLE mubiaowenjian = NULL;
//初始化
OBJECT_ATTRIBUTES old_object_attributes;
UNICODE_STRING old_ufile_name = RTL_CONSTANT_STRING(L"\\??\\C:\\1.txt");//使用对象路径
InitializeObjectAttributes(&old_object_attributes, &old_ufile_name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
//初始化
OBJECT_ATTRIBUTES new_object_attributes;
UNICODE_STRING new_ufile_name = RTL_CONSTANT_STRING(L"\\??\\C:\\2.txt");//使用对象路径
InitializeObjectAttributes(&new_object_attributes, &new_ufile_name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
//保存打开文件的返回状态
IO_STATUS_BLOCK oldstatus;
IO_STATUS_BLOCK newstatus;
status = ZwCreateFile(
&yuanwenjian,
GENERIC_READ | GENERIC_WRITE,
&old_object_attributes,
&oldstatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
status = ZwCreateFile(
&mubiaowenjian,
GENERIC_READ | GENERIC_WRITE,
&new_object_attributes,
&newstatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
);
//复制文件
while (1){
length = 4 * 1024;
status = ZwReadFile(yuanwenjian, NULL, NULL, NULL, &iostatus, Buffer, length, &offset, NULL);
if (!NT_SUCCESS(status)){
//如果状态为 STATUS_END_OF_FILE 说明拷贝完成
if (status == STATUS_END_OF_FILE){
status = STATUS_SUCCESS;
}
break;
}
//得到实际读取到的长度
length = (ULONG)iostatus.Information;
status = ZwWriteFile(mubiaowenjian, NULL, NULL, NULL, &iostatus, Buffer, length, &offset, NULL);
if (!NT_SUCCESS(status)){
break;
}
//设置新的偏移
offset.QuadPart += length;
}
//释放资源,关闭句柄
if (yuanwenjian != NULL){ ZwClose(yuanwenjian); }
if (mubiaowenjian != NULL){ ZwClose(mubiaowenjian); }
if (Buffer != NULL){ ExFreePool(Buffer); }
DbgPrint("misaka: finished\r\n");
driver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}