内核文件基本操作

调用:

KernelCopyFile(L"\??\C:\888.exe", L"\??\C:\567.exe");

注意点:

1、文件过大怎么读写?
readoffset.QuadPart = 0 这个是读取文件位置,如果读取的文件很大,可以通过这个参数来分批读入
2、ZwClose(hfile2); 最后不关闭句柄的效果
在这里插入图片描述

文件的打开,读取,创建,写入 都包含在这个函数

///KernelCopyFile内核拷贝函数
///执行流程基于旧文件的打开,旧文件内容的读取,新文件的创建最后新文件的写入
/// 参数1是新文件路径,参数2是旧文件路径
NTSTATUS KernelCopyFile(PWCHAR defile_path, PWCH sourcefile_path)
{
    
    
	NTSTATUS status = STATUS_SUCCESS;// 定义一个返回值
	
	HANDLE hfile1 = NULL; //定义一个句柄

	UNICODE_STRING sourcefilepath = {
    
     0 }; //源文件路径

	OBJECT_ATTRIBUTES obja1 = {
    
     0 }; //源文件参数

	IO_STATUS_BLOCK iostack1 = {
    
     0 };//旧文件操作记录

	RtlInitUnicodeString(&sourcefilepath, sourcefile_path);//初始化一个文件路径

	//初始化
	InitializeObjectAttributes(&obja1, &sourcefilepath, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL);

	//打开文件旧文件
	//参数1:文件句柄
	//参数2:访问权限
	//参数3:&iostack1 会记录这次操作的一些信息
	//参数4:FILE_SHARE_READ 共享读、FILE_SHARE_WRITE共享写
	status = ZwOpenFile(&hfile1, GENERIC_ALL, &obja1, &iostack1, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);

	// 判断打开文件是否成功
	if (!NT_SUCCESS(status))
	{
    
    
		DbgPrint("Open SourceFile Failed:%x\n", status);

		return status;
	}

	FILE_STANDARD_INFORMATION fbi = {
    
     0 }; //获取文件大小用

	//查询文件信息
	status = ZwQueryInformationFile(hfile1, &iostack1, &fbi, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);

	if (!NT_SUCCESS(status))
	{
    
    
		//查询文件信息失败
		DbgPrint("QueryInformation SorceFile:%x\n", status);
		//关闭文件
		ZwClose(hfile1);
		return status;
	}

	//到这里文件查询就成功了

	PVOID filebuffer = NULL; //定义一个文件缓存区

	//参数2 是缓冲区大小,这里就是上面获取旧文件的大小
	filebuffer = ExAllocatePool(NonPagedPool, fbi.EndOfFile.QuadPart);//申请一个缓冲区

	if (!filebuffer)
	{
    
    
		//申请缓冲区失败信息
		DbgPrint("AllocteBuffer Failed:%x\n", status);
		ZwClose(hfile1);
		return status;
	}

	RtlZeroMemory(filebuffer, fbi.EndOfFile.QuadPart);//缓冲区清零

	//接下来开始读取文件

	LARGE_INTEGER readoffset = {
    
    0};

	readoffset.QuadPart = 0;

	//读文件
	//参数1:读取文件的句柄
	//参数2:NULL 表示读事件,异步读
	//参数3:NULL 异步读需要一个什么东西,这里没有填
	//参数4: &iostack1 里面有请求的基本信息,请求的长度、结果等
	//参数5:fbi.EndOfFile.QuadPart 缓冲区的长度
	//参数6:从哪里开始读文件 ,readoffset 这里是从0开始读
	//最后一个参数KEY 一般传空 NULL
	status = ZwReadFile(hfile1, NULL, NULL, NULL, &iostack1, filebuffer, fbi.EndOfFile.QuadPart, &readoffset, NULL);
	if (!NT_SUCCESS(status))
	{
    
    
		//读取失败
		DbgPrint("ReadFile Failed:%x\n", status);
		
		ZwClose(hfile1);

		ExFreePool(filebuffer);
		
		return status;
	}
	//打印出信息
	DbgPrint("-----IoInfo----%d\n",iostack1.Information);

	ZwClose(hfile1);//关闭旧文件的句柄,文件已经读到内存
	
	//
	// 下面开始创建新文件
	//

	HANDLE hfile2 = NULL;

	UNICODE_STRING defilepath = {
    
    0};

	OBJECT_ATTRIBUTES obja2 = {
    
     0 }; //新文件参数

	IO_STATUS_BLOCK iostack2 = {
    
     0 };//新文件IO操作记录

	RtlInitUnicodeString(&defilepath, defile_path);//新文件路径

	//初始化文件描述
	InitializeObjectAttributes(&obja2,&defilepath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

	//ZwCreateFile可以创建新文件,也可以打开设备,可以打开任何东西
	//参数1:&hfile2 句柄
	//参数2:访问权限 GENERIC_ALL是全部权限
	//参数3:&obja2文件信息描述
	//参数4:iostack2 IO操作记录
	//参数5:一个指针 提前申请文件大小,本例先设置NULL,不设置大小 先创建
	//参数6:FILE_ATTRIBUTE_NORMAL 文件的描述
	//参数7:FILE_SHARE_WRITE这
	//参数8:这个参数比较重要,如果文件已经存在怎么办? FILE_SUPERSEDE  这个参数表示如果文件存在就用新创建的文件替换
	//参数9:FILE_SYNCHRONOUS_IO_NONALERT和ZwOpenFile一样
	//参数10:NULL 用到网络通信,本例用不到 设置NULL  ,打开TCP UDP设备的时候用到这个参数
	//参数11: 0  用到网络通信,本例用不到 设置0 ,打开TCP UDP设备的时候用到这个参数
	status = ZwCreateFile(&hfile2, GENERIC_ALL, &obja2, &iostack2, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_SUPERSEDE, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);

	if (!NT_SUCCESS(status))
	{
    
    
		//创建文件失败
		DbgPrint("Create File Failed:%x\n", status);

		ZwClose(hfile2);
		
		ExFreePool(filebuffer);
		
		return status;
	}

	//到这里文件就创建成功了

	//接下来就写入文件

	LARGE_INTEGER writeoffset = {
    
     0 }; 

	writeoffset.QuadPart = 0; //从哪里开始写文件,这里是新文件从0开始写

	/// <写入文件>
	/// ZwWriteFile
	/// 参数1:hfile2 文件句柄
	/// 参数2:NULL 事件
	/// 参数3:NULL 是否APC异步写
	/// 参数4:NULL
	/// 参数5:&iostack2
	/// 参数6:filebuffe 内存中的文件
	/// 参数7:fbi.EndOfFile.QuadPart文件的长度
	/// 参数8:writeoffset.QuadPart 从哪里开始写
	/// 参数9:NULL
	status = ZwWriteFile(hfile2,NULL,NULL, NULL, &iostack2,filebuffer, fbi.EndOfFile.QuadPart, writeoffset.QuadPart,NULL);
	
	if (!NT_SUCCESS(status))
	{
    
    
		//创建文件失败
		DbgPrint("Write File Failed:%x\n", status);

		ExFreePool(filebuffer);

		ZwClose(hfile2);

		return status;
	}
	
	//打印出实际写入的信息
	DbgPrint("----Write----%d\n", iostack2.Information );

	//最后收尾释放

	ExFreePool(filebuffer);

	ZwClose(hfile2);//如果不加这一句关闭文件句柄 ,文件会被系统进程锁住,该文件不能删除也不能运行,俗称占坑

	return STATUS_SUCCESS;
}

猜你喜欢

转载自blog.csdn.net/lygl35/article/details/112799034