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

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

这个问题也是一个老问题,不过我是菜鸟我有话要说。我在做这个问题的时候查阅了好多资料,其实这个问题不能算解决,这篇文章你将会看到一段比较长的代码,其实这段代码不是我写的,是网上一个比较有名的人(人称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); } HANDLE SkillIoOpenFile(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; } //回调函数 NTSTATUS SkillSetFileCompletion( 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编译成驱动文件。大题的思路我已经用注释说明,细节部分还有待仔细研究。

菜鸟言论,仅供娱乐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值