Windows 内核编程并没有提供像 Ring3 层的 CopyFile 这样的 API,看了看书中的例子自己写了一份 MyCopyFile,以后用来备用。
代码语言:javascript复制#include <ntddk.h>
#ifndef MEM_TAG
#define MEM_TAG 'MyTt'
#endif
NTSTATUS MyOpenFile(
HANDLE* handle,
IO_STATUS_BLOCK* io_status,
CONST PUNICODE_STRING file_path)
{
NTSTATUS status;
OBJECT_ATTRIBUTES object_attributes;
InitializeObjectAttributes(
&object_attributes,
file_path,
OBJ_CASE_INSENSITIVE OBJ_KERNEL_HANDLE,
NULL, NULL);
status = ZwCreateFile(
handle, // 文件句柄
GENERIC_READ GENERIC_WRITE, // 打开文件的权限
&object_attributes, // 文件对象的描述信息
io_status, // 操作结果结构体
NULL, // 文件创建后的初始大小
FILE_ATTRIBUTE_NORMAL, // 文件属性信息
FILE_SHARE_READ, // 其他文件打开时的属性
FILE_OPEN_IF, // 如果文件存在,则打开;如果不存在,则创建
FILE_NON_DIRECTORY_FILE FILE_RANDOM_ACCESS FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
return status;
}
NTSTATUS MyCopyFile(PUNICODE_STRING target_path, PUNICODE_STRING source_path)
{
NTSTATUS status;
// 创建源文件和目标文件句柄
HANDLE target = NULL;
HANDLE source = NULL;
// buffer
PVOID buffer = NULL;
// offset
LARGE_INTEGER offset = { 0 };
// io_status
IO_STATUS_BLOCK io_status = { 0 };
#if DBG
_asm int 3
#endif
do
{
// 分别打开文件得到文件句柄
MyOpenFile(&source, &io_status, source_path);
MyOpenFile(&target, &io_status, target_path);
// 分配一个缓冲区用来存储每次读取的内容
buffer = (PWCHAR)ExAllocatePoolWithTag(NonPagedPool, 4096, MEM_TAG);
// ZwReadFile 和 ZwWriteFile 所需的两个参数
IO_STATUS_BLOCK IoStatus = { 0 };
ULONG length = 4 * 1024;
while (1)
{
// 读取
status = ZwReadFile(source, NULL, NULL, NULL,
&IoStatus, buffer, length, &offset, NULL);
if (!NT_SUCCESS(status))
{
if (status == STATUS_END_OF_FILE)
{
status = STATUS_SUCCESS;
}
break;
}
// 获取实际读到的大小
length = IoStatus.Information;
// 根据读取到的实际大小写入到另外一个文件中
status = ZwWriteFile(target, NULL, NULL, NULL,
&IoStatus, buffer, length, &offset, NULL);
if (!NT_SUCCESS(status))
break;
// offset 后移
offset.QuadPart = IoStatus.Information;
}
} while (0);
if (target != NULL)
ZwClose(target);
if (source != NULL)
ZwClose(source);
if (buffer != NULL)
ExFreePool(buffer);
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNICODE_STRING src = RTL_CONSTANT_STRING(L"\??\C:\1.txt");
UNICODE_STRING dst = RTL_CONSTANT_STRING(L"\??\C:\2.txt");
MyCopyFile(&dst, &src);
return STATUS_UNSUCCESSFUL;
}