这个程序比较简单,主要练习了两个点:
(1)模拟发送IRP
(2)使用内核事件对象同步IRP的执行
强制删除文件的思路很简单,把SECTION_OBJECT_POINTERS结构的DataSectionObject和ImageSectionObject两个域清空即可删除正在运行的文件。如果不清空就不能删除运行中的文件。正在运行的文件的这两个域值不为0而文件系统正在根据这两个域决定该文件是否可以删除。如果文件系统检测这两个值为0,就理解为文件没有被使用,可以删除。接下去,就是直接发IRP。
测试时,在C盘目录下放一个test.exe并执行,然后加载驱动即可。
强制删除文件功能在ForceDeleteFile中实现,DriverEntry中只需要简单调用即可。具体实现如下
- NTSTATUS DriverEntry(
- IN OUT PDRIVER_OBJECT DriverObject,
- IN PUNICODE_STRING RegistryPath
- )
- {
- // 其他初始化代码
- // ……
- DbgPrint ( "Delete File %s", ForceDeleteFile(L"//DosDevices//C://test.exe") ? "Success!" : "Failed!" ) ;
- return STATUS_SUCCESS;
- }
- NTSTATUS FD_SetFileCompletion(
- 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;
- }
- HANDLE FD_OpenFile ( WCHAR szFileName[] )
- {
- NTSTATUS ntStatus ;
- UNICODE_STRING FileName ;
- OBJECT_ATTRIBUTES objectAttributes;
- HANDLE hFile ;
- IO_STATUS_BLOCK ioStatus ;
- // 确保IRQL在PASSIVE_LEVEL上
- if (KeGetCurrentIrql() > PASSIVE_LEVEL)
- return NULL;
- // 初始化文件名
- RtlInitUnicodeString ( &FileName, szFileName ) ;
- DbgPrint ( "%ws", FileName.Buffer ) ;
- //初始化对象属性
- InitializeObjectAttributes ( &objectAttributes, &FileName,OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE, NULL, NULL ) ;
- // 打开文件
- ntStatus = IoCreateFile ( &hFile, FILE_READ_ATTRIBUTES, &objectAttributes, &ioStatus, /
- 0,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_DELETE,FILE_OPEN,0,NULL,0,CreateFileTypeNone,NULL,IO_NO_PARAMETER_CHECKING);
- if ( !NT_SUCCESS(ntStatus) )
- return NULL ;
- return hFile ;
- }
- BOOLEAN FD_StripFileAttributes ( HANDLE FileHandle )
- {
- NTSTATUS ntStatus = STATUS_SUCCESS;
- PFILE_OBJECT fileObject;
- PDEVICE_OBJECT DeviceObject;
- PIRP Irp;
- KEVENT SycEvent;
- FILE_BASIC_INFORMATION FileInformation;
- IO_STATUS_BLOCK ioStatus;
- PIO_STACK_LOCATION irpSp;
- // 获取文件对象
- ntStatus = ObReferenceObjectByHandle ( FileHandle, DELETE,
- *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL) ;
- if ( !NT_SUCCESS(ntStatus) )
- {
- DbgPrint ( "ObReferenceObjectByHandle error!" ) ;
- return FALSE;
- }
- // 获取与指定文件对象相关联的设备对象
- DeviceObject = IoGetRelatedDeviceObject ( fileObject ) ;
- // 创建IRP
- Irp = IoAllocateIrp ( DeviceObject->StackSize, TRUE ) ;
- if ( Irp == NULL )
- {
- ObDereferenceObject(fileObject);
- DbgPrint ( "FD_StripFileAttributes IoAllocateIrp error" ) ;
- return FALSE;
- }
- // 初始化同步事件对象
- KeInitializeEvent ( &SycEvent, SynchronizationEvent, FALSE ) ;
- memset ( &FileInformation, 0, 0x28 ) ;
- FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
- // 初始化IRP
- Irp->AssociatedIrp.SystemBuffer = &FileInformation;
- Irp->UserEvent = &SycEvent;
- Irp->UserIosb = &ioStatus;
- Irp->Tail.Overlay.OriginalFileObject = fileObject;
- Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
- Irp->RequestorMode = KernelMode;
- // 设置IRP堆栈信息
- 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, FD_SetFileCompletion ,NULL, TRUE, TRUE, TRUE ) ;
- // 派发IRP
- IoCallDriver(DeviceObject, Irp);
- // 等待IRP的完成
- KeWaitForSingleObject ( &SycEvent, Executive, KernelMode, TRUE, NULL ) ;
- // 递减引用计数
- ObDereferenceObject(fileObject);
- return TRUE ;
- }
- BOOLEAN FD_DeleteFile ( HANDLE FileHandle )
- {
- NTSTATUS ntStatus = STATUS_SUCCESS;
- PFILE_OBJECT fileObject;
- PDEVICE_OBJECT DeviceObject;
- PIRP Irp;
- KEVENT SycEvent ;
- FILE_DISPOSITION_INFORMATION FileInformation;
- IO_STATUS_BLOCK ioStatus;
- PIO_STACK_LOCATION irpSp;
- PSECTION_OBJECT_POINTERS pSectionObjectPointer;
- // 获取文件对象
- ntStatus = ObReferenceObjectByHandle ( FileHandle, DELETE,
- *IoFileObjectType, KernelMode, (PVOID*)&fileObject, NULL) ;
- if ( !NT_SUCCESS(ntStatus) )
- {
- DbgPrint ( "ObReferenceObjectByHandle error!" ) ;
- return FALSE;
- }
- // 获取与指定文件对象相关联的设备对象
- DeviceObject = IoGetRelatedDeviceObject ( fileObject ) ;
- // 创建IRP
- Irp = IoAllocateIrp ( DeviceObject->StackSize, TRUE ) ;
- if (Irp == NULL)
- {
- ObDereferenceObject ( fileObject ) ;
- DbgPrint ( "FD_DeleteFile IoAllocateIrp error" ) ;
- return FALSE;
- }
- // 初始化同步事件对象
- KeInitializeEvent ( &SycEvent, SynchronizationEvent, FALSE ) ;
- FileInformation.DeleteFile = TRUE;
- // 初始化IRP
- Irp->AssociatedIrp.SystemBuffer = &FileInformation;
- Irp->UserEvent = &SycEvent;
- Irp->UserIosb = &ioStatus;
- Irp->Tail.Overlay.OriginalFileObject = fileObject;
- Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
- Irp->RequestorMode = KernelMode;
- // 设置IRP堆栈
- irpSp = IoGetNextIrpStackLocation(Irp);
- 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, FD_SetFileCompletion, NULL, TRUE, TRUE, TRUE ) ;
- // 如果没有这3行,就无法删除正在运行的文件
- pSectionObjectPointer = fileObject->SectionObjectPointer;
- pSectionObjectPointer->ImageSectionObject = 0;
- pSectionObjectPointer->DataSectionObject = 0;
- // 派发IRP
- IoCallDriver ( DeviceObject, Irp ) ;
- // 等待IRP完成
- KeWaitForSingleObject ( &SycEvent, Executive, KernelMode, TRUE, NULL);
- // 递减引用计数
- ObDereferenceObject ( fileObject ) ;
- return TRUE ;
- }
- BOOLEAN ForceDeleteFile ( WCHAR szFileName[] )
- {
- HANDLE hFile = NULL ;
- BOOLEAN status = FALSE ;
- __try {
- // 打开文件
- if ( ( hFile = FD_OpenFile( szFileName ) ) == NULL )
- {
- DbgPrint ( "FD_OpenFile error!" ) ;
- return FALSE ;
- }
- // //去掉只读属性,才能删除只读文件
- if ( FD_StripFileAttributes(hFile) == FALSE )
- {
- ZwClose ( hFile ) ;
- DbgPrint ( "FD_StripFileAttributes error!" ) ;
- return FALSE ;
- }
- // 删除文件
- status = FD_DeleteFile(hFile) ;
- ZwClose ( hFile ) ;
- return status ;
- } __except ( 1 ) {
- DbgPrint ( "execption!" ) ;
- }
- return FALSE ;
- }