强制删除文件(1)——直接发IRP到文件系统

来源:互联网 发布:c4d r17 mac安装教程 编辑:程序博客网 时间:2024/06/05 03:53

这个程序比较简单,主要练习了两个点:
(1)模拟发送IRP
(2)使用内核事件对象同步IRP的执行

强制删除文件的思路很简单,把SECTION_OBJECT_POINTERS结构的DataSectionObject和ImageSectionObject两个域清空即可删除正在运行的文件。如果不清空就不能删除运行中的文件。正在运行的文件的这两个域值不为0而文件系统正在根据这两个域决定该文件是否可以删除。如果文件系统检测这两个值为0,就理解为文件没有被使用,可以删除。接下去,就是直接发IRP。

测试时,在C盘目录下放一个test.exe并执行,然后加载驱动即可。
强制删除文件功能在ForceDeleteFile中实现,DriverEntry中只需要简单调用即可。具体实现如下

[csharp] view plain copy
  1. NTSTATUS DriverEntry(  
  2.     IN OUT PDRIVER_OBJECT   DriverObject,  
  3.     IN PUNICODE_STRING      RegistryPath  
  4.     )  
  5. {  
  6.     // 其他初始化代码  
  7.     // ……  
  8.   
  9.     DbgPrint ( "Delete File %s", ForceDeleteFile(L"//DosDevices//C://test.exe") ? "Success!" : "Failed!" ) ;  
  10.     return STATUS_SUCCESS;  
  11. }  
  12.   
  13. NTSTATUS FD_SetFileCompletion(  
  14.                        IN PDEVICE_OBJECT DeviceObject,  
  15.                        IN PIRP Irp,  
  16.                        IN PVOID Context  
  17.                        )  
  18. {  
  19.     Irp->UserIosb->Status     = Irp->IoStatus.Status;  
  20.     Irp->UserIosb->Information    = Irp->IoStatus.Information;  
  21.   
  22.     KeSetEvent ( Irp->UserEvent, IO_NO_INCREMENT, FALSE ) ;  
  23.   
  24.     IoFreeIrp(Irp);  
  25.     return STATUS_MORE_PROCESSING_REQUIRED;  
  26. }  
  27.   
  28. HANDLE  FD_OpenFile ( WCHAR szFileName[] )  
  29. {  
  30.     NTSTATUS            ntStatus ;  
  31.     UNICODE_STRING      FileName ;  
  32.     OBJECT_ATTRIBUTES   objectAttributes;  
  33.     HANDLE              hFile ;  
  34.     IO_STATUS_BLOCK     ioStatus ;  
  35.   
  36.     // 确保IRQL在PASSIVE_LEVEL上  
  37.     if (KeGetCurrentIrql() > PASSIVE_LEVEL)  
  38.         return NULL;  
  39.   
  40.     // 初始化文件名  
  41.     RtlInitUnicodeString ( &FileName, szFileName ) ;  
  42.     DbgPrint ( "%ws", FileName.Buffer ) ;  
  43.   
  44.     //初始化对象属性  
  45.     InitializeObjectAttributes ( &objectAttributes, &FileName,OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE, NULL, NULL ) ;  
  46.   
  47.     // 打开文件  
  48.     ntStatus = IoCreateFile ( &hFile, FILE_READ_ATTRIBUTES, &objectAttributes, &ioStatus, /  
  49.         0,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_DELETE,FILE_OPEN,0,NULL,0,CreateFileTypeNone,NULL,IO_NO_PARAMETER_CHECKING);  
  50.     if ( !NT_SUCCESS(ntStatus) )  
  51.         return NULL ;  
  52.   
  53.     return  hFile ;  
  54. }  
  55.   
  56. BOOLEAN FD_StripFileAttributes ( HANDLE FileHandle )  
  57. {  
  58.     NTSTATUS                ntStatus = STATUS_SUCCESS;  
  59.     PFILE_OBJECT            fileObject;  
  60.     PDEVICE_OBJECT          DeviceObject;  
  61.     PIRP                    Irp;  
  62.     KEVENT                  SycEvent;  
  63.     FILE_BASIC_INFORMATION  FileInformation;  
  64.     IO_STATUS_BLOCK         ioStatus;  
  65.     PIO_STACK_LOCATION      irpSp;  
  66.   
  67.     // 获取文件对象  
  68.     ntStatus = ObReferenceObjectByHandle ( FileHandle, DELETE,  
  69.         *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL) ;  
  70.     if ( !NT_SUCCESS(ntStatus) )  
  71.     {  
  72.         DbgPrint ( "ObReferenceObjectByHandle error!" ) ;  
  73.         return FALSE;  
  74.     }  
  75.   
  76.     // 获取与指定文件对象相关联的设备对象  
  77.     DeviceObject = IoGetRelatedDeviceObject ( fileObject ) ;  
  78.   
  79.     // 创建IRP  
  80.     Irp = IoAllocateIrp ( DeviceObject->StackSize, TRUE ) ;  
  81.     if ( Irp == NULL )   
  82.     {  
  83.         ObDereferenceObject(fileObject);  
  84.   
  85.         DbgPrint ( "FD_StripFileAttributes IoAllocateIrp error" ) ;  
  86.         return FALSE;  
  87.     }  
  88.   
  89.     // 初始化同步事件对象  
  90.     KeInitializeEvent ( &SycEvent, SynchronizationEvent, FALSE ) ;  
  91.   
  92.     memset ( &FileInformation, 0, 0x28 ) ;  
  93.     FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;  
  94.   
  95.     // 初始化IRP  
  96.     Irp->AssociatedIrp.SystemBuffer          = &FileInformation;  
  97.     Irp->UserEvent                           = &SycEvent;  
  98.     Irp->UserIosb                            = &ioStatus;  
  99.     Irp->Tail.Overlay.OriginalFileObject = fileObject;  
  100.     Irp->Tail.Overlay.Thread             = (PETHREAD)KeGetCurrentThread();  
  101.     Irp->RequestorMode = KernelMode;  
  102.   
  103.     // 设置IRP堆栈信息  
  104.     irpSp = IoGetNextIrpStackLocation(Irp);  
  105.     irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;  
  106.     irpSp->DeviceObject      = DeviceObject;  
  107.     irpSp->FileObject        = fileObject;  
  108.     irpSp->Parameters.SetFile.Length             = sizeof(FILE_BASIC_INFORMATION) ;  
  109.     irpSp->Parameters.SetFile.FileInformationClass   = FileBasicInformation;  
  110.     irpSp->Parameters.SetFile.FileObject         = fileObject ;  
  111.   
  112.     // 设置完成例程  
  113.     IoSetCompletionRoutine ( Irp, FD_SetFileCompletion ,NULL, TRUE, TRUE, TRUE ) ;  
  114.   
  115.     // 派发IRP  
  116.     IoCallDriver(DeviceObject, Irp);  
  117.   
  118.     // 等待IRP的完成  
  119.     KeWaitForSingleObject ( &SycEvent, Executive, KernelMode, TRUE, NULL ) ;  
  120.   
  121.     // 递减引用计数  
  122.     ObDereferenceObject(fileObject);  
  123.   
  124.     return TRUE ;  
  125. }  
  126.   
  127. BOOLEAN FD_DeleteFile ( HANDLE FileHandle )  
  128. {  
  129.     NTSTATUS          ntStatus = STATUS_SUCCESS;  
  130.     PFILE_OBJECT      fileObject;  
  131.     PDEVICE_OBJECT    DeviceObject;  
  132.     PIRP              Irp;  
  133.     KEVENT            SycEvent ;  
  134.     FILE_DISPOSITION_INFORMATION    FileInformation;  
  135.     IO_STATUS_BLOCK                 ioStatus;  
  136.     PIO_STACK_LOCATION              irpSp;  
  137.     PSECTION_OBJECT_POINTERS        pSectionObjectPointer;       
  138.   
  139.     // 获取文件对象  
  140.     ntStatus = ObReferenceObjectByHandle ( FileHandle, DELETE,  
  141.         *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL) ;  
  142.     if ( !NT_SUCCESS(ntStatus) )  
  143.     {  
  144.         DbgPrint ( "ObReferenceObjectByHandle error!" ) ;  
  145.         return FALSE;  
  146.     }  
  147.   
  148.     // 获取与指定文件对象相关联的设备对象  
  149.     DeviceObject = IoGetRelatedDeviceObject ( fileObject ) ;  
  150.   
  151.     // 创建IRP  
  152.     Irp = IoAllocateIrp ( DeviceObject->StackSize, TRUE ) ;  
  153.     if (Irp == NULL)  
  154.     {  
  155.         ObDereferenceObject ( fileObject ) ;  
  156.         DbgPrint ( "FD_DeleteFile IoAllocateIrp error" ) ;  
  157.         return FALSE;  
  158.     }  
  159.   
  160.     // 初始化同步事件对象  
  161.     KeInitializeEvent ( &SycEvent, SynchronizationEvent, FALSE ) ;  
  162.   
  163.     FileInformation.DeleteFile = TRUE;  
  164.   
  165.     // 初始化IRP  
  166.     Irp->AssociatedIrp.SystemBuffer          = &FileInformation;  
  167.     Irp->UserEvent                           = &SycEvent;  
  168.     Irp->UserIosb                            = &ioStatus;  
  169.     Irp->Tail.Overlay.OriginalFileObject = fileObject;  
  170.     Irp->Tail.Overlay.Thread             = (PETHREAD)KeGetCurrentThread();  
  171.     Irp->RequestorMode                       = KernelMode;  
  172.   
  173.     // 设置IRP堆栈  
  174.     irpSp = IoGetNextIrpStackLocation(Irp);  
  175.     irpSp->MajorFunction = IRP_MJ_SET_INFORMATION;  
  176.     irpSp->DeviceObject      = DeviceObject;  
  177.     irpSp->FileObject        = fileObject;  
  178.     irpSp->Parameters.SetFile.Length             = sizeof(FILE_DISPOSITION_INFORMATION);  
  179.     irpSp->Parameters.SetFile.FileInformationClass   = FileDispositionInformation;  
  180.     irpSp->Parameters.SetFile.FileObject         = fileObject;  
  181.   
  182.     // 设置完成例程  
  183.     IoSetCompletionRoutine ( Irp, FD_SetFileCompletion, NULL, TRUE, TRUE, TRUE ) ;  
  184.   
  185.     // 如果没有这3行,就无法删除正在运行的文件  
  186.     pSectionObjectPointer = fileObject->SectionObjectPointer;  
  187.     pSectionObjectPointer->ImageSectionObject = 0;  
  188.     pSectionObjectPointer->DataSectionObject = 0;  
  189.   
  190.     // 派发IRP  
  191.     IoCallDriver ( DeviceObject, Irp ) ;  
  192.   
  193.     // 等待IRP完成  
  194.     KeWaitForSingleObject ( &SycEvent, Executive, KernelMode, TRUE, NULL);  
  195.   
  196.     // 递减引用计数  
  197.     ObDereferenceObject ( fileObject ) ;  
  198.   
  199.     return TRUE ;  
  200. }  
  201.   
  202. BOOLEAN ForceDeleteFile ( WCHAR szFileName[] )  
  203. {  
  204.     HANDLE      hFile = NULL ;  
  205.     BOOLEAN     status = FALSE ;  
  206.   
  207.     __try {  
  208.         // 打开文件  
  209.         if ( ( hFile = FD_OpenFile( szFileName ) ) == NULL )  
  210.         {  
  211.             DbgPrint ( "FD_OpenFile error!" ) ;  
  212.             return FALSE ;  
  213.         }  
  214.   
  215.         // //去掉只读属性,才能删除只读文件  
  216.         if ( FD_StripFileAttributes(hFile) == FALSE )  
  217.         {  
  218.             ZwClose ( hFile ) ;  
  219.             DbgPrint ( "FD_StripFileAttributes error!" ) ;  
  220.             return FALSE ;  
  221.         }  
  222.   
  223.         // 删除文件  
  224.         status = FD_DeleteFile(hFile) ;  
  225.         ZwClose ( hFile ) ;  
  226.   
  227.         return status ;  
  228.   
  229.     } __except ( 1 ) {  
  230.         DbgPrint ( "execption!" ) ;  
  231.     }  
  232.   
  233.     return FALSE ;  
  234. }