836 views
首页 > 技术心得 > 获取文件句柄的基本信息

获取文件句柄的基本信息

2010年8月5日

有时候我们想得到文件句柄的一些信息, 比如这个句柄的引用计数, 属性等等的. 我就写了下面的函数.

声明的头文件:

typedef LONG NTSTATUS;

typedef struct _OBJECT_BASIC_INFORMATION
{
	ULONG Attributes;
	ACCESS_MASK GrantedAccess;
	ULONG HandleCount;
	ULONG PointerCount;
	ULONG PagedPoolCharge;
	ULONG NonPagedPoolCharge;
	ULONG Reserved[3];
	ULONG NameInfoSize;
	ULONG TypeInfoSize;
	ULONG SecurityDescriptorSize;
	LARGE_INTEGER CreationTime;
} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;

NTSTATUS WINAPI _GetHandleInformation
	(
	HANDLE ProcessHandle,
	HANDLE Handle,
	POBJECT_BASIC_INFORMATION BasicInformation
	);


以下是实现文件:

#include <windows.h>
#include <tchar.h>

#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)

#define __out_bcount_opt(x)
#define __in
#define __in_opt
#define __out_opt

typedef enum _OBJECT_INFORMATION_CLASS
{
	ObjectBasicInformation,
	ObjectNameInformation,
	ObjectTypeInformation,
	ObjectTypesInformation,
	ObjectHandleFlagInformation,
	ObjectSessionInformation,
	MaxObjectInfoClass,
} OBJECT_INFORMATION_CLASS;

typedef NTSTATUS (WINAPI * PFN_NtQueryObject)
	(
	__in HANDLE Handle,
	__in OBJECT_INFORMATION_CLASS ObjectInformationClass,
	__out_bcount_opt(ObjectInformationLength) PVOID ObjectInformation,
	__in ULONG ObjectInformationLength,
	__out_opt PULONG ReturnLength
	);

typedef NTSTATUS (WINAPI * PFN_NtClose) ( __in HANDLE Handle );

typedef NTSTATUS (WINAPI * PFN_NtDuplicateObject)
	(
	__in HANDLE SourceProcessHandle,
	__in HANDLE SourceHandle,
	__in_opt HANDLE TargetProcessHandle,
	__out_opt PHANDLE TargetHandle,
	__in ACCESS_MASK DesiredAccess,
	__in ULONG HandleAttributes,
	__in ULONG Options
	);

#define NtCurrentProcess() ( (HANDLE) -1 )
#define NtCurrentThread() ( (HANDLE) -2 )   

NTSTATUS WINAPI _GetHandleInformation
	(
	__in HANDLE ProcessHandle,
	__in HANDLE Handle,
	__out_opt POBJECT_BASIC_INFORMATION BasicInformation
	)
{
	HMODULE hNtDll = NULL;
	BOOL bDup = FALSE;

	NTSTATUS status;
	HANDLE dupHandle = NULL;
	PFN_NtDuplicateObject pfn_NtDuplicateObject = NULL;
	PFN_NtQueryObject pfn_NtQueryObject = NULL;
	PFN_NtClose pfn_NtClose = NULL;

	if (Handle == NULL || Handle == NtCurrentProcess() ||
		Handle == NtCurrentThread())
	{
		return STATUS_INVALID_HANDLE;
	}

	hNtDll = GetModuleHandle(_T("ntdll.dll"));
	if (NULL == hNtDll) {
		return STATUS_INVALID_HANDLE;
	}

	pfn_NtDuplicateObject = (PFN_NtDuplicateObject)
		GetProcAddress(hNtDll, "NtDuplicateObject");
	pfn_NtQueryObject = (PFN_NtQueryObject)
		GetProcAddress(hNtDll, "NtQueryObject");
	pfn_NtClose = (PFN_NtClose) GetProcAddress(hNtDll, "NtClose");

	if (NULL == pfn_NtQueryObject) {
		return STATUS_INVALID_HANDLE;
	}

	// Duplicate the handle if we're not using KPH.

	// However, we obviously don't need to duplicate it
	// if the handle is in the current process.
	if (ProcessHandle != NtCurrentProcess())
	{
		status = pfn_NtDuplicateObject(ProcessHandle, Handle,
			NtCurrentProcess(), &dupHandle, 0, 0, 0);

		if (!NT_SUCCESS(status))
			return status;
		bDup = TRUE;
	}
	else
	{
		dupHandle = Handle;
	}

	// Get basic information.
	if (BasicInformation)
	{
		status = pfn_NtQueryObject(
			dupHandle,
			ObjectBasicInformation,
			BasicInformation,
			sizeof(OBJECT_BASIC_INFORMATION),
			NULL
			);

		if (NT_SUCCESS(status))
		{
			// The object was referenced in NtQueryObject and
			// a handle was opened to the object. We need to
			// subtract 1 from the pointer count, then subtract
			// 1 from both counts.
			BasicInformation->PointerCount -= 1;
			if (bDup)
			{
				BasicInformation->HandleCount -= 1;
				BasicInformation->PointerCount -= 1;
			}
		}
	}

	if (bDup) {
		pfn_NtClose(dupHandle);
	}
	return status;
}

技术心得 , , ,

  1. 目前还没有任何评论.
  1. 目前还没有任何 trackbacks 和 pingbacks.