x64内核强删文件.

  • 2019 年 10 月 11 日
  • 笔记

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.那么则无法删除运行中的文件.
pSectionObjectPointer->ImageSectionObject = 0;  pSectionObjectPointer->DataSectionObject = 0;
  • 9.发送IRP(IoCallDriver)
  • 10.根据 事件 来等待是否IRP完成(KeWaitForSingleObject)
  • 11.做完收工.(ZwClose)

2.Nt驱动代码

#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;  }

代码测试可以进行强删.