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

上面这个连接中的DEMO是比较完整软件,这里我把其中发IRP强制删除文件的部分抽出来了,
学习了下,顺便加点注释。这个程序比较简单,主要练习了两个点:
(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 ;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值