找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3322|回复: 2

一种在Windows系统中强删正在运行文件的方法

[复制链接]
发表于 2015-5-26 00:45:03 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
本帖最后由 元始天尊 于 2015-5-31 17:19 编辑

随便运行一个exe文件,,在它运行时进行删除操作,基本上会得到一个 无法删除的错误,下面我们就来破解这个限制
  1. DeleteFile -> NtSetInformationFile FileInformationClass = FileDispositionInformation:
  2.         函数结构如下:(参考wrk)
  3.         CurrentThread = PsGetCurrentThread();
  4.         requestorMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);
  5.         status = ObReferenceObjectByHandle(FileHandle,
  6.                 IopQueryOperationAccess[FileInformationClass],IoFileObjectType,
  7.                 requestorMode,(PVOID *)&fileObject,&handleInformation);
  8.         if (!(fileObject->Flags & FO_DIRECT_DEVICE_OPEN)) {
  9.                 deviceObject = IoGetRelatedDeviceObject(fileObject);
  10.         }
  11.         else {
  12.                 deviceObject = IoGetAttachedDevice(fileObject->DeviceObject);
  13.         }
  14.         fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
  15.         if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  16.                 BOOLEAN interrupted;
  17.                 if (!IopAcquireFastLock(fileObject)) {
  18.                         status = IopAcquireFileObjectLock(fileObject,
  19.                                 requestorMode,
  20.                                 (BOOLEAN)((fileObject->Flags & FO_ALERTABLE_IO) != 0),
  21.                                 &interrupted);
  22.                         if (interrupted) {
  23.                                 ObDereferenceObject(fileObject);
  24.                                 return status;
  25.                         }
  26.                 }
  27.                 event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  28.                 if (event == NULL) {
  29.                         ObDereferenceObject(fileObject);
  30.                         return STATUS_INSUFFICIENT_RESOURCES;
  31.                 }
  32.                 KeInitializeEvent(event, SynchronizationEvent, FALSE);
  33.                 synchronousIo = FALSE;
  34.         }
  35.         KeClearEvent(&fileObject->Event);
  36.         irp = IoAllocateIrp(deviceObject->StackSize, FALSE);
  37.         if (!irp) {
  38.                 if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) {
  39.                         ExFreePool(event);
  40.                 }
  41.                 IopAllocateIrpCleanup(fileObject, (PKEVENT)NULL);
  42.                 return STATUS_INSUFFICIENT_RESOURCES;
  43.         }
  44.         irp->Tail.Overlay.OriginalFileObject = fileObject;
  45.         irp->Tail.Overlay.Thread = CurrentThread;
  46.         irp->RequestorMode = requestorMode;
  47.         if (synchronousIo) {
  48.                 irp->UserEvent = (PKEVENT)NULL;
  49.                 irp->UserIosb = IoStatusBlock;
  50.         }
  51.         else {
  52.                 irp->UserEvent = event;
  53.                 irp->UserIosb = &localIoStatus;
  54.                 irp->Flags = IRP_SYNCHRONOUS_API;
  55.         }
  56.         irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE)NULL;
  57.         irpSp = IoGetNextIrpStackLocation(irp);
  58.         irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
  59.         irpSp->FileObject = fileObject;
  60.         irp->UserBuffer = FileInformation;
  61.         irp->AssociatedIrp.SystemBuffer = (PVOID)NULL;
  62.         irp->MdlAddress = (PMDL)NULL;
  63.         try {
  64.                 irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuota(NonPagedPool,
  65.                         Length);
  66.         } except(EXCEPTION_EXECUTE_HANDLER) {
  67.                 IopExceptionCleanup(fileObject,
  68.                         irp,
  69.                         (PKEVENT)NULL,
  70.                         event);
  71.                 return GetExceptionCode();
  72.         }
  73.         irp->Flags |= IRP_BUFFERED_IO |
  74.                 IRP_DEALLOCATE_BUFFER |
  75.                 IRP_INPUT_OPERATION |
  76.                 IRP_DEFER_IO_COMPLETION;
  77.         irpSp->Parameters.QueryFile.Length = Length;
  78.         irpSp->Parameters.QueryFile.FileInformationClass = FileInformationClass;
  79.         IopQueueThreadIrp(irp);
  80.         IopUpdateOtherOperationCount();
  81.         if (FileInformationClass == FileDispositionInformation){
  82.                 PFILE_DISPOSITION_INFORMATION disposition = irp->AssociatedIrp.SystemBuffer;
  83.                 if (disposition->DeleteFile) {
  84.                         irpSp->Parameters.SetFile.DeleteHandle = FileHandle;
  85.                 }
  86.                 status = IoCallDriver(deviceObject, irp);
  87. windbg查看deviceObject内存,得到driverObject内存,发现Call的Driver是\FileSystem\Ntfs,
  88. 现在反汇编该文件查看IRP_MJ_SET_INFORMATION派遣,用windbg下断:Ntfs!NtfsFsdSetInformation
  89. NtfsFsdSetInformation->NtfsCommonSetInformation->NtfsSetDispositionInfo:
  90. nt!MmFlushImageSection  该函数返回空 ->
  91. nt!MiCheckControlAreaStatus

  92. BOOLEAN MmFlushImageSection (__in PSECTION_OBJECT_POINTERS SectionPointer,__in MMFLUSH_TYPE FlushType)
  93. {
  94.     PLIST_ENTRY Next;
  95.     PCONTROL_AREA ControlArea;
  96.     PLARGE_CONTROL_AREA LargeControlArea;
  97.     KIRQL OldIrql;
  98.     LOGICAL state;
  99.     if (FlushType == MmFlushForDelete) {
  100.         LOCK_PFN (OldIrql);
  101.         ControlArea = (PCONTROL_AREA)(SectionPointer->DataSectionObject);
  102.         if (ControlArea != NULL) {
  103.             if ((ControlArea->NumberOfUserReferences != 0) ||
  104.                 (ControlArea->u.Flags.BeingCreated)) {
  105.                 UNLOCK_PFN (OldIrql);
  106.                 return FALSE;
  107.             }
  108.         }
  109.         UNLOCK_PFN (OldIrql);
  110.     }
  111.     state = MiCheckControlAreaStatus (CheckImageSection,SectionPointer,FALSE,&ControlArea,&OldIrql);
  112.     if (ControlArea == NULL) {
  113.         return (BOOLEAN) state;
  114.     }
  115.     do {
  116.         ControlArea->u.Flags.BeingDeleted = 1;
  117.         ControlArea->NumberOfMappedViews = 1;
  118.         LargeControlArea = NULL;
  119.         if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) {
  120.             NOTHING;
  121.         }
  122.         else if (IsListEmpty(&((PLARGE_CONTROL_AREA)ControlArea)->UserGlobalList)) {
  123.             ASSERT (ControlArea ==(PCONTROL_AREA)SectionPointer->ImageSectionObject);
  124.         }
  125.         else {
  126.             ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 1);
  127.             Next = ((PLARGE_CONTROL_AREA)ControlArea)->UserGlobalList.Flink;
  128.             LargeControlArea = CONTAINING_RECORD (Next,LARGE_CONTROL_AREA,UserGlobalList);
  129.             ASSERT (LargeControlArea->u.Flags.GlobalOnlyPerSession == 1);
  130.             LargeControlArea->NumberOfSectionReferences += 1;
  131.         }
  132.         UNLOCK_PFN (OldIrql);
  133.         MiCleanSection (ControlArea, TRUE);
  134.         if (LargeControlArea != NULL) {
  135.             state = MiCheckControlAreaStatus (CheckImageSection,SectionPointer,FALSE, &ControlArea,&OldIrql);
  136.             if (!ControlArea) {
  137.                 LOCK_PFN (OldIrql);
  138.                 LargeControlArea->NumberOfSectionReferences -= 1;
  139.                 MiCheckControlArea ((PCONTROL_AREA)LargeControlArea,OldIrql);
  140.             }
  141.             else {
  142.                 LargeControlArea->NumberOfSectionReferences -= 1;
  143.                 MiCheckControlArea ((PCONTROL_AREA)LargeControlArea,OldIrql);
  144.                 LOCK_PFN (OldIrql);
  145.             }
  146.         }
  147.         else {
  148.             state = TRUE;
  149.             break;
  150.         }
  151.     } while (ControlArea);
  152.     return (BOOLEAN) state;
  153. }

  154. LOGICAL MiCheckControlAreaStatus (IN SECTION_CHECK_TYPE SectionCheckType,IN PSECTION_OBJECT_POINTERS SectionObjectPointers,IN ULONG DelayClose, OUT PCONTROL_AREA *ControlAreaOut, OUT PKIRQL PreviousIrql)
  155. {
  156.     PKTHREAD CurrentThread;
  157.     PEVENT_COUNTER IoEvent;
  158.     PEVENT_COUNTER SegmentEvent;
  159.     LOGICAL DeallocateSegmentEvent;
  160.     PCONTROL_AREA ControlArea;
  161.     ULONG SectRef;
  162.     KIRQL OldIrql;
  163.     *ControlAreaOut = NULL;
  164.     do {
  165.         SegmentEvent = MiGetEventCounter ();
  166.         if (SegmentEvent != NULL) {
  167.             break;
  168.         }
  169.         KeDelayExecutionThread (KernelMode,
  170.                                 FALSE,
  171.                                 (PLARGE_INTEGER)&MmShortTime);
  172.     } while (TRUE);
  173.     LOCK_PFN (OldIrql);
  174.     if (SectionCheckType != CheckImageSection) {
  175.         ControlArea = ((PCONTROL_AREA)(SectionObjectPointers->DataSectionObject));
  176.     }
  177.     else {
  178.         ControlArea = ((PCONTROL_AREA)(SectionObjectPointers->ImageSectionObject));
  179.     }
  180.     if (ControlArea == NULL) {
  181.         if (SectionCheckType != CheckBothSection) {
  182.             UNLOCK_PFN (OldIrql);
  183.             MiFreeEventCounter (SegmentEvent);
  184.             return TRUE;
  185.         }
  186.         else {
  187.             ControlArea = ((PCONTROL_AREA)(SectionObjectPointers->ImageSectionObject));
  188.             if (ControlArea == NULL) {
  189.                 UNLOCK_PFN (OldIrql);
  190.                 MiFreeEventCounter (SegmentEvent);
  191.                 return TRUE;
  192.             }
  193.         }
  194.     }
  195.     if (SectionCheckType != CheckUserDataSection) {
  196.         SectRef = ControlArea->NumberOfSectionReferences;
  197.     }
  198.     else {
  199.         SectRef = ControlArea->NumberOfUserReferences;
  200.     }
  201.     if ((SectRef != 0) ||
  202.         (ControlArea->NumberOfMappedViews != 0) ||
  203.         (ControlArea->u.Flags.BeingCreated)) {
  204.         if (DelayClose) {
  205.             ControlArea->u.Flags.DeleteOnClose = 1;
  206.         }
  207.         UNLOCK_PFN (OldIrql);
  208.         MiFreeEventCounter (SegmentEvent);
  209.         return FALSE;
  210.     }
  211.     if (ControlArea->u.Flags.BeingDeleted) {
  212.         if (ControlArea->WaitingForDeletion == NULL) {
  213.             DeallocateSegmentEvent = FALSE;
  214.             ControlArea->WaitingForDeletion = SegmentEvent;
  215.             IoEvent = SegmentEvent;
  216.         }
  217.         else {
  218.             DeallocateSegmentEvent = TRUE;
  219.             IoEvent = ControlArea->WaitingForDeletion;
  220.             IoEvent->RefCount += 1;
  221.         }
  222.         CurrentThread = KeGetCurrentThread ();
  223.         KeEnterCriticalRegionThread (CurrentThread);
  224.         UNLOCK_PFN_AND_THEN_WAIT(OldIrql);
  225.         KeWaitForSingleObject(&IoEvent->Event,
  226.                               WrPageOut,
  227.                               KernelMode,
  228.                               FALSE,
  229.                               (PLARGE_INTEGER)NULL);
  230.         KeLeaveCriticalRegionThread (CurrentThread);
  231.         MiFreeEventCounter (IoEvent);
  232.         if (DeallocateSegmentEvent == TRUE) {
  233.             MiFreeEventCounter (SegmentEvent);
  234.         }
  235.         return TRUE;
  236.     }
  237.     ASSERT (SegmentEvent->RefCount == 1);
  238.     ASSERT (SegmentEvent->ListEntry.Next == NULL);
  239.     InterlockedPushEntrySList (&MmEventCountSListHead,
  240.                                (PSLIST_ENTRY)&SegmentEvent->ListEntry);
  241.     *ControlAreaOut = ControlArea;
  242.     *PreviousIrql = OldIrql;
  243.     return FALSE;
  244. }


复制代码

看了以上代码逻辑,可知只需改一些结构体就可以实现:运行时删除,很简单的代码如下:

  1. NTSTATUS DriverIoctl(PDEVICE_OBJECT pDevObj,PIRP pIrp)
  2. {
  3.         NTSTATUS status = STATUS_SUCCESS;
  4.         KdPrint(("Driver Ioctl\n"));
  5.         PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp);
  6.         ULONG cbin = pStack->Parameters.DeviceIoControl.InputBufferLength;
  7.         ULONG cbout = pStack->Parameters.DeviceIoControl.OutputBufferLength;
  8.         PVOID buffer = pIrp->AssociatedIrp.SystemBuffer;
  9.         ULONG ulOutputLen=0;

  10.         switch(pStack->Parameters.DeviceIoControl.IoControlCode)
  11.         {
  12.         case IOCTL_IO_DELFILE:
  13.                 {
  14.                         PFILE_OBJECT pObject;
  15.                         status = ObReferenceObjectByHandle(*(HANDLE*)buffer,GENERIC_READ,*IoFileObjectType,KernelMode,(PVOID*)&pObject,NULL);
  16.                          if(NT_SUCCESS(status))
  17.                         {
  18.                                 __try
  19.                                 {
  20.                                         PSCB Scb = (PSCB)pObject->FsContext;//NtfsDecodeFileObject
  21.                                         if(Scb)
  22.                                         {
  23.                                                 Scb->Fcb->Info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;//IsReadOnly
  24.                                                 PSECTION_OBJECT_POINTERS pop=&Scb->NonpagedScb->SegmentObject;
  25.                                                 pop->ImageSectionObject = NULL;
  26.                                         }
  27.                                 }
  28.                                 __except(1)
  29.                                 {

  30.                                 }
  31.                                 ObDereferenceObject(pObject);
  32.                         }
  33.                 }
  34.                 break;
  35.         }

  36.         pIrp->IoStatus.Status = status;
  37.         pIrp->IoStatus.Information = ulOutputLen;
  38.         IoCompleteRequest(pIrp,IO_NO_INCREMENT);
  39.         return status;
  40. }

  41. #include <iostream>
  42. #include <windows.h>
  43. using namespace std;

  44. #define IOCTL_IO_DELFILE CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)//获取驱动加载信息
  45. int _tmain(int argc, _TCHAR* argv[])
  46. {
  47.         if (argc != 2)
  48.         {
  49.                 cout << "参数不够" << endl;
  50.         }

  51.         HANDLE hFile = CreateFileW(argv[1], 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  52.         if (hFile != INVALID_HANDLE_VALUE)
  53.         {

  54.                 HANDLE hDev = CreateFileW(L"\\\\.\\NtMem", GENERIC_ALL, 0, NULL, OPEN_EXISTING, 0, NULL);
  55.                 if (hDev != INVALID_HANDLE_VALUE)
  56.                 {
  57.                         DWORD nop = 0;
  58.                         DeviceIoControl(hDev, IOCTL_IO_DELFILE, (LPVOID)&hFile, sizeof(HANDLE), (LPVOID)&hFile, 0, &nop, NULL);

  59.                         CloseHandle(hDev);
  60.                 }
  61.                 else
  62.                 {
  63.                         cout << "无法打开设备!" << endl;
  64.                 }
  65.                 CloseHandle(hFile);
  66.         }
  67.         else
  68.         {
  69.                 cout << "无法打开文件!" << endl;
  70.         }

  71.         return 0;
  72. }

复制代码

xp 下测试删文件很轻松,还小试了一把360,没成功,发现根本未能进NtSetInformationFile这一层,估计在应用层做了hook。
回复

使用道具 举报

 楼主| 发表于 2015-5-26 08:56:47 | 显示全部楼层
FILE_OBJECT->FsContext      
*(_DWORD *)(a4 + 148) + 12->PSECTION_OBJECT_POINTERS
->ImageSectionObject->CONTROL_AREA
回复 赞! 靠!

使用道具 举报

 楼主| 发表于 2015-6-2 21:20:14 | 显示全部楼层
  1. #define MiGetPdePart(va) (((ULONG)va>>22)&0x3FF)
  2. #define MiGetPtePart(va) (((ULONG)va>>12)&0x3FF)
  3. #define MiGetOffsetPart(va) ((ULONG)va&0xFFF)
  4.                         ULONG cr3val=0;
  5.                         _asm
  6.                         {
  7.                                 mov eax,cr3;
  8.                                 mov cr3val,eax;
  9.                         }
  10.                         PVOID oriaddr=ExAllocatePool(NonPagedPool,0x1000);
  11.                         *(PULONG)oriaddr = 0x12345;
  12.                         PMMPTE PointerPte1,PointerPte2;

  13.                         PULONG pdaddr;
  14.                         LARGE_INTEGER mapaddr;
  15.                         mapaddr.QuadPart = cr3val;
  16.                         pdaddr = (PULONG)MmMapIoSpace(mapaddr,0x1000,MmWriteCombined);
  17.                         if(pdaddr)
  18.                         {
  19.                                 PointerPte1 = (PMMPTE)&pdaddr[MiGetPdePart(oriaddr)];
  20.                                 if(PointerPte1->u.Hard.LargePage == 0)
  21.                                 {
  22.                                         mapaddr.QuadPart = PointerPte1->u.Hard.PageFrameNumber;
  23.                                         pdaddr = (PULONG)MmMapIoSpace(mapaddr,0x1000,MmWriteCombined);
  24.                                         if(pdaddr)
  25.                                         {
  26.                                                 PointerPte1 = (PMMPTE)&pdaddr[MiGetPtePart(oriaddr)];
  27.                                                 mapaddr.QuadPart = PointerPte1->u.Hard.PageFrameNumber;
  28.                                                 pdaddr= (PULONG)MmMapIoSpace(mapaddr,0x1000,MmWriteCombined);
  29.                                                 if(pdaddr)
  30.                                                 {
  31.                                                         PCHAR objaddr=(PCHAR)pdaddr+MiGetOffsetPart(oriaddr);
  32.                                                         objaddr = NULL;
  33.                                                 }
  34.                                         }
  35.                                 }
复制代码
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-11-22 17:12 , Processed in 0.033096 second(s), 21 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表