x64内核强删文件.
- 2019 年 10 月 11 日
- 笔记
x64内核中强删文件的实现
一丶简介
说道删除文件.有各种各样的方法. 有ring3 也有ring0. 而且也有许多对抗的方法. 如ring3想删除一个文件.被占用你就无法删除.此时可以通过解除句柄进行删除 ring0中想删除一个文件.有常规方法也有非常规方法.常规方法就是 设置文件属性为删除.然后进行设置. 还有就是直接调用ZwDeleteFile 进行删除. 暴力删除就是这里所讲的 IRP删除.给底层发送IRP即可进行删除文件.
1.步骤
步骤很简单.基本上说完就可以自己写代码做出
- 1.打开文件.获取文件句柄 (IoCreateFile)
- 2.根据文件句柄,获取文件对象.(有了句柄都应该第一时间想到获取它的对象) (ObReferenceObjectByHandle)
- 3.获取文件对象的设备对象指针.这个发送IRP的时候需要使用(IoGetRelatedDeviceObject)
- 4.申请IRP(IoAllocateIrp)
- 5.初始化你申请的IRP
- 6.获取IRP的下层堆栈,并且初始化信息.(IoGetNextIrpStackLocation)
- 7.设置回调.系统完成IRP之后会调用你这个回调.所以你需要设置事件同步跟你自己同步,才知道IRP已经发送完了.(IoSetCompletionRoutine)
- 8.获取文件对象的域指针.并且设置域指针的两个成员为0.系统以他来判断这个程序是否可以删除.如果不为0.那么则无法删除运行中的文件.
pSectionObjectPointer->ImageSectionObject = 0; pSectionObjectPointer->DataSectionObject = 0;
- 9.发送IRP(IoCallDriver)
- 10.根据 事件 来等待是否IRP完成(KeWaitForSingleObject)
- 11.做完收工.(ZwClose)
2.Nt驱动代码
#include "Driver.h" //删除文件函数的入口 NTSTATUS RetOpenFileHandle(UNICODE_STRING uDelFileName, PHANDLE pFileHandle) { NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; IO_STATUS_BLOCK iostu; HANDLE hFileHandle = 0; if (pFileHandle == NULL) return STATUS_UNSUCCESSFUL; if (KeGetCurrentIrql() > PASSIVE_LEVEL) return 0; if (uDelFileName.Length < 0 || uDelFileName.MaximumLength < 0) { return 0; } OBJECT_ATTRIBUTES ObjAttribute; ObjAttribute.ObjectName = &uDelFileName; ObjAttribute.SecurityDescriptor = NULL; ObjAttribute.SecurityQualityOfService = NULL; ObjAttribute.Attributes = OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE; ObjAttribute.Length = sizeof(OBJECT_ATTRIBUTES); /* InitializeObjectAttributes( &ObjAttribute, &uDelFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);*/ ntStatus = IoCreateFile(&hFileHandle, FILE_READ_ATTRIBUTES, &ObjAttribute, &iostu, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_DELETE, FILE_OPEN, 0, NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING); *pFileHandle = hFileHandle; return ntStatus; } //去掉文件属性 //CallBack回调 NTSTATUS CallBackIrpCompleteionProc( PDEVICE_OBJECT DeviceObject, PIRP Irp, 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; } NTSTATUS PassFileattribute(PFILE_OBJECT pFileObj) { /* 1.申请IRP,初始化IRP 2.初始化同步事件,以及设置回调. 3.设置文件属性为默认 4.发送IRP */ PDEVICE_OBJECT pNextDeviceObj = NULL; PIRP pAllocIrp = NULL; KEVENT IrpSynEvent = {0}; //Irp同步需要的事件同步 FILE_BASIC_INFORMATION fileBasciInfo = { 0 }; IO_STATUS_BLOCK iostu; PIO_STACK_LOCATION IrpStack; //通过文件对象.获取其设备对象指针 pNextDeviceObj = IoGetRelatedDeviceObject(pFileObj); if (pNextDeviceObj == NULL) return STATUS_UNSUCCESSFUL; //通过设备对象指针.确定申请的IRP的大小,注意在完成设置里面进行释放. pAllocIrp = IoAllocateIrp(pNextDeviceObj->StackSize,TRUE); if (pAllocIrp == NULL) return STATUS_UNSUCCESSFUL; //初始化Irp //设置为自动,设置为无信号. KeInitializeEvent(&IrpSynEvent, SynchronizationEvent, FALSE); fileBasciInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; pAllocIrp->AssociatedIrp.SystemBuffer = &fileBasciInfo; pAllocIrp->UserIosb = &iostu; pAllocIrp->UserEvent = &IrpSynEvent; pAllocIrp->Tail.Overlay.OriginalFileObject = pFileObj; pAllocIrp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); //获取下层堆栈.进行设置. //IrpStack = IrpStack = IoGetNextIrpStackLocation(pAllocIrp); IrpStack->MajorFunction = IRP_MJ_SET_INFORMATION; IrpStack->DeviceObject = pNextDeviceObj; IrpStack->FileObject = pFileObj; IrpStack->Parameters.SetFile.Length = sizeof(FILE_BASIC_INFORMATION); IrpStack->Parameters.SetFile.FileObject = pFileObj; IrpStack->Parameters.SetFile.FileInformationClass = FileBasicInformation; //设置完成例程 IoSetCompletionRoutine(pAllocIrp, CallBackIrpCompleteionProc, &IrpSynEvent, TRUE, TRUE, TRUE); //发送IRP IoCallDriver(pNextDeviceObj, pAllocIrp); //等待完成. KeWaitForSingleObject(&IrpSynEvent, Executive, KernelMode, TRUE, NULL); return STATUS_SUCCESS; } NTSTATUS FsDeleteFile(PFILE_OBJECT pFileObj) { /* 1.申请IRP,初始化IRP 2.初始化同步事件,以及设置回调. 3.设置文件属性为默认 4.发送IRP 核心: 核心是设置 FileObject中的域.进而删除正在运行中的文件 */ PDEVICE_OBJECT pNextDeviceObj = NULL; PIRP pAllocIrp = NULL; KEVENT IrpSynEvent = { 0 }; //Irp同步需要的事件同步 FILE_DISPOSITION_INFORMATION fileBasciInfo = { 0 }; //注意此位置.已经变化为 FILE_DISPOSITION_INFORMATION IO_STATUS_BLOCK iostu; PIO_STACK_LOCATION IrpStack; PSECTION_OBJECT_POINTERS pFileExe; //注意此属性要设置为0.欺骗系统进行删除 //通过文件对象.获取其设备对象指针 pNextDeviceObj = IoGetRelatedDeviceObject(pFileObj); if (pNextDeviceObj == NULL) return STATUS_UNSUCCESSFUL; //通过设备对象指针.确定申请的IRP的大小,注意在完成设置里面进行释放. pAllocIrp = IoAllocateIrp(pNextDeviceObj->StackSize, TRUE); if (pAllocIrp == NULL) return STATUS_UNSUCCESSFUL; //初始化Irp //设置为自动,设置为无信号. KeInitializeEvent(&IrpSynEvent, SynchronizationEvent, FALSE); fileBasciInfo.DeleteFile = TRUE; //设置标记为删除 pAllocIrp->AssociatedIrp.SystemBuffer = &fileBasciInfo; pAllocIrp->UserIosb = &iostu; pAllocIrp->UserEvent = &IrpSynEvent; pAllocIrp->Tail.Overlay.OriginalFileObject = pFileObj; pAllocIrp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread(); //获取下层堆栈.进行设置. //IrpStack = IrpStack = IoGetNextIrpStackLocation(pAllocIrp); IrpStack->MajorFunction = IRP_MJ_SET_INFORMATION; IrpStack->DeviceObject = pNextDeviceObj; IrpStack->FileObject = pFileObj; IrpStack->Parameters.SetFile.Length = sizeof(FILE_DISPOSITION_INFORMATION); IrpStack->Parameters.SetFile.FileObject = pFileObj; IrpStack->Parameters.SetFile.FileInformationClass = FileDispositionInformation; //设置完成例程 IoSetCompletionRoutine(pAllocIrp, CallBackIrpCompleteionProc, &IrpSynEvent, TRUE, TRUE, TRUE); //删除正在运行中的文件. pFileExe = pFileObj->SectionObjectPointer; pFileExe->DataSectionObject = 0; pFileExe->ImageSectionObject = 0; //发送IRP IoCallDriver(pNextDeviceObj, pAllocIrp); //等待完成. KeWaitForSingleObject(&IrpSynEvent, Executive, KernelMode, TRUE, NULL); return STATUS_SUCCESS; } NTSTATUS IrpDeleteFileRun(UNICODE_STRING uDelFileName) { KdBreakPoint(); NTSTATUS ntStatus = STATUS_UNSUCCESSFUL; /* 1.首先通过发送IRP去掉文件的属性 2.设置文件属性为删除.进行发送IRP强删文件. */ HANDLE hFileHandle = { 0 }; PFILE_OBJECT pFileObject = NULL; //sep1 : OpenFile Get File Handle ntStatus = RetOpenFileHandle(uDelFileName,&hFileHandle); if (!NT_SUCCESS(ntStatus)) { goto ExitAnRelease; } //sep2: Chang File Handle to FileObject ntStatus = ObReferenceObjectByHandle( hFileHandle, GENERIC_ALL, *IoFileObjectType, KernelMode, &pFileObject, NULL); if (!NT_SUCCESS(ntStatus)) { goto ExitAnRelease; } //setp 3: Pass File Atribute KdBreakPoint(); ntStatus = PassFileattribute(pFileObject); if (!NT_SUCCESS(ntStatus)) { goto ExitAnRelease; } //setp 4: Send Irp DeleteFile KdBreakPoint(); ntStatus = FsDeleteFile(pFileObject); if (!NT_SUCCESS(ntStatus)) { goto ExitAnRelease; } ExitAnRelease: if (pFileObject != NULL) ObDereferenceObject(pFileObject); if (hFileHandle != NULL) ZwClose(hFileHandle); return ntStatus; } NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath) { ULONG iCount = 0; NTSTATUS ntStatus; UNICODE_STRING uDelFileName = { 0 }; pDriverObj->DriverUnload = DriverUnLoad; /*ntStatus = InitDeviceAnSybolicLinkName(pDriverObj); if (!NT_SUCCESS(ntStatus)) { return ntStatus; } ntStatus = InitDisPatchFunction(pDriverObj); if (!NT_SUCCESS(ntStatus)) { return ntStatus; }*/ //也可写成: \??\c:\xxx.txt RtlInitUnicodeString(&uDelFileName, L"//DosDevices//C://123.txt"); IrpDeleteFileRun(uDelFileName); return STATUS_SUCCESS; }
代码测试可以进行强删.