关于不结束进程强删文件一点点看法

本文探讨了两种实现强制删除文件的技术方案:一是通过发送IRP给目标文件的设备驱动;二是挂钩MmFlushImageSection函数。同时介绍了NtDeleteFile系统服务的局限性,并提供了具体的代码示例。

这也是好久以前的代码了。我是菜鸟,在这个问题上研究的不够深,说错了还请大牛指正。

 

这个问题也是一个老问题,不过我是菜鸟我有话要说。我在做这个问题的时候查阅了好多资料,其实这个问题不能算解决,这篇文章你将会看到一段比较长的代码,其实这段代码不是我写的,是网上一个比较有名的人(人称MJ)写的,据说这段代码是通过360文件粉碎机逆向出来的。

 

我查了好多资料,发现能够实现标题所说的功能大概有两种常用的方法,一个是本文提到的直接发送IRP给目标文件的设备驱动强删文件,还有一种就是挂钩MmFlushImageSection函数,很遗憾的是后一种方法没有什么实质性的源码可以参考(不过哪位大神写一段的话可以拿来分享一下),MmFlushImageSection不是一个系统服务,SSDT的方法当然不行,因为SSDT表没有导出这个函数,我记忆不错的话按照“列宁”大神的说法MmFlushImageSection函数更加底层,是由内核导出的一个内核函数。以我的才疏学浅的知识不明白如何挂钩这样的函数。如果有哪位大神看见了本菜鸟的疑惑还请不吝赐教。

 

另外还想提到的一点是,之前被一个论坛的好友迷惑了一下,他说只要使用NtDeleteFile这个系统服务就可以实现这样的功能,这个系统服务有这么一个功能:

在《The Undocumented Functions》一书中可以看到它对NtDeleteFile的解释如下:
      It's very interesting NT System Call... Normally, file deletion is realised as FileDispositionInformation class in a call to NtSetInformationFile. When you use NtDeleteFile, file will be deleted immediatly after call (system isn't waiting for close last HANDLE to file).

      从上述说明可以看出,如果我们直接调用NtDeleteFile,目标文件将会被立即删除而不会等到所有句柄都被关闭。

原文在此

于是就试了一下,诶?果然能删除文件,我是用一个记事本试的,比如aa.txt。其实这种方式是不正确的,为什么呢?仔细想想,aa.txt是自己打开的吗?不是,是由记事本程序打开的,也就是notepad.exe,你删除了文件并不能表示你可以删除正在运行的exe文件,果然,事实证明这样写不能删除正在运行的exe文件。下面也附上我写的这段代码吧,虽然方法上是不正确的。

[cpp]  view plain  copy
  1. #include "windows.h"  
  2.   
  3. typedef struct _UNICODE_STRING {  
  4. USHORT Length;  
  5. USHORT MaximumLength;  
  6. PWSTR Buffer;  
  7. } UNICODE_STRING, *PUNICODE_STRING;  
  8.   
  9. typedef struct _OBJECT_ATTRIBUTES {  
  10.    ULONG Length;  
  11.    HANDLE RootDirectory;  
  12.    PUNICODE_STRING ObjectName;  
  13.    ULONG Attributes;  
  14.    PVOID SecurityDescriptor;  
  15.    PVOID SecurityQualityOfService;  
  16. } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;  
  17.   
  18. static VOID InitializeObjectAttributes ( OUT POBJECT_ATTRIBUTES InitializedAttributes,   
  19. IN PUNICODE_STRING ObjectName,   
  20. IN ULONG Attributes,   
  21. IN HANDLE RootDirectory,   
  22. IN PSECURITY_DESCRIPTOR SecurityDescriptor   
  23. )   
  24. {   
  25. InitializedAttributes->Length = sizeof( OBJECT_ATTRIBUTES );   
  26. InitializedAttributes->RootDirectory = RootDirectory;   
  27. InitializedAttributes->Attributes = Attributes;   
  28. InitializedAttributes->ObjectName = ObjectName;   
  29. InitializedAttributes->SecurityDescriptor = SecurityDescriptor;   
  30. InitializedAttributes->SecurityQualityOfService = NULL;   
  31. return;   
  32. }  
  33.   
  34. //extern "C" __declspec(dllimport) long __stdcall NtDeleteFile(POBJECT_ATTRIBUTES ObjectAttribtues);  
  35. typedef ULONG (__stdcall *_NtDeleteFile)(IN POBJECT_ATTRIBUTES ObjectAttributes);  
  36. _NtDeleteFile NtDeleteFile;  
  37.   
  38.   
  39. void main()  
  40. {  
  41.     HMODULE m_handle=LoadLibrary("ntdll.dll");  
  42.     UNICODE_STRING uniname ;  
  43.     WCHAR   m_file_name[]={L"\\??\\e:\\aa.txt"};  
  44.     uniname.Buffer=m_file_name;  
  45.     uniname.Length = sizeof(m_file_name) - sizeof(WCHAR);  
  46.     uniname.MaximumLength = sizeof(uniname);  
  47.     OBJECT_ATTRIBUTES oba ;  
  48.     if (m_handle!=NULL)  
  49.     {  
  50.         InitializeObjectAttributes(&oba , &uniname , 0x40 , 0 , 0 );  
  51.         NtDeleteFile=(_NtDeleteFile)GetProcAddress(m_handle,"NtDeleteFile");  
  52.         NtDeleteFile(&oba);  
  53.     }  
  54. }  


这是一个用户态的程序,直接从ntdll中导出了NtDeleteFile。

 

然后我也附上Mj大神的发送IRP强删文件的方法:

[cpp]  view plain  copy
  1. #include <ntddk.h>  
  2.   
  3. #define NT_DEVICE_NAME              L"\\Device\\360SuperKill"  
  4. #define DOS_DEVICE_NAME             L"\\DosDevices\\360SuperKill"  
  5.   
  6. NTSTATUS NTAPI VfatBuildRequest (PDEVICE_OBJECT DeviceObject,  
  7.                                    PIRP Irp);  
  8. VOID   
  9. SKillUnloadDriver(   
  10.     IN PDRIVER_OBJECT  DriverObject   
  11.     )  
  12. {  
  13.     PDEVICE_OBJECT  deviceObject = DriverObject->DeviceObject;  
  14.     UNICODE_STRING  uniSymLink;  
  15.   
  16.     RtlInitUnicodeString(&uniSymLink, DOS_DEVICE_NAME);  
  17.       
  18.     IoDeleteSymbolicLink(&uniSymLink);  
  19.   
  20.     IoDeleteDevice(deviceObject);  
  21. }  
  22.   
  23.   
  24. HANDLE  
  25. SkillIoOpenFile(IN PCWSTR FileName,IN ACCESS_MASK DesiredAccess,IN ULONG ShareAccess)  
  26. {  
  27.     NTSTATUS            ntStatus;  
  28.     UNICODE_STRING      uniFileName;  
  29.     OBJECT_ATTRIBUTES   objectAttributes;  
  30.     HANDLE              ntFileHandle;  
  31.     IO_STATUS_BLOCK     ioStatus;  
  32.   
  33.     if (KeGetCurrentIrql() > PASSIVE_LEVEL)  
  34.     {  
  35.         return 0;  
  36.     }  
  37.   
  38.     RtlInitUnicodeString(&uniFileName, FileName);  
  39.   
  40.     InitializeObjectAttributes(&objectAttributes, &uniFileName,  
  41.         OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);  
  42.   
  43.     ntStatus = IoCreateFile(&ntFileHandle,  
  44.         DesiredAccess,  
  45.         &objectAttributes,  
  46.         &ioStatus,  
  47.         0,  
  48.         FILE_ATTRIBUTE_NORMAL,  
  49.         ShareAccess,  
  50.         FILE_OPEN,  
  51.         0,  
  52.         NULL,  
  53.         0,  
  54.         0,  
  55.         NULL,  
  56.         IO_NO_PARAMETER_CHECKING);  
  57.   
  58.     if (!NT_SUCCESS(ntStatus))  
  59.     {  
  60.         return 0;  
  61.     }  
  62.   
  63.     return ntFileHandle;  
  64. }  
  65.   
  66. //回调函数  
  67. NTSTATUS  
  68. SkillSetFileCompletion(  
  69.     IN PDEVICE_OBJECT DeviceObject,  
  70.     IN PIRP Irp,  
  71.     IN PVOID Context  
  72.     )  
  73. {  
  74.     Irp->UserIosb->Status = Irp->IoStatus.Status;  
  75.     Irp->UserIosb->Information = Irp->IoStatus.Information;  
  76.   
  77.     KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE);  
  78.   
  79.     IoFreeIrp(Irp);//释放IRP  
  80.   
  81.     return STATUS_MORE_PROCESSING_REQUIRED;  
  82. }  
  83.   
  84. BOOLEAN SKillDeleteFile(IN HANDLE  FileHandle)  
  85. {  
  86.     NTSTATUS        ntStatus = STATUS_SUCCESS;  
  87.     PFILE_OBJECT    fileObject;  
  88.     PDEVICE_OBJECT  DeviceObject;  
  89.     PIRP            Irp;  
  90.     KEVENT          event;  
  91.     FILE_DISPOSITION_INFORMATION  FileInformation;  
  92.     IO_STATUS_BLOCK ioStatus;  
  93.     PIO_STACK_LOCATION irpSp;  
  94.     PSECTION_OBJECT_POINTERS pSectionObjectPointer;   
  95.   
  96.   
  97.   
  98.     ntStatus = ObReferenceObjectByHandle(FileHandle,  
  99.         DELETE,  
  100.         *IoFileObjectType,  
  101.         KernelMode,  
  102.         &fileObject,  
  103.         NULL);//打开文件的设备对象  
  104.       
  105.     if (!NT_SUCCESS(ntStatus))  
  106.     {  
  107.         return FALSE;  
  108.     }     
  109.   
  110.     DeviceObject = IoGetRelatedDeviceObject(fileObject);  //返回打开的对象指针  
  111.     Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);  //分配一个该设备对象的IRP  
  112.   
  113.     if (Irp == NULL)  
  114.     {  
  115.         ObDereferenceObject(fileObject);  
  116.         return FALSE;  
  117.     }  
  118.   
  119.     KeInitializeEvent(&event, SynchronizationEvent, FALSE);//初始化IRP的信号状态  
  120.       
  121.     FileInformation.DeleteFile = TRUE;  
  122.   
  123.     //设置IRP  
  124.     Irp->AssociatedIrp.SystemBuffer = &FileInformation;  
  125.     Irp->UserEvent = &event;  
  126.     Irp->UserIosb = &ioStatus;  
  127.     Irp->Tail.Overlay.OriginalFileObject = fileObject;  
  128.     Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();  
  129.     Irp->RequestorMode = KernelMode;  
  130.       
  131.     irpSp = IoGetNextIrpStackLocation(Irp);  
  132.     irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;  
  133.     irpSp->DeviceObject = DeviceObject;  
  134.     irpSp->FileObject = fileObject;  
  135.     irpSp->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION);  
  136.     irpSp->Parameters.SetFile.FileInformationClass = FileDispositionInformation;  
  137.     irpSp->Parameters.SetFile.FileObject = fileObject;  
  138.   
  139.     //设置完成IPR请求的回调函数  
  140.     IoSetCompletionRoutine(  
  141.             Irp,  
  142.             SkillSetFileCompletion,  
  143.             &event,  
  144.             TRUE,  
  145.             TRUE,  
  146.             TRUE);  
  147.     pSectionObjectPointer = fileObject->SectionObjectPointer;  
  148.     pSectionObjectPointer->ImageSectionObject = 0;  
  149.     pSectionObjectPointer->DataSectionObject = 0;  
  150.   
  151.     IoCallDriver(DeviceObject, Irp);         //发送IRP  
  152.   
  153.     KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL);  
  154.   
  155.     ObDereferenceObject(fileObject);          //关闭设备对象  
  156.   
  157.     return TRUE;  
  158. }  
  159.   
  160. NTSTATUS DriverEntry(  
  161.         IN PDRIVER_OBJECT DriverObject,  
  162.         IN PUNICODE_STRING RegistryPath  
  163.         )  
  164. {  
  165.         UNICODE_STRING                uniDeviceName;  
  166.         UNICODE_STRING                uniSymLink;  
  167.         NTSTATUS                        ntStatus;  
  168.         PDEVICE_OBJECT                deviceObject = NULL;  
  169.       HANDLE              hFileHandle;  
  170.       
  171.         RtlInitUnicodeString(&uniDeviceName, NT_DEVICE_NAME);  
  172.     RtlInitUnicodeString(&uniSymLink, DOS_DEVICE_NAME);  
  173.      //创建设备对象  
  174.         ntStatus = IoCreateDevice(  
  175.                 DriverObject,  
  176.                 0,  
  177.                 &uniDeviceName,  
  178.                 FILE_DEVICE_UNKNOWN,  
  179.                 FILE_DEVICE_SECURE_OPEN,  
  180.                 FALSE,  
  181.                 &deviceObject);  
  182.   
  183.         if (!NT_SUCCESS(ntStatus))  
  184.         {  
  185.                 return ntStatus;  
  186.         }  
  187.      //设置设备对象的名称  
  188.     ntStatus = IoCreateSymbolicLink(&uniSymLink, &uniDeviceName);  
  189.   
  190.     if (!NT_SUCCESS(ntStatus))  
  191.     {  
  192.         IoDeleteDevice(deviceObject);  
  193.         return ntStatus;  
  194.     }  
  195.   
  196.     DriverObject->DriverUnload = SKillUnloadDriver;  
  197.     //打开文件  
  198.     hFileHandle = SkillIoOpenFile(L"\\??\\c:\\calc.exe",   
  199.                         FILE_READ_ATTRIBUTES,  
  200.                         FILE_SHARE_DELETE);  
  201.       
  202.     DbgPrint("hFileHandle:%08X/n",hFileHandle);  
  203.   
  204.    if (hFileHandle!=NULL)  
  205.    {  
  206.         SKillDeleteFile(hFileHandle);    //删除文件  
  207.         ZwClose(hFileHandle);  
  208.    }  
  209.    return STATUS_SUCCESS;  
  210. }  


这是一段驱动代码,需要DDK编译成驱动文件。大题的思路我已经用注释说明,细节部分还有待仔细研究。

菜鸟言论,仅供娱乐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值