驱动中枚举和关闭内核句柄

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;
}

 

 

 

 

 

 

 

本博客旨在提供高稳定性和良好风格的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值