首页
论坛
课程
招聘
[分享]学习强制删除正在运行的文件
2009-4-28 12:03 15981

[分享]学习强制删除正在运行的文件

2009-4-28 12:03
15981
首先说明一下的是,代码是从网上找来的,自己加了一些理解,供和我一样菜的人学习。

http://hi.baidu.com/%C3%F7%ED%F8%B5%C4%D0%C4

强制删除文件,简单说来,其实就是自己构造IRP,然后向NTFS.sys发送IRP,先设置文件的属性,再删除文件。删除文件时会先到NTFS.sys的分派例程,依次进入NtfsSetDispositionInfo-》MmFlushImageSection。MmFlushImageSection()函数会检查这个文件对象的SECTION_OBJECT_POINter结构,看里面是不是为空,也就是检查这个文件在没在运行,没有的话,直接返回TRUE。所以我们如果想要删除正在运行的文件,一种方法是,我们可以设置SECTION_OBJECT_POINter结构里的变量都为0。这样MmFlushImageSection()为返回TRUE,表示能删除。另一种方法是HOOK NTFS.sys的导入表中的MmFlushImageSection()函数,在HOOK函数中检查是不是我们要删除的文件,是的话直接返回TRUE也行。下面是完整代码

#include <ntddk.h>

#define NT_DEVICE_NAME                L"\\Device\\SuperKill"
#define DOS_DEVICE_NAME               L"\\DosDevices\\SuperKill"

VOID
SKillUnloadDriver(
      IN PDRIVER_OBJECT    DriverObject
      )
{
      PDEVICE_OBJECT    deviceObject = DriverObject->DeviceObject;
      UNICODE_STRING    uniSymLink;

      RtlInitUnicodeString(&uniSymLink, DOS_DEVICE_NAME);
   
      IoDeleteSymbolicLink(&uniSymLink);

      IoDeleteDevice(deviceObject);
}

HANDLE
SkillIoOpenFile(
      IN PCWSTR FileName,
      IN ACCESS_MASK DesiredAccess,
      IN ULONG ShareAccess
      )
{
      NTSTATUS              ntStatus;
      UNICODE_STRING        uniFileName;
      OBJECT_ATTRIBUTES     objectAttributes;
      HANDLE                ntFileHandle;
      IO_STATUS_BLOCK       ioStatus;

      if (KeGetCurrentIrql() > PASSIVE_LEVEL)
      {
          return 0;
      }

      RtlInitUnicodeString(&uniFileName, FileName);

      InitializeObjectAttributes(&objectAttributes, &uniFileName,
          OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);

      ntStatus = IoCreateFile(&ntFileHandle,
          DesiredAccess,
          &objectAttributes,
          &ioStatus,
          0,
          FILE_ATTRIBUTE_NORMAL,
          ShareAccess,
          FILE_OPEN,
          0,
          NULL,
          0,
          0,
          NULL,
          IO_NO_PARAMETER_CHECKING);

      if (!NT_SUCCESS(ntStatus))
      {
          return 0;
      }

      return ntFileHandle;
}

NTSTATUS
SkillSetFileCompletion(
      IN PDEVICE_OBJECT DeviceObject,
      IN PIRP Irp,
      IN 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;
}

BOOLEAN
SKillStripFileAttributes(
      IN HANDLE    FileHandle
      )
{
      NTSTATUS          ntStatus = STATUS_SUCCESS;
      PFILE_OBJECT      fileObject;
      PDEVICE_OBJECT    DeviceObject;
      PIRP              Irp;
      KEVENT            event1;
      FILE_BASIC_INFORMATION    FileInformation;
      IO_STATUS_BLOCK ioStatus;
      PIO_STACK_LOCATION irpSp;

      ntStatus = ObReferenceObjectByHandle(FileHandle,
          DELETE,
          *IoFileObjectType,
          KernelMode,
          &fileObject,
          NULL);//我想知道的是这个文件句柄是在哪个进程的句柄表中

      if (!NT_SUCCESS(ntStatus))
      {
          return FALSE;
      }

      DeviceObject = IoGetRelatedDeviceObject(fileObject);
      Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);

      if (Irp == NULL)
      {
          ObDereferenceObject(fileObject);
          return FALSE;
      }

      KeInitializeEvent(&event1, SynchronizationEvent, FALSE);

      memset(&FileInformation,0,0x28);

      FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
      Irp->AssociatedIrp.SystemBuffer = &FileInformation;
      Irp->UserEvent = &event1;
      Irp->UserIosb = &ioStatus;
      Irp->Tail.Overlay.OriginalFileObject = fileObject;
      Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
      Irp->RequestorMode = KernelMode;
   
      irpSp = IoGetNextIrpStackLocation(Irp);
      irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
      irpSp->DeviceObject = DeviceObject;
      irpSp->FileObject = fileObject;
      irpSp->Parameters.SetFile.Length = sizeof(FILE_BASIC_INFORMATION);
      irpSp->Parameters.SetFile.FileInformationClass = FileBasicInformation;
      irpSp->Parameters.SetFile.FileObject = fileObject;

      IoSetCompletionRoutine(
              Irp,
              SkillSetFileCompletion,
              &event1,
              TRUE,
              TRUE,
              TRUE);

      IoCallDriver(DeviceObject, Irp);//调用这个设备对象的驱动对象,并且IO_StACK_LOCAtion会指向下一个,也就是刚刚设置的
                   //如果没有文件系统驱动建立的设备对象没有Attacked的话,就调用文件系统驱动的IRP_MJ_SET_INFORMATION分派例程
                                      

                                   //会调用NTFS.sys驱动的NtfsFsdSetInformation例程,再会进入NtfsSetBasicInfo()函数,最后它会设置代表此文件的FCB(文件
                                   //控制块结构的一些信息,用来设置代表此文件的属性。最后不知道在哪里会调用IoCompleteRequest,它会依次调用先前设置的回调函数
                                    //回调函数会释放刚分配的IRP和设置事件对象为受信状态。
      KeWaitForSingleObject(&event1, Executive, KernelMode, TRUE, NULL);//一等到事件对象变成受信状态就会继续向下执行。

      ObDereferenceObject(fileObject);

      return TRUE;
}

BOOLEAN
SKillDeleteFile(
      IN HANDLE    FileHandle
      )
{
      NTSTATUS          ntStatus = STATUS_SUCCESS;
      PFILE_OBJECT      fileObject;
      PDEVICE_OBJECT    DeviceObject;
      PIRP              Irp;
      KEVENT            event1;
      FILE_DISPOSITION_INFORMATION    FileInformation;
      IO_STATUS_BLOCK ioStatus;
      PIO_STACK_LOCATION irpSp;
      PSECTION_OBJECT_POINTERS pSectionObjectPointer;     ////////////////////

      SKillStripFileAttributes( FileHandle);          //去掉只读属性,才能删除只读文件

      ntStatus = ObReferenceObjectByHandle(FileHandle,
          DELETE,
          *IoFileObjectType,
          KernelMode,
          &fileObject,
          NULL);

      if (!NT_SUCCESS(ntStatus))
      {
          return FALSE;
      }

      DeviceObject = IoGetRelatedDeviceObject(fileObject);//如果NTFS.sys驱动建立的设备对象上没有附加的设备对象的话,就返回NTFS.sys建立的设备对象
                                                       //否则返回的是这个设备对象的highest level设备对象。
      Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);//如果没有附加,StackSize为7

      if (Irp == NULL)
      {
          ObDereferenceObject(fileObject);
          return FALSE;
      }

      KeInitializeEvent(&event1, SynchronizationEvent, FALSE);
   
      FileInformation.DeleteFile = TRUE;

      Irp->AssociatedIrp.SystemBuffer = &FileInformation;
      Irp->UserEvent = &event1;
      Irp->UserIosb = &ioStatus;
      Irp->Tail.Overlay.OriginalFileObject = fileObject;
      Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
      Irp->RequestorMode = KernelMode;
   
      irpSp = IoGetNextIrpStackLocation(Irp);            //得到文件系统NTFS.sys驱动的设备IO_STACK_LOCATION
      irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
      irpSp->DeviceObject = DeviceObject;
      irpSp->FileObject = fileObject;
      irpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);
      irpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;
      irpSp->Parameters.SetFile.FileObject = fileObject;

      IoSetCompletionRoutine(
              Irp,
              SkillSetFileCompletion,
              &event1,
              TRUE,
              TRUE,
              TRUE);

//再加上下面这三行代码 ,MmFlushImageSection    函数通过这个结构来检查是否可以删除文件。
      pSectionObjectPointer = fileObject->SectionObjectPointer;
      pSectionObjectPointer->ImageSectionObject = 0;
      pSectionObjectPointer->DataSectionObject = 0;

      IoCallDriver(DeviceObject, Irp);//这里会依次进入NTFS.sys驱动的NtfsFsdSetInformation例程->NtfsSetDispositionInfo()->MmFlushImageSection(),
                                      //MmFlushImageSection()这函数是用来检查FILE_OBJECT对象的SECTION_OBJECT_POINTER结构的变量,检查这个文件
                                   //在内存有没有被映射。也就是有没有执行。如果上面那样设置了,也就是说文件可以删除了。我们也可以HOOK NTFS.sys导入表中的
                                   //的MmFlushImageSection(),来检查这个文件对象是不是我们要删除 的,是的话,返回TRUE就行了。
      KeWaitForSingleObject(&event1, Executive, KernelMode, TRUE, NULL);

      ObDereferenceObject(fileObject);

      return TRUE;
}

NTSTATUS DriverEntry(
          IN PDRIVER_OBJECT DriverObject,
          IN PUNICODE_STRING RegistryPath
          )
{
          UNICODE_STRING                  uniDeviceName;
          UNICODE_STRING                  uniSymLink;
           NTSTATUS                          ntStatus;
          PDEVICE_OBJECT                  deviceObject = NULL;
          HANDLE                hFileHandle;
   
          RtlInitUnicodeString(&uniDeviceName, NT_DEVICE_NAME);
          RtlInitUnicodeString(&uniSymLink, DOS_DEVICE_NAME);

          ntStatus = IoCreateDevice(
                  DriverObject,
                  0x100u,
                  &uniDeviceName,
                  FILE_DEVICE_UNKNOWN,
                  FILE_DEVICE_SECURE_OPEN,
                  TRUE,
                  &deviceObject);

          if (!NT_SUCCESS(ntStatus))
          {
                  return ntStatus;
          }

      ntStatus = IoCreateSymbolicLink(&uniSymLink, &uniDeviceName);

      if (!NT_SUCCESS(ntStatus))
      {
          IoDeleteDevice(deviceObject);
          return ntStatus;
      }

      DriverObject->DriverUnload = SKillUnloadDriver;

      //
      // 重点在这
      //
      hFileHandle = SkillIoOpenFile(L"\\Device\\HarddiskVolume1\\test.exe",
                          FILE_READ_ATTRIBUTES,
                          FILE_SHARE_DELETE);   //得到文件句柄

     if (hFileHandle!=NULL)
     {
          SKillDeleteFile(hFileHandle);
          ZwClose(hFileHandle);
     }
     return STATUS_SUCCESS;
}

看雪2022 KCTF 秋季赛 防守篇规则,征题截止日期11月12日!(iPhone 14等你拿!)

收藏
点赞0
打赏
分享
最新回复 (23)
雪    币: 7510
活跃值: 活跃值 (402)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2009-4-28 12:16
2
0
很经典的代码,值得收藏,我在好几个驱动中都看到过~~
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sand 活跃值 2009-4-28 12:28
3
0
不错。。。已经收藏
雪    币: 313
活跃值: 活跃值 (22)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
better 活跃值 2 2009-4-28 14:17
4
0
太好了,学习……
雪    币: 218
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
deryope 活跃值 1 2009-4-28 14:30
5
0
正好我也在看这个,LZ说得较详细

这个代码实际上起作用的是这三行:
//再加上下面这三行代码 ,MmFlushImageSection 函数通过这个结构来检查是否可以删除文件。
pSectionObjectPointer = fileObject->SectionObjectPointer;
pSectionObjectPointer->ImageSectionObject = 0;
pSectionObjectPointer->DataSectionObject = 0;


因为MmFlushImageSection代码里做了这样的检查:
ControlArea = (PCONTROL_AREA)(SectionPointer->DataSectionObject);
if (ControlArea != NULL) {
  ...
  return FALSE;
}
所以清0就可以删正在使用的文件。

感觉 防这个代码删文件,可以Hook MmFlushImageSection直接返回False,只是处理比较麻烦(也许这样就什么文件也删不掉了)。
雪    币: 459
活跃值: 活跃值 (84)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
qihoocom 活跃值 9 2009-4-28 15:31
6
0
又是抄我3年前的代码~
雪    币: 141
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dsjHZAHfaf 活跃值 2009-4-28 16:02
7
0
C:\WinDDK\6001.18001
中makefile和sources怎么写.
雪    币: 190
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mkuymkuy 活跃值 2009-4-28 16:33
8
0
看看~~吓人
雪    币: 1
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wangzheye 活跃值 2009-4-28 18:02
9
0
为什么没人从硬件觉得考虑写删除文件的代码,直接操作IDE可将系统文件东西都可以删除。只要磁盘中有的都行。
雪    币: 250
活跃值: 活跃值 (85)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
weolar 活跃值 10 2009-4-28 19:19
10
0
不是没人考虑,是比较麻烦。既要考虑不同的ide接口,又要考虑不同的文件系统。而且ntfs系统比较复杂。当然你放出来我们都支持你
雪    币: 462
活跃值: 活跃值 (985)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
sudami 活跃值 25 2009-4-28 20:01
11
0
还放什么啊. ntfs3g开源的.自己下去就是了...
雪    币: 250
活跃值: 活跃值 (85)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
weolar 活跃值 10 2009-4-28 23:27
12
0
对这方面了解比较少,去看看~~
雪    币: 69
活跃值: 活跃值 (182)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dnybz 活跃值 2009-4-29 13:06
13
0
[QUOTE=yaolibing;613142]首先说明一下的是,代码是从网上找来的,自己加了一些理解,供和我一样菜的人学习。

http://hi.baidu.com/%C3%F7%ED%F8%B5%C4%D0%C4

强制删除文件,简单说来,其实就是自己构造IRP,然后向NTFS.sys发送IRP,先设置文件的属性,再删除文件。...[/QUOTE]



你这个和原来那个有点不同?
雪    币: 507
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
BeWideWay 活跃值 2009-5-12 15:36
14
0
mask  mask
thx for sharing
雪    币: 8669
活跃值: 活跃值 (1188)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
cvcvxk 活跃值 10 2009-5-12 16:03
15
0
新时代了,打开文件居然还有IoCreateFile?这是个新时代,要用新方法打开文件,另外还要防止XX文件大法和sudami的深度hook等等,所以还是自己解析文件再去XX吧~
雪    币: 79
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
林郎君 活跃值 2009-5-12 16:13
16
0
谢谢楼主发布分享

收藏之
雪    币: 74
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
Possible 活跃值 2009-5-13 15:40
17
0
ntfs3g可以看看,很不错
雪    币: 101
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
keweijie 活跃值 2009-5-14 00:07
18
0
谢谢分享了啊
雪    币: 100
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
枯藤 活跃值 2009-5-15 02:51
19
0
很不错的代码。
值得收藏。
谢谢楼主。
雪    币: 203
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tensai 活跃值 2009-7-15 15:01
20
0
我已经安装了2008 DDK

请问怎么编译和运行啊?
雪    币: 200
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
taday 活跃值 2009-7-15 21:37
21
0
谢谢楼主分享,学习一下
雪    币: 10
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kangken 活跃值 2009-7-16 02:08
22
0
学习学习。。感谢分享。
雪    币: 232
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sding 活跃值 2009-7-16 13:40
23
0
收藏        !!!
雪    币: 507
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
BeWideWay 活跃值 2009-7-22 10:23
24
0
I just wonder if there is anyother approach to force delete those under using file so much as system files?
雪    币: 93
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
WinDebug 活跃值 2009-7-22 14:55
25
0
不管怎么样,还是顶下。
游客
登录 | 注册 方可回帖
返回