驱动强删文件代码

当文件是PE文件而且已经被加载到内存中的时候,正常情况下是无法通过资源管理器explorer.exe来删除本地文件的,因为在删除运行中的文件或者被加载的DLL文件的时候,系统会调用MmFlushImageSection内核函数来检测文件是否处于运行状态,若是,则拒绝删除操作。其中,系统中的MmFlushImageSection内核函数,主要是通过检查文件对象中的PSECTION_OBJECT_POINTERS结构数据来判断该文件是否处于运行状态、是否可以删除。

 

同时,在发送IRP删除文件的时候,系统同样会判断文件的属性是否是只读,若是只读属性则会拒绝删除操作。

 

所以,根据上述的删除原理,文件强制删除的具体实现流程如下所示。

  • 首先,发送IRP打开删除文件,并获取文件对象。

  • 然后,发送IRP设置文件属性,属性类型为FileBasicInformation,将文件属性重新设置为FILE_ATTRIBUTE_NORMAL,防止原来的文件属性为只读属性。并保存文件对象中的PSECTION_OBJECT_POINTERS结构的值,保存完成后,再对该结构进行清空处理。

  • 接着,发送IRP设置文件属性,属性类型为FileDispositionInformation,实现删除文件操作。这样,即使是运行中的文件也能被强制删除。

  • 最后,还原文件对象中的PSECTION_OBJECT_POINTERS结构,并调用ObDereferenceObject函数释放文件对象,完成清理工作。

那么,实现文件强制删除的实现代码如下所示。

// 强制删除文件
NTSTATUS ForceDeleteFile(UNICODE_STRING ustrFileName)
{
    NTSTATUS status = STATUS_SUCCESS;
    PFILE_OBJECT pFileObject = NULL;
    IO_STATUS_BLOCK iosb = { 0 };
    FILE_BASIC_INFORMATION fileBaseInfo = { 0 };
    FILE_DISPOSITION_INFORMATION fileDispositionInfo = { 0 };
    PVOID pImageSectionObject = NULL;
    PVOID pDataSectionObject = NULL;
    PVOID pSharedCacheMap = NULL;
 
    // 发送IRP打开文件
    status = IrpCreateFile(&pFileObject, GENERIC_READ | GENERIC_WRITE, &ustrFileName,
        &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("IrpCreateFile Error[0x%X]\n", status);
        return FALSE;
    }
 
    // 发送IRP设置文件属性, 去掉只读属性, 修改为 FILE_ATTRIBUTE_NORMAL
    RtlZeroMemory(&fileBaseInfo, sizeof(fileBaseInfo));
    fileBaseInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
    status = IrpSetInformationFile(pFileObject, &iosb, &fileBaseInfo, sizeof(fileBaseInfo), FileBasicInformation);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("IrpSetInformationFile[SetInformation] Error[0x%X]\n", status);
        return status;
    }
 
    // 清空PSECTION_OBJECT_POINTERS结构
    if (pFileObject->SectionObjectPointer)
    {
        // 保存旧值
        pImageSectionObject = pFileObject->SectionObjectPointer->ImageSectionObject;
        pDataSectionObject = pFileObject->SectionObjectPointer->DataSectionObject;
        pSharedCacheMap = pFileObject->SectionObjectPointer->SharedCacheMap;
        // 置为空
        pFileObject->SectionObjectPointer->ImageSectionObject = NULL;
        pFileObject->SectionObjectPointer->DataSectionObject = NULL;
        pFileObject->SectionObjectPointer->SharedCacheMap = NULL;
    }
 
    // 发送IRP设置文件属性, 设置删除文件操作
    RtlZeroMemory(&fileDispositionInfo, sizeof(fileDispositionInfo));
    fileDispositionInfo.DeleteFile = TRUE;
    status = IrpSetInformationFile(pFileObject, &iosb, &fileDispositionInfo, sizeof(fileDispositionInfo), FileDispositionInformation);
    if (!NT_SUCCESS(status))
    {
        DbgPrint("IrpSetInformationFile[DeleteFile] Error[0x%X]\n", status);
        return status;
    }
 
    //还原旧值 
    if (pFileObject->SectionObjectPointer)
    {
        pFileObject->SectionObjectPointer->ImageSectionObject = pImageSectionObject;
        pFileObject->SectionObjectPointer->DataSectionObject = pDataSectionObject;
        pFileObject->SectionObjectPointer->SharedCacheMap = pSharedCacheMap;
    }
 
    // 关闭文件对象
    ObDereferenceObject(pFileObject);
 
    return status;
}

打赏作者

发表评论

电子邮件地址不会被公开。 必填项已用*标注