学习强制删除正在运行的文件

来源:互联网 发布:用友软件培训中心 编辑:程序博客网 时间:2024/06/02 10:36

看雪软件安全论坛 > 软件安全 > 『安全编程论坛』 > 【分享】学习强制删除正在运行的文件
PDA

查看完整版本 : 【分享】学习强制删除正在运行的文件
yaolibing
2009-04-28, 12:03
首先说明一下的是,代码是从网上找来的,自己加了一些理解,供和我一样菜的人学习。
:p:
http://hi.baidu.com/%C3%F7%ED%F8%B5%C4%D0%C4

强制删除文件,简单说来,其实就是自己构造IRP,然后向NTFS.sys发送IRP,先设置文件的属性,再删除文件。删除文件时会先到NTFS.sys的分派例程,依次进入NtfsSetDispositionInfo-》MmFlushImageSection。MmFlushImageSection()函数会检查这个文件对象的SECTION_OBJECT_POINter结构,看里面是不是为空,也就是检查这个文件在没在运行,没有的话,直接返回TRUE。所以我们如果想要删除正在运行的文件,一种方法是,我们可以设置SECTION_OBJECT_POINter结构里的变量都为0。这样MmFlushImageSection()为返回TRUE,表示能删除。另一种方法是HOOK NTFS.sys的导入表中的MmFlushImageSection()函数,在HOOK函数中检查是不是我们要删除的文件,是的话直接返回TRUE也行。下面是完整代码

#include <ntddk.h>

#define NT_DEVICE_NAME L"//Device//SuperKill"
#define DOS_DEVICE_NAME L"//DosDevices//SuperKill"


VOID
SKillUnloadDriver( :p:
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);

return STATUS_MORE_PROCESSING_REQUIRED;
}

BOOLEAN
SKillStripFileAttributes(
IN HANDLE FileHandle
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PFILE_OBJECT fileObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
KEVENT event1;
FILE_BASIC_INFORMATION FileInformation;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION irpSp;

ntStatus = ObReferenceObjectByHandle(FileHandle,
DELETE,
*IoFileObjectType,
KernelMode,
&fileObject,
NULL);//我想知道的是这个文件句柄是在哪个进程的句柄表中

if (!NT_SUCCESS(ntStatus))
{
return FALSE;
}

DeviceObject = IoGetRelatedDeviceObject(fileObject);
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);

if (Irp == NULL)
{
ObDereferenceObject(fileObject);
return FALSE;
}

KeInitializeEvent(&event1, SynchronizationEvent, FALSE);

memset(&FileInformation,0,0x28);

FileInformation.FileAttributes = FILE_ATTRIBUTE_NORMAL;
Irp->AssociatedIrp.SystemBuffer = &FileInformation;
Irp->UserEvent = &event1;
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_BASIC_INFORMATION);
irpSp->Parameters.SetFile.FileInformationClass = FileBasicInformation;
irpSp->Parameters.SetFile.FileObject = fileObject;

IoSetCompletionRoutine(
Irp,
SkillSetFileCompletion,
&event1,
TRUE,
TRUE,
TRUE);

IoCallDriver(DeviceObject, Irp);//调用这个设备对象的驱动对象,并且IO_StACK_LOCAtion会指向下一个,也就是刚刚设置的
                //如果没有文件系统驱动建立的设备对象没有Attacked的话,就调用文件系统驱动的IRP_MJ_SET_INFORMATION分派例程


//会调用NTFS.sys驱动的NtfsFsdSetInformation例程,再会进入NtfsSetBasicInfo()函数,最后它会设置代表此文件的FCB(文件
//控制块结构的一些信息,用来设置代表此文件的属性。最后不知道在哪里会调用IoCompleteRequest,它会依次调用先前设置的回调函数
//回调函数会释放刚分配的IRP和设置事件对象为受信状态。
KeWaitForSingleObject(&event1, Executive, KernelMode, TRUE, NULL);//一等到事件对象变成受信状态就会继续向下执行。

ObDereferenceObject(fileObject);

return TRUE;
}


BOOLEAN
SKillDeleteFile(
IN HANDLE FileHandle
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PFILE_OBJECT fileObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
KEVENT event1;
FILE_DISPOSITION_INFORMATION FileInformation;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION irpSp;
PSECTION_OBJECT_POINTERS pSectionObjectPointer; ////////////////////

SKillStripFileAttributes( FileHandle); //去掉只读属性,才能删除只读文件

ntStatus = ObReferenceObjectByHandle(FileHandle,
DELETE,
*IoFileObjectType,
KernelMode,
&fileObject,
NULL);

if (!NT_SUCCESS(ntStatus))
{
return FALSE;
}

DeviceObject = IoGetRelatedDeviceObject(fileObject);//如果NTFS.sys驱动建立的设备对象上没有附加的设备对象的话,就返回NTFS.sys建立的设备对象
//否则返回的是这个设备对象的highest level设备对象。
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);//如果没有附加,StackSize为7

if (Irp == NULL)
{
ObDereferenceObject(fileObject);
return FALSE;
}

KeInitializeEvent(&event1, SynchronizationEvent, FALSE);

FileInformation.DeleteFile = TRUE;

Irp->AssociatedIrp.SystemBuffer = &FileInformation;
Irp->UserEvent = &event1;
Irp->UserIosb = &ioStatus;
Irp->Tail.Overlay.OriginalFileObject = fileObject;
Irp->Tail.Overlay.Thread = (PETHREAD)KeGetCurrentThread();
Irp->RequestorMode = KernelMode;

irpSp = IoGetNextIrpStackLocation(Irp); //得到文件系统NTFS.sys驱动的设备IO_STACK_LOCATION
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,
SkillSetFileCompletion,
&event1,
TRUE,
TRUE,
TRUE);

//再加上下面这三行代码 ,MmFlushImageSection 函数通过这个结构来检查是否可以删除文件。
pSectionObjectPointer = fileObject->SectionObjectPointer;
pSectionObjectPointer->ImageSectionObject = 0;
pSectionObjectPointer->DataSectionObject = 0;


IoCallDriver(DeviceObject, Irp);//这里会依次进入NTFS.sys驱动的NtfsFsdSetInformation例程->NtfsSetDispositionInfo()->MmFlushImageSection(),
//MmFlushImageSection()这函数是用来检查FILE_OBJECT对象的SECTION_OBJECT_POINTER结构的变量,检查这个文件
//在内存有没有被映射。也就是有没有执行。如果上面那样设置了,也就是说文件可以删除了。我们也可以HOOK NTFS.sys导入表中的
//的MmFlushImageSection(),来检查这个文件对象是不是我们要删除 的,是的话,返回TRUE就行了。
KeWaitForSingleObject(&event1, 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,
0x100u,
&uniDeviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
TRUE,
&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"//Device//HarddiskVolume1//test.exe",
FILE_READ_ATTRIBUTES,
FILE_SHARE_DELETE); //得到文件句柄

if (hFileHandle!=NULL)
{
SKillDeleteFile(hFileHandle);
ZwClose(hFileHandle);
}
return STATUS_SUCCESS;
}
achillis
2009-04-28, 12:16
很经典的代码,值得收藏,我在好几个驱动中都看到过~~
sand
2009-04-28, 12:28
不错。。。已经收藏
better
2009-04-28, 14:17
太好了,学习……
deryope
2009-04-28, 14:30
正好我也在看这个,LZ说得较详细:):

这个代码实际上起作用的是这三行:
//再加上下面这三行代码 ,MmFlushImageSection 函数通过这个结构来检查是否可以删除文件。
pSectionObjectPointer = fileObject->SectionObjectPointer;
pSectionObjectPointer->ImageSectionObject = 0;
pSectionObjectPointer->DataSectionObject = 0;

因为MmFlushImageSection代码里做了这样的检查:
ControlArea = (PCONTROL_AREA)(SectionPointer->DataSectionObject);
if (ControlArea != NULL) {
...
return FALSE;
}
所以清0就可以删正在使用的文件。


感觉 防这个代码删文件,可以Hook MmFlushImageSection直接返回False,只是处理比较麻烦(也许这样就什么文件也删不掉了)。
qihoocom
2009-04-28, 15:31
又是抄我3年前的代码~
mkuymkuy
2009-04-28, 16:33
看看~~吓人
wangzheye
2009-04-28, 18:02
为什么没人从硬件觉得考虑写删除文件的代码,直接操作IDE可将系统文件东西都可以删除。只要磁盘中有的都行。
weolar
2009-04-28, 19:19
为什么没人从硬件觉得考虑写删除文件的代码,直接操作IDE可将系统文件东西都可以删除。只要磁盘中有的都行。

不是没人考虑,是比较麻烦。既要考虑不同的ide接口,又要考虑不同的文件系统。而且ntfs系统比较复杂。当然你放出来我们都支持你:):
sudami
2009-04-28, 20:01
还放什么啊. ntfs3g开源的.自己下去就是了...:3:
weolar
2009-04-28, 23:27
还放什么啊. ntfs3g开源的.自己下去就是了...:3:
:p: 对这方面了解比较少,去看看~~
dnybz
2009-04-29, 13:06
首先说明一下的是,代码是从网上找来的,自己加了一些理解,供和我一样菜的人学习。
:p:
http://hi.baidu.com/%C3%F7%ED%F8%B5%C4%D0%C4

强制删除文件,简单说来,其实就是自己构造IRP,然后向NTFS.sys发送IRP,先设置文件的属性,再删除文件。...

:eek:

你这个和原来那个有点不同?
BeWideWay
2009-05-12, 15:36
mask mask
thx for sharing
cvcvxk
2009-05-12, 16:03
新时代了,打开文件居然还有IoCreateFile?这是个新时代,要用新方法打开文件,另外还要防止XX文件大法和sudami的深度hook等等,所以还是自己解析文件再去XX吧~
林郎君
2009-05-12, 16:13
谢谢楼主发布分享

收藏之
Possible
2009-05-13, 15:40
ntfs3g可以看看,很不错
keweijie
2009-05-14, 00:07
谢谢分享了啊
枯藤
2009-05-15, 02:51
很不错的代码。
值得收藏。
谢谢楼主。
tensai
2009-07-15, 15:01
我已经安装了2008 DDK

请问怎么编译和运行啊?
taday
2009-07-15, 21:37
谢谢楼主分享,学习一下:):
kangken
2009-07-16, 02:08
学习学习。。感谢分享。
sding
2009-07-16, 13:40
收藏 !!!
BeWideWay
2009-07-22, 10:23
I just wonder if there is anyother approach to force delete those under using file so much as system files?
WinDebug
2009-07-22, 14:55
不管怎么样,还是顶下。:):