强杀文件
思路:
打开文件:IoCreateFile
- 果文件被其他程序独占:
ZwQuerySystemInformation 全局句柄表,找到句柄
ZwDuplicateObject DUPLICATE_CLOSE_SOURCE 拷贝句柄,并关闭之前句柄 - 如果文件正在运行:(不能直接删除)
pSectionObjectPointer = fileObject->SectionObjectPointer pSectionObjectPointer->ImageSectionObject = 0 pSectionObjectPointer->DataSectionObject = 0 自己构建IRP(不用ZwDeleteFile,防止这些函数被hook!)
C代码
# include <ntddk.h>
# include <ntimage.h>
# include <ntdef.h>
# include "DelFile.h"
PDEVICE_OBJECT
g_HookDevice;
NTSTATUS
dfQuerySymbolicLink(
IN
PUNICODE_STRING
SymbolicLinkName,
OUT
PUNICODE_STRING
LinkTarget
)
{
OBJECT_ATTRIBUTES
oa;
NTSTATUS
status;
HANDLE
handle;
InitializeObjectAttributes(
& oa,
SymbolicLinkName,
OBJ_CASE_INSENSITIVE,
0,
0);
status = ZwOpenSymbolicLinkObject( & handle, GENERIC_READ, & oa);
if (!NT_SUCCESS(status))
{
return status;
}
LinkTarget->MaximumLength = 1024 * sizeof(WCHAR);
LinkTarget->Length = 0;
LinkTarget->Buffer = ExAllocatePoolWithTag(PagedPool, LinkTarget->MaximumLength, 'A0');
if (!LinkTarget->Buffer)
{
ZwClose(handle);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(LinkTarget->Buffer, LinkTarget->MaximumLength);
status = ZwQuerySymbolicLinkObject(handle, LinkTarget, NULL);
ZwClose(handle);
if (!NT_SUCCESS(status))
{
ExFreePool(LinkTarget->Buffer);
}
return status;
}
BOOLEAN
dfCloseFileHandle(WCHAR * name) // 遍历全局句柄表,找到目标句柄,解除独占并删除
{
NTSTATUS
status;
PVOID
buf = NULL;
PSYSTEM_HANDLE_INFORMATION
pSysHandleInfo;
SYSTEM_HANDLE_TABLE_ENTRY_INFO
handleTEI;
ULONG
size = 1;
ULONG
NumOfHandle = 0;
ULONG
i;
CLIENT_ID
cid;
HANDLE
hHandle;
HANDLE
hProcess;
HANDLE
hDupObj;
HANDLE
hFile;
HANDLE
link_handle;
OBJECT_ATTRIBUTES
oa;
ULONG
FileType;
ULONG
processID;
UNICODE_STRING
uLinkName;
UNICODE_STRING
uLink;
OBJECT_ATTRIBUTES
objectAttributes;
IO_STATUS_BLOCK
IoStatus;
ULONG
ulRet;
PVOID
fileObject;
POBJECT_NAME_INFORMATION
pObjName;
UNICODE_STRING
delFileName = {0};
int
length;
WCHAR
wVolumeLetter[3];
WCHAR * pFilePath;
UNICODE_STRING
uVolume;
UNICODE_STRING
uFilePath;
UNICODE_STRING
NullString = RTL_CONSTANT_STRING(L
"");
BOOLEAN
bRet = FALSE;
for (size = 1;; size *= 2)
{
if (NULL == (buf = ExAllocatePoolWithTag(NonPagedPool, size, 'FILE')))
{
DbgPrint(("alloc mem failed\n"));
goto
Exit;
}
RtlZeroMemory(buf, size);
status = ZwQuerySystemInformation(SystemHandleInformation, buf, size, NULL);
if (!NT_SUCCESS(status))
{
if (STATUS_INFO_LENGTH_MISMATCH == status)
{
ExFreePool(buf);
buf = NULL;
}
else
{
DbgPrint(("ZwQuerySystemInformation() failed"));
goto Exit;
}
}
else
{
break;
}
}
pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)
buf;
NumOfHandle = pSysHandleInfo->NumberOfHandles;
/ *Get
the
volume
character
like
C: * /
// \??\c:\1.
exe -->\device\harddiskvolume3\1.
exe.doc
wVolumeLetter[0] = name[4];
wVolumeLetter[1] = name[5];
wVolumeLetter[2] = 0;
uLinkName.Buffer = ExAllocatePoolWithTag(NonPagedPool, 256 + sizeof(ULONG), 'A1');
uLinkName.MaximumLength = 256;
RtlInitUnicodeString( & uVolume, wVolumeLetter);
RtlInitUnicodeString( & uLink, L
"\\DosDevices\\");
RtlCopyUnicodeString( & uLinkName, & uLink);
status = RtlAppendUnicodeStringToString( & uLinkName, & uVolume);
if (!NT_SUCCESS(status))
{
KdPrint(("RtlAppendUnicodeStringToString() failed"));
return FALSE;
}
dfQuerySymbolicLink( & uLinkName, & delFileName);
RtlFreeUnicodeString( & uLinkName);
KdPrint(("delFileName:%wZ", & delFileName));
pFilePath = (WCHAR *) & name[6];
RtlInitUnicodeString( & uFilePath, pFilePath);
RtlAppendUnicodeStringToString( & delFileName, & uFilePath);
if (!NT_SUCCESS(status))
{
KdPrint(("RtlAppendUnicodeStringToString() failed"));
return FALSE;
}
KdPrint(("delFile:%wZ", & delFileName));
for (i = 0; i < NumOfHandle; i++)
{
handleTEI = pSysHandleInfo->Handles[i];
if (handleTEI.ObjectTypeIndex != 25 & & handleTEI.ObjectTypeIndex != 28) // 28文件, 25设备对象
continue;
processID = (ULONG)
handleTEI.UniqueProcessId;
cid.UniqueProcess = (HANDLE)
processID;
cid.UniqueThread = (HANDLE)
0;
hHandle = (HANDLE)
handleTEI.HandleValue;
InitializeObjectAttributes( & oa, NULL, 0, NULL, NULL);
status = ZwOpenProcess( & hProcess, PROCESS_DUP_HANDLE, & oa, & cid);
if (!NT_SUCCESS(status))
{
KdPrint(("ZwOpenProcess:%d Fail ", processID));
continue;
}
status = ZwDuplicateObject(hProcess, hHandle, NtCurrentProcess(), & hDupObj, \ // 拷贝到自己进程
PROCESS_ALL_ACCESS, 0, DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(status))
{
DbgPrint(("ZwDuplicateObject1 : Fail "));
continue;
}
status = ObReferenceObjectByHandle(
hDupObj,
FILE_ANY_ACCESS,
0,
KernelMode,
& fileObject,
NULL);
if (!NT_SUCCESS(status))
{
DbgPrint(("ObReferenceObjectByHandle : Fail "));
continue;
}
pObjName = (POBJECT_NAME_INFORMATION)
ExAllocatePoolWithTag(NonPagedPool, \
sizeof(OBJECT_NAME_INFORMATION) + 1024 * sizeof(WCHAR), 'A1');
if (STATUS_SUCCESS != (status = ObQueryNameString(fileObject, pObjName, \
sizeof(OBJECT_NAME_INFORMATION) + 1024 * sizeof(WCHAR), & ulRet)))
{
ObDereferenceObject(fileObject);
continue;
}
if (RtlCompareUnicodeString( & pObjName->Name, & delFileName, TRUE) == 0)
{
ObDereferenceObject(fileObject);
ZwClose(hDupObj);
status = ZwDuplicateObject(hProcess, hHandle, NtCurrentProcess(), & hDupObj, \
PROCESS_ALL_ACCESS, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
if (!NT_SUCCESS(status))
{
DbgPrint(("ZwDuplicateObject2 : Fail "));
// return FALSE;
}
else
{
ZwClose(hDupObj);
bRet = TRUE;
// return TRUE;
}
break;
}
ExFreePool(pObjName);
pObjName = NULL;
ObDereferenceObject(fileObject);
ZwClose(hDupObj);
ZwClose(hProcess);
}
Exit:
if (pObjName != NULL)
{
ExFreePool(pObjName);
pObjName = NULL;
}
if (delFileName.Buffer != NULL)
{
ExFreePool(delFileName.Buffer);
}
if (buf != NULL)
{
ExFreePool(buf);
buf = NULL;
}
return (bRet);
}
NTSTATUS
dfOpenFile(WCHAR * name, PHANDLE
phFileHandle, ACCESS_MASK
access, ULONG
share)
{
IO_STATUS_BLOCK
iosb;
NTSTATUS
stat;
OBJECT_ATTRIBUTES
oba;
UNICODE_STRING
nameus;
if (KeGetCurrentIrql() > PASSIVE_LEVEL) {
return 0;}
RtlInitUnicodeString( & nameus, name);
InitializeObjectAttributes(
& oba,
& nameus,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
0,
0);
stat = IoCreateFile(
phFileHandle,
access,
& oba,
& iosb,
0,
FILE_ATTRIBUTE_NORMAL,
share,
FILE_OPEN,
0,
NULL,
0,
0,
NULL,
IO_NO_PARAMETER_CHECKING);
return stat;
}
NTSTATUS
dfSkillSetFileCompletion(
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
dfDelFile(WCHAR * name)
{
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;
HANDLE
handle;
ntStatus = dfOpenFile(name, & handle, FILE_READ_ATTRIBUTES | DELETE, FILE_SHARE_DELETE); // 打开句柄
if (ntStatus == STATUS_OBJECT_NAME_NOT_FOUND | |
ntStatus == STATUS_OBJECT_PATH_NOT_FOUND)
{
KdPrint(("No such file"));
return FALSE;
}
else if (!NT_SUCCESS(ntStatus)) // 打开句柄
{
if (dfCloseFileHandle(name)) // 遍历全局句柄表,关闭独占打开的句柄
{
ntStatus = dfOpenFile(name, & handle, FILE_READ_ATTRIBUTES | DELETE, FILE_SHARE_DELETE);
if (!NT_SUCCESS(ntStatus))
return FALSE;
}
else
{
return FALSE;
}
}
ntStatus = ObReferenceObjectByHandle(handle,
DELETE,
*IoFileObjectType,
KernelMode,
& fileObject,
NULL);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("ObReferenceObjectByHandle()");
ZwClose(handle);
return FALSE;
}
DeviceObject = IoGetRelatedDeviceObject(fileObject); // 得到DeviceObjct
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); // 构造irp
if (Irp == NULL)
{
ObDereferenceObject(fileObject);
ZwClose(handle);
return FALSE;
}
KeInitializeEvent( & event, SynchronizationEvent, FALSE);
FileInformation.DeleteFile = TRUE;
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;
IoSetCompletionRoutine(
Irp,
dfSkillSetFileCompletion, // irp下发
& event,
TRUE,
TRUE,
TRUE);
// 删除正在运行中的exe所做的处理
pSectionObjectPointer = fileObject->SectionObjectPointer;
if (pSectionObjectPointer)
{
pSectionObjectPointer->ImageSectionObject = 0;
pSectionObjectPointer->DataSectionObject = 0;
}
ntStatus = IoCallDriver(DeviceObject, Irp);
if (!NT_SUCCESS(ntStatus))
{
ObDereferenceObject(fileObject);
ZwClose(handle);
return FALSE;
}
KeWaitForSingleObject( & event, Executive, KernelMode, TRUE, NULL);
// IoFreeIrp(Irp);
ObDereferenceObject(fileObject);
ZwClose(handle);
return TRUE;
}
NTSTATUS
OnUnload(IN
PDRIVER_OBJECT
DriverObject)
{
UNICODE_STRING
deviceLinkUnicodeString;
PDEVICE_OBJECT
p_NextObj;
DbgPrint("OnUnload called\n");
p_NextObj = DriverObject->DeviceObject;
if (p_NextObj != NULL)
{
RtlInitUnicodeString( & deviceLinkUnicodeString, deviceLinkBuffer);
IoDeleteSymbolicLink( & deviceLinkUnicodeString);
IoDeleteDevice(DriverObject->DeviceObject);
}
return STATUS_SUCCESS;
}
NTSTATUS
DriverEntry(IN
PDRIVER_OBJECT
DriverObject, IN
PUNICODE_STRING
RegistryPath)
{
NTSTATUS
ntStatus;
UNICODE_STRING
deviceNameUnicodeString;
UNICODE_STRING
deviceLinkUnicodeString;
RtlInitUnicodeString( & deviceNameUnicodeString,
deviceNameBuffer);
RtlInitUnicodeString( & deviceLinkUnicodeString,
deviceLinkBuffer);
ntStatus = IoCreateDevice(DriverObject,
0,
& deviceNameUnicodeString,
FILE_DEVICE_SWAP,
0,
TRUE,
& g_HookDevice);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint(("Failed to create device!\n"));
return ntStatus;
}
/ *We
test
the
DelFile()
function
here * /
if (dfDelFile(L"\\??\\c:\\1.exe"))
{
KdPrint(("Deleted"));
}
else
{
KdPrint(("Failed"));
}
if (dfDelFile(L"\\??\\c:\\2.exe"))
{
KdPrint(("Deleted"));
}
else
{
KdPrint(("Failed"));
}
ntStatus = IoCreateSymbolicLink( & deviceLinkUnicodeString,
& deviceNameUnicodeString);
if (!NT_SUCCESS(ntStatus))
{
IoDeleteDevice(DriverObject->DeviceObject);
DbgPrint("Failed to create symbolic link!\n");
return ntStatus;
}
DriverObject->DriverUnload = OnUnload;
return STATUS_SUCCESS;
}
//头文件:
#ifndef _MAIN_H_
#define _MAIN_H_
const WCHAR deviceLinkBuffer[] = L"\\DosDevices\\Delfile";
const WCHAR deviceNameBuffer[] = L"\\Device\\Delfile";
typedef unsigned long DWORD;
#define SystemHandleInformation 16
#define INVALID_PID_VALUE 0xFFFFFFFF
#define FILE_DEVICE_SWAP 0x0000800a
typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
USHORT UniqueProcessId;
USHORT CreatorBackTraceIndex;
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
PVOID Object;
ULONG GrantedAccess;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
NTSTATUS
ObQueryNameString(
IN PVOID Object,
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
IN ULONG Length,
OUT PULONG ReturnLength
);
NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
ULONG SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
NTSYSAPI
NTSTATUS
NTAPI
ZwDuplicateObject(
IN HANDLE SourceProcessHandle,
IN HANDLE SourceHandle,
IN HANDLE TargetProcessHandle OPTIONAL,
OUT PHANDLE TargetHandle OPTIONAL,
IN ACCESS_MASK DesiredAccess,
IN ULONG HandleAttributes,
IN ULONG Options
);
NTSYSAPI
NTSTATUS
NTAPI
ZwOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId
);
/* The file name looks like L"\\??\\C:\\hello.doc" */
BOOLEAN dfDelFile(WCHAR* name);
#endif