前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >x64内核强删文件.

x64内核强删文件.

作者头像
IBinary
发布2019-09-30 16:06:45
1.3K0
发布2019-09-30 16:06:45
举报
文章被收录于专栏:逆向技术

x64内核中强删文件的实现

一丶简介

说道删除文件.有各种各样的方法. 有ring3 也有ring0. 而且也有许多对抗的方法. 如ring3想删除一个文件.被占用你就无法删除.此时可以通过解除句柄进行删除 ring0中想删除一个文件.有常规方法也有非常规方法.常规方法就是 设置文件属性为删除.然后进行设置. 还有就是直接调用ZwDeleteFile 进行删除. 暴力删除就是这里所讲的 IRP删除.给底层发送IRP即可进行删除文件.

1.步骤

步骤很简单.基本上说完就可以自己写代码做出

  • 1.打开文件.获取文件句柄 (IoCreateFile)
  • 2.根据文件句柄,获取文件对象.(有了句柄都应该第一时间想到获取它的对象) (ObReferenceObjectByHandle)
  • 3.获取文件对象的设备对象指针.这个发送IRP的时候需要使用(IoGetRelatedDeviceObject)
  • 4.申请IRP(IoAllocateIrp)
  • 5.初始化你申请的IRP
  • 6.获取IRP的下层堆栈,并且初始化信息.(IoGetNextIrpStackLocation)
  • 7.设置回调.系统完成IRP之后会调用你这个回调.所以你需要设置事件同步跟你自己同步,才知道IRP已经发送完了.(IoSetCompletionRoutine)
  • 8.获取文件对象的域指针.并且设置域指针的两个成员为0.系统以他来判断这个程序是否可以删除.如果不为0.那么则无法删除运行中的文件.
代码语言:javascript
复制
pSectionObjectPointer->ImageSectionObject = 0;
pSectionObjectPointer->DataSectionObject = 0;
  • 9.发送IRP(IoCallDriver)
  • 10.根据 事件 来等待是否IRP完成(KeWaitForSingleObject)
  • 11.做完收工.(ZwClose)

2.Nt驱动代码

代码语言:javascript
复制
#include "Driver.h"


//删除文件函数的入口
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;
}

//去掉文件属性


//CallBack回调
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)
{
    KdBreakPoint();
    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))
    {
        goto ExitAnRelease;
    }
    //sep2:  Chang File Handle to FileObject

    ntStatus = ObReferenceObjectByHandle(
        hFileHandle,
        GENERIC_ALL,
        *IoFileObjectType,
        KernelMode,
        &pFileObject,
        NULL);
    if (!NT_SUCCESS(ntStatus))
    {
       
        goto ExitAnRelease;
    }

    //setp 3:  Pass File Atribute
    KdBreakPoint();
   ntStatus =  PassFileattribute(pFileObject);
   if (!NT_SUCCESS(ntStatus))
   {
       goto ExitAnRelease;
   }

   //setp 4: Send Irp DeleteFile
   KdBreakPoint();
   ntStatus = FsDeleteFile(pFileObject);
   if (!NT_SUCCESS(ntStatus))
   {
       goto ExitAnRelease;
   }
ExitAnRelease:

    if (pFileObject != NULL)
        ObDereferenceObject(pFileObject);
    if (hFileHandle != NULL)
        ZwClose(hFileHandle);
  
    return ntStatus;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
{
    ULONG iCount = 0;
    NTSTATUS ntStatus;
    UNICODE_STRING uDelFileName = { 0 };
    pDriverObj->DriverUnload = DriverUnLoad;
    /*ntStatus = InitDeviceAnSybolicLinkName(pDriverObj);
    if (!NT_SUCCESS(ntStatus))
    {
        return ntStatus;
    }

    ntStatus = InitDisPatchFunction(pDriverObj);
    if (!NT_SUCCESS(ntStatus))
    {
        return ntStatus;
    }*/

    //也可写成: \\??\\c:\\xxx.txt

    RtlInitUnicodeString(&uDelFileName, L"//DosDevices//C://123.txt");
    IrpDeleteFileRun(uDelFileName);
    return STATUS_SUCCESS;
}

代码测试可以进行强删.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-09-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • x64内核中强删文件的实现
    • 一丶简介
      • 1.步骤
      • 2.Nt驱动代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档