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

程式碼測試可以進行強刪.