Windows用户层使用指令操作内核程序执行指令! (3) 文件操作

驱动开发中,文件操作是一个至关重要的环节。尽管在Windows系统中,“万物皆文件”的概念并不像在Linux中那样普遍,但文件操作仍然扮演着关键角色。例如,日记操作、强制删除文件等操作都离不开对文件系统的深入理解和操作能力。

通过亲自动手编写代码,可以有效提高自己的驱动开发水平。这不仅有助于加深对操作系统底层机制的理解,还能锻炼解决实际问题的能力。

文件定义:file.h

#pragma once
#include <ntifs.h>
#include "struct.h"
#include "Logging.h"

BOOLEAN MyFileExists(M_L ustrFilePath);
BOOLEAN MyCreateFile(M_L ustrFilePath);
BOOLEAN MyCreateFileFolder(M_L ustrFileFolderPath);
BOOLEAN MyDeleteFileOrFileFolder(M_L ustrFileName);

NTSTATUS WriteResponseCreate(UNICODE_STRING filePath);
NTSTATUS WriteResponseOpen(UNICODE_STRING filePath, PHANDLE fileHandle);
NTSTATUS WriteResponse(UNICODE_STRING response, HANDLE fileHandle);
NTSTATUS WriteResponseAppend(UNICODE_STRING response, HANDLE fileHandle);
NTSTATUS WriteResponseExists(UNICODE_STRING filePath, PBOOLEAN exists);
NTSTATUS WriteResponseDelete(UNICODE_STRING filePath);


NTSTATUS RetOpenFileHandle(UNICODE_STRING uDelFileName, PHANDLE pFileHandle);
NTSTATUS CallBackIrpCompleteionProc(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context);
NTSTATUS PassFileattribute(PFILE_OBJECT pFileObj);
NTSTATUS FsDeleteFile(PFILE_OBJECT pFileObj);
NTSTATUS IrpDeleteFileRun(UNICODE_STRING uDelFileName);

中间代码是我重写了一遍上面的代码使其更"好"用了一些,一般我们使用上面的,但是有一些文件操作可以看我的第一篇Windows用户层使用指令操作内核程序执行指令! (1) 日记文件,下面的代码暂时废弃,我在虚拟机中使用强删文件(IrpDeleteFileRun)时会导致不明错误:在资源管理器(explorer.exe)文件删了一刷新就会重新出现,在CMD中会直接显示拒绝访问

file.cpp

#include "file.h"

BOOLEAN MyFileExists(M_L ustrFilePath)
{
	NTSTATUS status = STATUS_SUCCESS;
	OBJECT_ATTRIBUTES objectAttributes = { 0 };
	IO_STATUS_BLOCK iosb = { 0 };
	HANDLE hFile = NULL;

	UNICODE_STRING ustrFilePathTmp;
	RtlInitUnicodeString(&ustrFilePathTmp, ustrFilePath);

	// 初始化对象属性结构体
	InitializeObjectAttributes(&objectAttributes, &ustrFilePathTmp, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

	// 打开文件
	status = ZwOpenFile(&hFile, FILE_READ_ATTRIBUTES, &objectAttributes, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
	if (!NT_SUCCESS(status))
	{
		return FALSE;
	}

	// 关闭句柄
	ZwClose(hFile);

	return TRUE;
}
BOOLEAN MyCreateFile(M_L ustrFilePath)
{
	HANDLE hFile = NULL;
	OBJECT_ATTRIBUTES objectAttributes = { 0 };
	IO_STATUS_BLOCK iosb = { 0 };
	NTSTATUS status = STATUS_SUCCESS;

	UNICODE_STRING ustrFilePathTmp;
	RtlInitUnicodeString(&ustrFilePathTmp, ustrFilePath);

	// 初始化对象属性结构体 FILE_SYNCHRONOUS_IO_NONALERT
	InitializeObjectAttributes(&objectAttributes, &ustrFilePathTmp, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

	// 创建文件
	status = ZwCreateFile(&hFile, GENERIC_READ, &objectAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
	if (!NT_SUCCESS(status))
	{
		return FALSE;
	}

	// 关闭句柄
	ZwClose(hFile);

	return TRUE;
}
BOOLEAN MyCreateFileFolder(M_L ustrFileFolderPath)
{
	HANDLE hFile = NULL;
	OBJECT_ATTRIBUTES objectAttributes = { 0 };
	IO_STATUS_BLOCK iosb = { 0 };
	NTSTATUS status = STATUS_SUCCESS;

	UNICODE_STRING ustrFileFolderPathTmp;
	RtlInitUnicodeString(&ustrFileFolderPathTmp, ustrFileFolderPath);

	// 初始化对象属性结构体
	InitializeObjectAttributes(&objectAttributes, &ustrFileFolderPathTmp, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

	// 创建目录 FILE_DIRECTORY_FILE
	status = ZwCreateFile(&hFile, GENERIC_READ, &objectAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_CREATE, FILE_DIRECTORY_FILE, NULL, 0);
	if (!NT_SUCCESS(status))
	{
		return FALSE;
	}
	// 关闭句柄
	ZwClose(hFile);

	return TRUE;
}
BOOLEAN MyDeleteFileOrFileFolder(M_L ustrFileName)
{
    NTSTATUS status = STATUS_SUCCESS;
    OBJECT_ATTRIBUTES objectAttributes = { 0 };
    UNICODE_STRING ustrFileNameTmp;
    RtlInitUnicodeString(&ustrFileNameTmp, ustrFileName);
    // 初始化属性
    InitializeObjectAttributes(&objectAttributes, &ustrFileNameTmp, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

    // 执行删除操作
    status = ZwDeleteFile(&objectAttributes);
    if (!NT_SUCCESS(status))
    {
        return FALSE;
    }

    return TRUE;
}

NTSTATUS WriteResponseCreate(UNICODE_STRING filePath)
{
	OBJECT_ATTRIBUTES objectAttributes;
	IO_STATUS_BLOCK ioStatusBlock;
	NTSTATUS status;
	HANDLE fileHandle = NULL;
	InitializeObjectAttributes(&objectAttributes, &filePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
	status = ZwCreateFile(&fileHandle, FILE_APPEND_DATA | SYNCHRONIZE, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
	if (status != STATUS_SUCCESS) {
		WriteLog("[LyKernelService] Failed to create file %wZ, status = 0x%x\n", filePath, status);
		return status;
	}
	if (fileHandle == NULL) {
		WriteLog("[LyKernelService] Failed to open file %wZ\n", filePath);
		return STATUS_INVALID_HANDLE;
	}
	return STATUS_SUCCESS;
}
NTSTATUS WriteResponseOpen(UNICODE_STRING filePath, PHANDLE fileHandle)
{
    OBJECT_ATTRIBUTES objAttr;
    InitializeObjectAttributes(&objAttr, &filePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
    IO_STATUS_BLOCK ioStatus;
    NTSTATUS status = STATUS_SUCCESS;
    HANDLE fileHandleTmp = NULL;
    status = ZwCreateFile(&fileHandleTmp, FILE_APPEND_DATA | SYNCHRONIZE, & objAttr, & ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
    if (status != STATUS_SUCCESS) {
        WriteLog("[LyKernelService] Failed to open file %wZ, status = 0x%x\n", filePath, status);
        return status;
    }
    if (fileHandleTmp == NULL) {
        WriteLog("[LyKernelService] Failed to open file %wZ\n", filePath);
        return STATUS_INVALID_HANDLE;
    }
    *fileHandle = fileHandleTmp;
    return STATUS_SUCCESS;
}
NTSTATUS WriteResponse(UNICODE_STRING response, HANDLE fileHandle)
{
	IO_STATUS_BLOCK ioStatusBlock;
	NTSTATUS status;
	status = ZwWriteFile(fileHandle, NULL, NULL, NULL, &ioStatusBlock, response.Buffer, response.Length / 2, NULL, NULL);
	if (status != STATUS_SUCCESS) {
		WriteLog("[LyKernelService] Failed to write to file, status = 0x%x\n", status);
	}
	ZwClose(fileHandle);
	return status;
}
NTSTATUS WriteResponseAppend(UNICODE_STRING response, HANDLE fileHandle)
{
	NTSTATUS status;
	IO_STATUS_BLOCK ioStatusBlock;
	status = ZwWriteFile(fileHandle, NULL, NULL, NULL, &ioStatusBlock, response.Buffer, response.Length / 2, NULL, NULL);
	if (status != STATUS_SUCCESS) {
		WriteLog("[LyKernelService] Failed to write to file, status = 0x%x\n", status);
	}
	return status;
}
NTSTATUS WriteResponseExists(UNICODE_STRING filePath, PBOOLEAN exists)
{
    NTSTATUS status = STATUS_SUCCESS;
    OBJECT_ATTRIBUTES objectAttributes = { 0 };
    IO_STATUS_BLOCK ioStatusBlock = { 0 };
    HANDLE fileHandle = NULL;
    InitializeObjectAttributes(&objectAttributes, &filePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
    status = ZwOpenFile(&fileHandle, FILE_READ_ATTRIBUTES, &objectAttributes, &ioStatusBlock, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
    if (status != STATUS_SUCCESS) {
        *exists = FALSE;
        return status;
    }
    if (fileHandle == NULL) {
        *exists = FALSE;
        return STATUS_INVALID_HANDLE;
    }
    *exists = TRUE;
    ZwClose(fileHandle);
    return STATUS_SUCCESS;
}
NTSTATUS WriteResponseDelete(UNICODE_STRING filePath)
{
    NTSTATUS status = STATUS_SUCCESS;
    OBJECT_ATTRIBUTES objectAttributes = { 0 };
    IO_STATUS_BLOCK ioStatusBlock = { 0 };
    HANDLE fileHandle = NULL;
    InitializeObjectAttributes(&objectAttributes, &filePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
    status = ZwOpenFile(&fileHandle, FILE_DELETE_CHILD, &objectAttributes, &ioStatusBlock, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
    if (status != STATUS_SUCCESS) {
        WriteLog("[LyKernelService] Failed to open file %wZ, status = 0x%x\n", filePath, status);
        return status;
    }
    if (fileHandle == NULL) {
        WriteLog("[LyKernelService] Failed to open file %wZ\n", filePath);
        return STATUS_INVALID_HANDLE;
    }
    status = ZwDeleteFile(&objectAttributes);
    if (status != STATUS_SUCCESS) {
        WriteLog("[LyKernelService] Failed to delete file %wZ, status = 0x%x\n", filePath, status);
        return status;
    }
    ZwClose(fileHandle);
    return STATUS_SUCCESS;
}

NTSTATUS RetOpenFileHandle(UNICODE_STRING uDelFileName, PHANDLE pFileHandle)
{

    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
    IO_STATUS_BLOCK iostu;
    HANDLE hFileHandle = 0;
    if (pFileHandle == NULL)
        return STATUS_UNSUCCESSFUL;
    if (KeGetCurrentIrql() > PASSIVE_LEVEL)
        return 0;

    if (uDelFileName.Length < 0 || uDelFileName.MaximumLength < 0)
    {
        return 0;
    }


    OBJECT_ATTRIBUTES ObjAttribute;
    ObjAttribute.ObjectName = &uDelFileName;
    ObjAttribute.SecurityDescriptor = NULL;
    ObjAttribute.SecurityQualityOfService = NULL;
    ObjAttribute.Attributes = OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE;
    ObjAttribute.Length = sizeof(OBJECT_ATTRIBUTES);

    /*  InitializeObjectAttributes(
          &ObjAttribute,
          &uDelFileName,
          OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
          NULL, NULL);*/

    ntStatus = IoCreateFile(&hFileHandle,
        FILE_READ_ATTRIBUTES,
        &ObjAttribute,
        &iostu,
        0,
        FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_DELETE,
        FILE_OPEN,
        0,
        NULL,
        0,
        CreateFileTypeNone,
        NULL,
        IO_NO_PARAMETER_CHECKING);

    *pFileHandle = hFileHandle;
    return ntStatus;
}
NTSTATUS CallBackIrpCompleteionProc(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{

    //操作系统会设置这个回调
    Irp->UserIosb->Status = Irp->IoStatus.Status;
    Irp->UserIosb->Information = Irp->IoStatus.Information;
    KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE);

    IoFreeIrp(Irp);
    return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS PassFileattribute(PFILE_OBJECT pFileObj)
{
    /*
    1.申请IRP,初始化IRP
    2.初始化同步事件,以及设置回调.
    3.设置文件属性为默认
    4.发送IRP
    */
    PDEVICE_OBJECT pNextDeviceObj = NULL;
    PIRP pAllocIrp = NULL;
    KEVENT IrpSynEvent = { 0 }; //Irp同步需要的事件同步
    FILE_BASIC_INFORMATION fileBasciInfo = { 0 };
    IO_STATUS_BLOCK iostu;
    PIO_STACK_LOCATION IrpStack;
    //通过文件对象.获取其设备对象指针
    pNextDeviceObj = IoGetRelatedDeviceObject(pFileObj);
    if (pNextDeviceObj == NULL)
        return STATUS_UNSUCCESSFUL;

    //通过设备对象指针.确定申请的IRP的大小,注意在完成设置里面进行释放.
    pAllocIrp = IoAllocateIrp(pNextDeviceObj->StackSize, TRUE);
    if (pAllocIrp == NULL)
        return STATUS_UNSUCCESSFUL;

    //初始化Irp

    //设置为自动,设置为无信号.
    KeInitializeEvent(&IrpSynEvent, SynchronizationEvent, FALSE);

    fileBasciInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
    pAllocIrp->AssociatedIrp.SystemBuffer = &fileBasciInfo;
    pAllocIrp->UserIosb = &iostu;
    pAllocIrp->UserEvent = &IrpSynEvent;
    pAllocIrp->Tail.Overlay.OriginalFileObject = pFileObj;
    pAllocIrp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();

    //获取下层堆栈.进行设置.

    //IrpStack  = 
    IrpStack = IoGetNextIrpStackLocation(pAllocIrp);
    IrpStack->MajorFunction = IRP_MJ_SET_INFORMATION;
    IrpStack->DeviceObject = pNextDeviceObj;
    IrpStack->FileObject = pFileObj;
    IrpStack->Parameters.SetFile.Length = sizeof(FILE_BASIC_INFORMATION);
    IrpStack->Parameters.SetFile.FileObject = pFileObj;
    IrpStack->Parameters.SetFile.FileInformationClass = FileBasicInformation;

    //设置完成例程
    IoSetCompletionRoutine(pAllocIrp, CallBackIrpCompleteionProc, &IrpSynEvent, TRUE, TRUE, TRUE);


    //发送IRP
    IoCallDriver(pNextDeviceObj, pAllocIrp);
    //等待完成.

    KeWaitForSingleObject(&IrpSynEvent, Executive, KernelMode, TRUE, NULL);

    return STATUS_SUCCESS;
}
NTSTATUS FsDeleteFile(PFILE_OBJECT pFileObj)
{
    /*
  1.申请IRP,初始化IRP
  2.初始化同步事件,以及设置回调.
  3.设置文件属性为默认
  4.发送IRP

  核心:
    核心是设置 FileObject中的域.进而删除正在运行中的文件

  */
    PDEVICE_OBJECT pNextDeviceObj = NULL;
    PIRP pAllocIrp = NULL;
    KEVENT IrpSynEvent = { 0 }; //Irp同步需要的事件同步
    FILE_DISPOSITION_INFORMATION     fileBasciInfo = { 0 };  //注意此位置.已经变化为 FILE_DISPOSITION_INFORMATION
    IO_STATUS_BLOCK iostu;
    PIO_STACK_LOCATION IrpStack;

    PSECTION_OBJECT_POINTERS pFileExe;  //注意此属性要设置为0.欺骗系统进行删除
    //通过文件对象.获取其设备对象指针
    pNextDeviceObj = IoGetRelatedDeviceObject(pFileObj);
    if (pNextDeviceObj == NULL)
        return STATUS_UNSUCCESSFUL;

    //通过设备对象指针.确定申请的IRP的大小,注意在完成设置里面进行释放.
    pAllocIrp = IoAllocateIrp(pNextDeviceObj->StackSize, TRUE);
    if (pAllocIrp == NULL)
        return STATUS_UNSUCCESSFUL;

    //初始化Irp

    //设置为自动,设置为无信号.
    KeInitializeEvent(&IrpSynEvent, SynchronizationEvent, FALSE);

    fileBasciInfo.DeleteFile = TRUE;        //设置标记为删除
    pAllocIrp->AssociatedIrp.SystemBuffer = &fileBasciInfo;
    pAllocIrp->UserIosb = &iostu;
    pAllocIrp->UserEvent = &IrpSynEvent;
    pAllocIrp->Tail.Overlay.OriginalFileObject = pFileObj;
    pAllocIrp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();

    //获取下层堆栈.进行设置.

    //IrpStack  = 
    IrpStack = IoGetNextIrpStackLocation(pAllocIrp);
    IrpStack->MajorFunction = IRP_MJ_SET_INFORMATION;
    IrpStack->DeviceObject = pNextDeviceObj;
    IrpStack->FileObject = pFileObj;
    IrpStack->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);
    IrpStack->Parameters.SetFile.FileObject = pFileObj;
    IrpStack->Parameters.SetFile.FileInformationClass = FileDispositionInformation;

    //设置完成例程
    IoSetCompletionRoutine(pAllocIrp, CallBackIrpCompleteionProc, &IrpSynEvent, TRUE, TRUE, TRUE);

    //删除正在运行中的文件.

    pFileExe = pFileObj->SectionObjectPointer;
    pFileExe->DataSectionObject = 0;
    pFileExe->ImageSectionObject = 0;
    //发送IRP
    IoCallDriver(pNextDeviceObj, pAllocIrp);
    //等待完成.

    KeWaitForSingleObject(&IrpSynEvent, Executive, KernelMode, TRUE, NULL);

    return STATUS_SUCCESS;
}
NTSTATUS IrpDeleteFileRun(UNICODE_STRING uDelFileName)
{
    NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
    /*
    1.首先通过发送IRP去掉文件的属性
    2.设置文件属性为删除.进行发送IRP强删文件.
    */
    HANDLE hFileHandle = { 0 };
    PFILE_OBJECT  pFileObject = NULL;
    //sep1 : OpenFile Get File Handle
    ntStatus = RetOpenFileHandle(uDelFileName, &hFileHandle);

    if (!NT_SUCCESS(ntStatus))
    {
        WriteLog("[LyKernelService] Failed to open file %wZ, status = 0x%x\n", uDelFileName, ntStatus);
        goto ExitAnRelease;
    }
    //sep2:  Chang File Handle to FileObject

    ntStatus = ObReferenceObjectByHandle(
        hFileHandle,
        GENERIC_ALL,
        *IoFileObjectType,
        KernelMode,
        (PVOID*)&pFileObject,
        NULL);
    if (!NT_SUCCESS(ntStatus))
    {
        WriteLog("[LyKernelService] Failed to get file object, status = 0x%x\n", ntStatus);
        goto ExitAnRelease;
    }

    //setp 3:  Pass File Atribute
    ntStatus = PassFileattribute(pFileObject);
    if (!NT_SUCCESS(ntStatus))
    {
        WriteLog("[LyKernelService] Failed to pass file attribute, status = 0x%x\n", ntStatus);
        goto ExitAnRelease;
    }

    //setp 4: Send Irp DeleteFile
    ntStatus = FsDeleteFile(pFileObject);
    if (!NT_SUCCESS(ntStatus))
    {
        WriteLog("[LyKernelService] Failed to send delete file irp, status = 0x%x\n", ntStatus);
        goto ExitAnRelease;
    }
ExitAnRelease:

    if (pFileObject != NULL)
        ObDereferenceObject(pFileObject);
    if (hFileHandle != NULL)
        ZwClose(hFileHandle);

    return ntStatus;
}

注意在使用file.h代码时一定要先使用ZwClose()对已获得的文件句柄释放掉(或者自己写一个强制解锁文件),否则会打印"0xC0000043"错误,即"STATUS_SHARING_VIOLATION"错误.对应代码其实不难,主要是可以根据Microsoft提供的文档进行开发

Windows用户层使用指令操作内核程序执行指令! (4) 驱动加密算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值