驱动中枚举和关闭内核句柄
日期: 2016-09-25 分类: 个人收藏 358次阅读
WIN64AST的作者之前发布了一些教程,里面有关于关闭内核句柄的介绍,但是他忘了一件事,所以那份代码并不能真正的关闭内核句柄,而且他的代码。。。不敢用在项目里。有人在看雪上问过类似问题,我也回答过,在vista之后,windows会检查内核句柄值得有效性,也就是为什么下面我提供的代码中会有这一行:
*(PULONG64)HandleValue |= (ULONG64)KERNEL_HANDLE_MASK,为什么,自己想。
因为大多数时候我们都是关闭的文件句柄,这份代码就是只提供了关闭文件句柄,你可以自己改改。
头文件unlockfile.h:
#include "ntifs.h"
#pragma pack(8) //让编译器对这个结构作8字节对齐
typedef struct _FILE_HANDLE_INFO
{
CHAR FilePath[264];
HANDLE hProcess;
HANDLE hHandle;
PVOID Object;
ULONG HandleCount;
}FILE_HANDLE_INFO, *PFILE_HANDLE_INFO;
typedef struct _FILE_HANDLE_INFO_LIST
{
ULONG64 Count;
FILE_HANDLE_INFO Info[1];
}FILE_HANDLE_INFO_LIST, *PFILE_HANDLE_INFO_LIST;
#pragma pack() //取消8字节对齐,恢复为默认字节对齐
PFILE_HANDLE_INFO_LIST EnumFileHandle();
BOOLEAN ForceCloseHandle(HANDLE hProcess, HANDLE HandleValue);
BOOLEAN ForceCloseHandleByPath(const char* Path);
源文件unlockfile.c:
#include "unlockfile.h"
typedef struct _HANDLE_INFO{
UCHAR ObjectTypeIndex;
UCHAR HandleAttributes;
USHORT HandleValue;
ULONG GrantedAccess;
ULONG64 Object;
UCHAR Name[256];
} HANDLE_INFO, *PHANDLE_INFO;
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 {
ULONG64 NumberOfHandles;
SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef struct _OBJECT_BASIC_INFORMATION {
ULONG Attributes;
ACCESS_MASK DesiredAccess;
ULONG HandleCount;
ULONG ReferenceCount;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
ULONG Reserved[3];
ULONG NameInformationLength;
ULONG TypeInformationLength;
ULONG SecurityDescriptorLength;
LARGE_INTEGER CreationTime;
} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;
typedef struct _OBJECT_TYPE_INFORMATION {
UNICODE_STRING TypeName;
ULONG TotalNumberOfHandles;
ULONG TotalNumberOfObjects;
WCHAR Unused1[8];
ULONG HighWaterNumberOfHandles;
ULONG HighWaterNumberOfObjects;
WCHAR Unused2[8];
ACCESS_MASK InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ACCESS_MASK ValidAttributes;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
USHORT MaintainTypeList;
POOL_TYPE PoolType;
ULONG DefaultPagedPoolCharge;
ULONG DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
typedef struct _OBJECT_HANDLE_FLAG_INFORMATION{
BOOLEAN Inherit;
BOOLEAN ProtectFromClose;
}OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION;
NTKERNELAPI
NTSTATUS
ObSetHandleAttributes(HANDLE Handle, POBJECT_HANDLE_FLAG_INFORMATION HandleFlags, KPROCESSOR_MODE PreviousMode);
NTSYSAPI
NTSTATUS
NTAPI ZwQuerySystemInformation(ULONG SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength);
BOOLEAN QueryFileHandle(PFILE_HANDLE_INFO FileHandleInfo)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
ULONG i = 0, RetLength = 0;
CLIENT_ID cid;
OBJECT_ATTRIBUTES oa;
HANDLE hProcess = NULL;
HANDLE hDupObj = NULL;
OBJECT_BASIC_INFORMATION BasicInfo;
POBJECT_NAME_INFORMATION pNameInfo = NULL;
ANSI_STRING AnsiString;
BOOLEAN Result = FALSE;
if (!FileHandleInfo)
return FALSE;
__try
{
cid.UniqueProcess = FileHandleInfo->hProcess;
cid.UniqueThread = (HANDLE)0;
do
{
InitializeObjectAttributes(&oa, NULL, 0, NULL, NULL);
status = ZwOpenProcess(&hProcess, PROCESS_DUP_HANDLE, &oa, &cid);
if (!NT_SUCCESS(status))
break;
status = ZwDuplicateObject(hProcess, FileHandleInfo->hHandle, NtCurrentProcess(), &hDupObj, PROCESS_ALL_ACCESS, 0, DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(status))
break;
status = ZwQueryObject(hDupObj, ObjectBasicInformation, &BasicInfo, sizeof(OBJECT_BASIC_INFORMATION), 0);
if (!NT_SUCCESS(status))
break;
FileHandleInfo->HandleCount = BasicInfo.HandleCount;
pNameInfo = (POBJECT_NAME_INFORMATION)ExAllocatePool(PagedPool, 1024);
if (NULL == pNameInfo)
break;
RtlZeroMemory(pNameInfo, 1024);
status = ZwQueryObject(hDupObj, 1/*ObjectNameInformation*/, pNameInfo, 1024, &RetLength);
if (!NT_SUCCESS(status))
break;
status = RtlUnicodeStringToAnsiString(&AnsiString, &pNameInfo->Name, TRUE);
if (!NT_SUCCESS(status))
break;
RtlCopyMemory(FileHandleInfo->FilePath, AnsiString.Buffer, AnsiString.Length);
FileHandleInfo->FilePath[AnsiString.Length] = '\0';
RtlFreeAnsiString(&AnsiString);
Result = TRUE;
} while (FALSE);
if (NULL != pNameInfo)
{
ExFreePool(pNameInfo);
pNameInfo = NULL;
}
if (NULL != hDupObj)
{
ZwClose(hDupObj);
hDupObj = NULL;
}
if (NULL != hProcess)
{
ZwClose(hProcess);
hProcess = NULL;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
return FALSE;
}
return Result;
}
//对外接口 枚举文件句柄接口 需要调用者自己释放内存
//FileHandleList =EnumFileHandle(); ExFreePool(FileHandleList);
PFILE_HANDLE_INFO_LIST EnumFileHandle()
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PVOID Buffer = NULL;
ULONG NeededSize = 0, i = 0, j = 0;
ULONG64 HandleCount = 0, FileHandleCount = 0;
PSYSTEM_HANDLE_TABLE_ENTRY_INFO pHandleTable = NULL;
PFILE_HANDLE_INFO_LIST InfoList =NULL;
__try
{
NeededSize = 0x20000;
Buffer = ExAllocatePool(NonPagedPool, NeededSize);
if (NULL == Buffer)
return NULL;
RtlZeroMemory(Buffer, NeededSize);
status = ZwQuerySystemInformation(16, Buffer, NeededSize, 0); //SystemHandleInformation
while (status == 0xC0000004) //STATUS_INFO_LENGTH_MISMATCH
{
ExFreePool(Buffer);
NeededSize = NeededSize * 2;
Buffer = ExAllocatePool(NonPagedPool, NeededSize);
if (NULL == Buffer)
break;
RtlZeroMemory(Buffer, NeededSize);
status = ZwQuerySystemInformation(16, Buffer, NeededSize, 0);
if (NeededSize > 100 * 1024 * 1024)
break;
}
if (!NT_SUCCESS(status))
{
ExFreePool(Buffer);
return NULL;
}
HandleCount = ((SYSTEM_HANDLE_INFORMATION *)Buffer)->NumberOfHandles;
pHandleTable = (SYSTEM_HANDLE_TABLE_ENTRY_INFO *)((SYSTEM_HANDLE_INFORMATION *)Buffer)->Handles;
for (i = 0; i < HandleCount; i++)
{
if (pHandleTable[i].ObjectTypeIndex == 28)//FILE TYPE (XP Win7x86 Win7x64)
FileHandleCount++;
}
//分配内存
InfoList = ExAllocatePool(NonPagedPool, sizeof(FILE_HANDLE_INFO_LIST)+ FileHandleCount * sizeof(FILE_HANDLE_INFO));
InfoList->Count = FileHandleCount;
for (i = 0; i < HandleCount; i++)
{
if (pHandleTable[i].ObjectTypeIndex == 28)
{
InfoList->Info[j].hProcess = (HANDLE)pHandleTable[i].UniqueProcessId;
InfoList->Info[j].hHandle = (HANDLE)pHandleTable[i].HandleValue;
InfoList->Info[j].Object = (HANDLE)pHandleTable[i].Object;
QueryFileHandle(&InfoList->Info[j]);//查询更多的句柄信息
j++;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("EXCEPTION_EXECUTE_HANDLER\n"));
}
if (NULL != Buffer)
{
ExFreePool(Buffer);
}
return InfoList;
}
//对外接口 关闭文件句柄
BOOLEAN ForceCloseHandle(HANDLE hProcess, HANDLE HandleValue)
{
KAPC_STATE KapcState;
OBJECT_HANDLE_FLAG_INFORMATION ObjectHandleFlagInfo;
NTSTATUS Status;
PEPROCESS pEprocess = NULL;
ULONG64 Value = (ULONG64)HandleValue;
__try
{
Status = PsLookupProcessByProcessId(hProcess, &pEprocess);
if (!NT_SUCCESS(Status))
return FALSE;
if (pEprocess == NULL || !MmIsAddressValid(pEprocess))
return FALSE;
KeStackAttachProcess(pEprocess, &KapcState);
ObDereferenceObject(pEprocess);
#define KERNEL_HANDLE_MASK ((ULONG_PTR)((LONG)0x80000000))//关闭内核句柄
if (PsGetCurrentProcess() == PsInitialSystemProcess)
{
Value |= (ULONG64)KERNEL_HANDLE_MASK;
HandleValue = (HANDLE)Value;
}
ObjectHandleFlagInfo.Inherit = 0;
ObjectHandleFlagInfo.ProtectFromClose = 0;
Status = ObSetHandleAttributes(HandleValue, &ObjectHandleFlagInfo, KernelMode);
if (!NT_SUCCESS(Status))
{
KdPrint(("ObSetHandleAttributes failed 0x%x\n", Status));
}
KeUnstackDetachProcess(&KapcState);
Status = ZwClose(HandleValue);
if (!NT_SUCCESS(Status))
{
KdPrint(("ZwClose failed 0x%x\n", Status));
return FALSE;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("EXCEPTION_EXECUTE_HANDLER\n"));
return FALSE;
}
return TRUE;
}
//对外接口 按指定路径关闭文件句柄
BOOLEAN ForceCloseHandleByPath(const PCHAR Path)
{
ULONG i = 0;
CHAR* FilePath = NULL;
BOOLEAN Result = FALSE;
PFILE_HANDLE_INFO_LIST FileHandleList = EnumFileHandle();
if (FileHandleList == NULL)
return FALSE;
for (i = 0; i < FileHandleList->Count; i++)
{
FilePath = FileHandleList->Info[i].FilePath;
if (RtlCompareMemory(FilePath, Path, strlen(FilePath)) == strlen(FilePath))
{
Result = ForceCloseHandle(FileHandleList->Info[i].hProcess, FileHandleList->Info[i].hHandle);
KdPrint(("ForceCloseHandle:%s\n", Path));
}
}
ExFreePool(FileHandleList);
return Result;
}
本博客旨在提供高稳定性和良好风格的代码。
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
标签:驱动 驱动 内核句柄
精华推荐