欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]X64下的解析句柄表

[原创]X64下的解析句柄表

新人发帖,牛牛们乐呵乐呵就好啦,
关于PspCidTable的寻找,我是通过PsLookupProcessByProcessId查找特征码寻找pspCidTable和32位没什么区别。可以在坛子里面搜搜
疑问:我想在KPCR中的KdVersionBlock中寻找,但是64位系统不知道为什么总是NULL,各位牛牛知道的求科普~

寻找PspCidTable:

SIZE_T FindCidTable()

{

	SIZE_T  CidTableAddr = 0;

	UNICODE_STRING ustPsFuncName;

	RtlInitUnicodeString(&ustPsFuncName, L"PsLookupProcessByProcessId");

	PUCHAR startAddr = (PUCHAR)MmGetSystemRoutineAddress(&ustPsFuncName);

	//DbgPrint("startAddr:0x%02X,startAddr+1:0x%02X\n", *startAddr, *(startAddr+1));

	for (ULONG64 i = 0; i < 100; i++)

	{

		if (*(startAddr + i) == 0x48 &&

			*(startAddr + i + 1) == 0x8b &&

			*(startAddr + i + 2) == 0x0d)

		{

			CidTableAddr = (SIZE_T)(*(PULONG)(startAddr + i + 3) + (startAddr + i + 3 + 4)) & 0xFFFFFFFEFFFFFFFF;

			DbgPrint("CidTableAddr:%p\n", CidTableAddr);

			break;

		}

	}

	return CidTableAddr;

}

二:实现
相关结构:

原32位结构:

typedef struct _HANDLE_TABLE

{

     ULONG TableCode;

     PEPROCESS QuotaProcess;

     PVOID UniqueProcessId;

     EX_PUSH_LOCK HandleLock;

     LIST_ENTRY HandleTableList;

     EX_PUSH_LOCK HandleContentionEvent;

     PHANDLE_TRACE_DEBUG_INFO DebugInfo;

     LONG ExtraInfoPages;

     ULONG Flags;

     ULONG StrictFIFO: 1;

     LONG FirstFreeHandle;

     PHANDLE_TABLE_ENTRY LastFreeHandleEntry;

     LONG HandleCount;

     ULONG NextHandleNeedingPool;

} HANDLE_TABLE, *PHANDLE_TABLE;

现在x64结构:

typedef struct _HANDLE_TABLE

{

	ULONG64 TableCode;

	PEPROCESS QuotaProcess;

	PVOID UniqueProcessId;

	EX_PUSH_LOCK HandleLock;

	LIST_ENTRY HandleTableList;

	EX_PUSH_LOCK HandleContentionEvent;

	PHANDLE_TRACE_DEBUG_INFO DebugInfo;

	LONG ExtraInfoPages;

	ULONG Flags;

	//ULONG StrictFIFO : 1;

	LONG64 FirstFreeHandle;

	PHANDLE_TABLE_ENTRY LastFreeHandleEntry;

	LONG HandleCount;

	ULONG NextHandleNeedingPool;

} HANDLE_TABLE, *PHANDLE_TABLE;

32位和64位结构体有点差别,注意LONG64 FirstFreeHandle;

其他的和32位没啥区别,就是一级表和二级表的数量 分别为:
#define   MAX_ENTRY_COUNT (0x1000/16)  //一级表中的 HANDLE_TABLE_ENTRY个数
#define   MAX_ADDR_COUNT   (0x1000/8) //二级表和 三级表中的地址个数

之后就是便利的核心代码了,方法是自己山寨ExEnumerateHandleRoutine
NTSTATUS EnumProcessByPspCidTable()

{

	NTSTATUS status = STATUS_UNSUCCESSFUL;

	PHANDLE_TABLE pHandleTable = NULL;

	pHandleTable =(PHANDLE_TABLE)*(PSIZE_T)FindCidTable();

	HANDLE hHanel;

	UNICODE_STRING usObGetObjectType;

	DbgPrint("pHandleTable:%p\n", pHandleTable);

	////获取system eprocess 结构,我这win7 是个二级表,为了方便我直接写了,关于句柄表可以看博客http://blog.csdn.net/zfdyq0

	//PEPROCESS process = (PEPROCESS)(*(PULONG)(*(PULONG)(pHandleTable->TableCode & 0xfffffff0)+8)&0xfffffff8);

	RtlInitUnicodeString(&usObGetObjectType, L"ObGetObjectType");

	g_pObGetObjectType = MmGetSystemRoutineAddress(&usObGetObjectType);

	DbgPrint("g_pObGetObjectType:%p\n", g_pObGetObjectType);

	MyEnumHandleTable(pHandleTable, MyEnumerateHandleRoutine, NULL, &hHanel);

	return status;

}

BOOLEAN MyEnumerateHandleRoutine(

	IN PHANDLE_TABLE_ENTRY HandleTableEntry,

	IN HANDLE Handle,

	IN PVOID EnumParameter

	)

{

	BOOLEAN Result = FALSE;

	ULONG64 ProcessObject;

	POBJECT_TYPE ObjectType;

	PVOID Object;

	UNICODE_STRING ustObjectName;

	UNREFERENCED_PARAMETER(EnumParameter);

	UNREFERENCED_PARAMETER(ustObjectName);

	ProcessObject = (HandleTableEntry->Value)&~7; //掩去低三位

	Object = (PVOID)((ULONG64)HandleTableEntry->Object&~7);

	ObjectType = g_pObGetObjectType(Object);

	if (MmIsAddressValid(HandleTableEntry))

	{

		if (ObjectType == *PsProcessType)//判断是否为Process

		{

			//注意PID其实就是Handle,而 不是从EPROCESS中取,可以对付伪pid

			UCHAR* szName = PsGetProcessImageFileName((PEPROCESS)ProcessObject);

			stcProcessInfo[nProcessCount].hProcessID = Handle;

			RtlCopyMemory(stcProcessInfo[nProcessCount].szName, szName, strlen(szName) + 1);

			nProcessCount++;

			DbgPrint("PID=%4d\t EPROCESS=0x%p %s\n", Handle, ProcessObject, PsGetProcessImageFileName((PEPROCESS)ProcessObject));

		}

	}

	return Result;//返回FALSE继续

}

//自己实现一个山寨的MyEnumHandleTable,接口和ExEnumHandleTable一样

#define   MAX_ENTRY_COUNT (0x1000/16)  //一级表中的 HANDLE_TABLE_ENTRY个数

#define   MAX_ADDR_COUNT   (0x1000/8) //二级表和 三级表中的地址个数

BOOLEAN

MyEnumHandleTable(

PHANDLE_TABLE HandleTable,

MY_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,

PVOID EnumParameter,

PHANDLE Handle

)

{

	ULONG64 i, j, k;

	ULONG_PTR CapturedTable;

	ULONG64 TableLevel;

	PHANDLE_TABLE_ENTRY TableLevel1, *TableLevel2, **TableLevel3;

	BOOLEAN CallBackRetned = FALSE;

	BOOLEAN ResultValue = FALSE;

	ULONG64 MaxHandle;

	//判断几个参数是否有效

	if (!HandleTable

		&& !EnumHandleProcedure

		&& !MmIsAddressValid(Handle))

	{

		return ResultValue;

	}

	//取表基址和表的级数

	CapturedTable = (HandleTable->TableCode)&~3;

	TableLevel = (HandleTable->TableCode) & 3;

	MaxHandle = HandleTable->NextHandleNeedingPool;

	DbgPrint("句柄上限值为0x%X\n", MaxHandle);

	//判断表的等级

	switch (TableLevel)

	{

	case 0:

	{

			  //一级表

			  TableLevel1 = (PHANDLE_TABLE_ENTRY)CapturedTable;

			  DbgPrint("解析一级表 0x%p...\n", TableLevel1);

			  for (i = 0; i < MAX_ENTRY_COUNT; i++)

			  {

				  *Handle = (HANDLE)(i * 4);

				  if (TableLevel1[i].Object && MmIsAddressValid(TableLevel1[i].Object))

				  {

					  //对象有效时,再调用回调函数

					  CallBackRetned = EnumHandleProcedure(&TableLevel1[i], *Handle, EnumParameter);

					  if (CallBackRetned)  break;

				  }

			  }

			  ResultValue = TRUE;

	}

		break;

	case 1:

	{

			  //二级表

			  TableLevel2 = (PHANDLE_TABLE_ENTRY*)CapturedTable;

			  DbgPrint("解析二级表 0x%p...\n", TableLevel2);

			  DbgPrint("二级表的个 数:%d\n", MaxHandle / (MAX_ENTRY_COUNT*4));

			  for (j = 0; j < MaxHandle / (MAX_ENTRY_COUNT * 4); j++)

			  {

				  TableLevel1 = TableLevel2[j];

				  if (!TableLevel1)

					  break; //为零则跳出

				  for (i = 0; i < MAX_ENTRY_COUNT; i++)

				  {

					  *Handle = (HANDLE)(j*MAX_ENTRY_COUNT * 4 + i * 4);

					  if (TableLevel1[i].Object && MmIsAddressValid(TableLevel1[i].Object))

					  {

						  //对象有效时,再调用回调函数

						  CallBackRetned = EnumHandleProcedure(&TableLevel1[i], *Handle, EnumParameter);

						  if (CallBackRetned)  break;

					  }

				  }

			  }

			  ResultValue = TRUE;

	}

		break;

	case 2:

	{

			  //三级表

			  TableLevel3 = (PHANDLE_TABLE_ENTRY**)CapturedTable;

			  DbgPrint("解析三级表 0x%p...\n", TableLevel3);

			  DbgPrint("三级表的个 数:%d\n", MaxHandle / (MAX_ENTRY_COUNT * 4 * MAX_ADDR_COUNT));

			  for (k = 0; k < MaxHandle / (MAX_ENTRY_COUNT * 4 * MAX_ADDR_COUNT); k++)

			  {

				  TableLevel2 = TableLevel3[k];

				  if (!TableLevel2)

					  break; //为零则跳出

				  for (j = 0; j < MaxHandle / (MAX_ENTRY_COUNT * 4); j++)

				  {

					  TableLevel1 = TableLevel2[j];

					  if (!TableLevel1)

						  break; //为零则跳出

					  for (i = 0; i < MAX_ENTRY_COUNT; i++)

					  {

						  *Handle = (HANDLE)(k*MAX_ENTRY_COUNT*MAX_ADDR_COUNT + j*MAX_ENTRY_COUNT + i * 4);

						  if (TableLevel1[i].Object && MmIsAddressValid(TableLevel1[i].Object))

						  {

							  //对象有效时,再调用回调函数

							  CallBackRetned = EnumHandleProcedure(&TableLevel1[i], *Handle, EnumParameter);

							  if (CallBackRetned)  break;

						  }

					  }

				  }

			  }

			  ResultValue = TRUE;

	}

		break;

	default:

	{

			   DbgPrint("Shoud NOT get here!\n");

	}

		break;

	}

	return ResultValue;

}

MyDriver1.rar

上传的附件 MyDriver1.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功