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

来源:互联网 发布:中国科学文献数据库 编辑:程序博客网 时间:2024/05/02 01:11

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

 

这个问题也是一个老问题,不过我是菜鸟我有话要说。我在做这个问题的时候查阅了好多资料,其实这个问题不能算解决,这篇文章你将会看到一段比较长的代码,其实这段代码不是我写的,是网上一个比较有名的人(人称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文件。下面也附上我写的这段代码吧,虽然方法上是不正确的。

#include "windows.h"typedef struct _UNICODE_STRING {USHORT Length;USHORT MaximumLength;PWSTR Buffer;} UNICODE_STRING, *PUNICODE_STRING;typedef struct _OBJECT_ATTRIBUTES {   ULONG Length;   HANDLE RootDirectory;   PUNICODE_STRING ObjectName;   ULONG Attributes;   PVOID SecurityDescriptor;   PVOID SecurityQualityOfService;} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;static VOID InitializeObjectAttributes ( OUT POBJECT_ATTRIBUTES InitializedAttributes, IN PUNICODE_STRING ObjectName, IN ULONG Attributes, IN HANDLE RootDirectory, IN PSECURITY_DESCRIPTOR SecurityDescriptor ) { InitializedAttributes->Length = sizeof( OBJECT_ATTRIBUTES ); InitializedAttributes->RootDirectory = RootDirectory; InitializedAttributes->Attributes = Attributes; InitializedAttributes->ObjectName = ObjectName; InitializedAttributes->SecurityDescriptor = SecurityDescriptor; InitializedAttributes->SecurityQualityOfService = NULL; return; }//extern "C" __declspec(dllimport) long __stdcall NtDeleteFile(POBJECT_ATTRIBUTES ObjectAttribtues);typedef ULONG (__stdcall *_NtDeleteFile)(IN POBJECT_ATTRIBUTES ObjectAttributes);_NtDeleteFile NtDeleteFile;void main(){HMODULE m_handle=LoadLibrary("ntdll.dll");UNICODE_STRING uniname ;WCHAR   m_file_name[]={L"\\??\\e:\\aa.txt"};uniname.Buffer=m_file_name;uniname.Length = sizeof(m_file_name) - sizeof(WCHAR);uniname.MaximumLength = sizeof(uniname);OBJECT_ATTRIBUTES oba ;if (m_handle!=NULL){InitializeObjectAttributes(&oba , &uniname , 0x40 , 0 , 0 );NtDeleteFile=(_NtDeleteFile)GetProcAddress(m_handle,"NtDeleteFile");NtDeleteFile(&oba);}}


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

 

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

#include <ntddk.h>#define NT_DEVICE_NAME              L"\\Device\\360SuperKill"#define DOS_DEVICE_NAME             L"\\DosDevices\\360SuperKill"NTSTATUS NTAPI VfatBuildRequest (PDEVICE_OBJECT DeviceObject,                                   PIRP Irp);VOID SKillUnloadDriver(     IN PDRIVER_OBJECT  DriverObject     ){    PDEVICE_OBJECT  deviceObject = DriverObject->DeviceObject;    UNICODE_STRING  uniSymLink;    RtlInitUnicodeString(&uniSymLink, DOS_DEVICE_NAME);        IoDeleteSymbolicLink(&uniSymLink);    IoDeleteDevice(deviceObject);}HANDLESkillIoOpenFile(IN PCWSTR FileName,IN ACCESS_MASK DesiredAccess,IN ULONG ShareAccess){    NTSTATUS            ntStatus;    UNICODE_STRING      uniFileName;    OBJECT_ATTRIBUTES   objectAttributes;    HANDLE              ntFileHandle;    IO_STATUS_BLOCK     ioStatus;    if (KeGetCurrentIrql() > PASSIVE_LEVEL)    {        return 0;    }    RtlInitUnicodeString(&uniFileName, FileName);    InitializeObjectAttributes(&objectAttributes, &uniFileName,        OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);    ntStatus = IoCreateFile(&ntFileHandle,        DesiredAccess,        &objectAttributes,        &ioStatus,        0,        FILE_ATTRIBUTE_NORMAL,        ShareAccess,        FILE_OPEN,        0,        NULL,        0,        0,        NULL,        IO_NO_PARAMETER_CHECKING);    if (!NT_SUCCESS(ntStatus))    {        return 0;    }    return ntFileHandle;}//回调函数NTSTATUSSkillSetFileCompletion(    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);//释放IRP    return STATUS_MORE_PROCESSING_REQUIRED;}BOOLEAN SKillDeleteFile(IN HANDLE  FileHandle){    NTSTATUS        ntStatus = STATUS_SUCCESS;    PFILE_OBJECT    fileObject;    PDEVICE_OBJECT  DeviceObject;    PIRP            Irp;    KEVENT          event;    FILE_DISPOSITION_INFORMATION  FileInformation;    IO_STATUS_BLOCK ioStatus;    PIO_STACK_LOCATION irpSp;    PSECTION_OBJECT_POINTERS pSectionObjectPointer;     ntStatus = ObReferenceObjectByHandle(FileHandle,        DELETE,        *IoFileObjectType,        KernelMode,        &fileObject,        NULL);//打开文件的设备对象    if (!NT_SUCCESS(ntStatus))    {        return FALSE;    }       DeviceObject = IoGetRelatedDeviceObject(fileObject);  //返回打开的对象指针    Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);  //分配一个该设备对象的IRP    if (Irp == NULL)    {        ObDereferenceObject(fileObject);        return FALSE;    }    KeInitializeEvent(&event, SynchronizationEvent, FALSE);//初始化IRP的信号状态        FileInformation.DeleteFile = TRUE;//设置IRP    Irp->AssociatedIrp.SystemBuffer = &FileInformation;    Irp->UserEvent = &event;    Irp->UserIosb = &ioStatus;    Irp->Tail.Overlay.OriginalFileObject = fileObject;    Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();    Irp->RequestorMode = KernelMode;        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;//设置完成IPR请求的回调函数    IoSetCompletionRoutine(            Irp,            SkillSetFileCompletion,            &event,            TRUE,            TRUE,            TRUE);    pSectionObjectPointer = fileObject->SectionObjectPointer;    pSectionObjectPointer->ImageSectionObject = 0;    pSectionObjectPointer->DataSectionObject = 0;    IoCallDriver(DeviceObject, Irp);         //发送IRP    KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL);    ObDereferenceObject(fileObject);          //关闭设备对象    return TRUE;}NTSTATUS DriverEntry(        IN PDRIVER_OBJECT DriverObject,        IN PUNICODE_STRING RegistryPath        ){        UNICODE_STRING                uniDeviceName;        UNICODE_STRING                uniSymLink;        NTSTATUS                        ntStatus;        PDEVICE_OBJECT                deviceObject = NULL;      HANDLE              hFileHandle;            RtlInitUnicodeString(&uniDeviceName, NT_DEVICE_NAME);    RtlInitUnicodeString(&uniSymLink, DOS_DEVICE_NAME);     //创建设备对象        ntStatus = IoCreateDevice(                DriverObject,                0,                &uniDeviceName,                FILE_DEVICE_UNKNOWN,                FILE_DEVICE_SECURE_OPEN,                FALSE,                &deviceObject);        if (!NT_SUCCESS(ntStatus))        {                return ntStatus;        }     //设置设备对象的名称    ntStatus = IoCreateSymbolicLink(&uniSymLink, &uniDeviceName);    if (!NT_SUCCESS(ntStatus))    {        IoDeleteDevice(deviceObject);        return ntStatus;    }    DriverObject->DriverUnload = SKillUnloadDriver;    //打开文件    hFileHandle = SkillIoOpenFile(L"\\??\\c:\\calc.exe",                         FILE_READ_ATTRIBUTES,                        FILE_SHARE_DELETE);        DbgPrint("hFileHandle:%08X/n",hFileHandle);   if (hFileHandle!=NULL)   {        SKillDeleteFile(hFileHandle);    //删除文件        ZwClose(hFileHandle);   }   return STATUS_SUCCESS;}


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

菜鸟言论,仅供娱乐。

原创粉丝点击