学习强制删除正在运行的文件
看雪軟件安全論壇 > 軟件安全 > 『安全編程論壇』 > 【分享】學習強制刪除正在運行的文件
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
不管怎么樣,還是頂下。:):
總結
以上是生活随笔為你收集整理的学习强制删除正在运行的文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GDI中的坐标映射问题
- 下一篇: MFC让文档/视图结构程序支持滚动条