首页
社区
课程
招聘
[原创]X64下的解析句柄表
发表于: 2014-12-7 17:46 8881

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

2014-12-7 17:46
8881
新人发帖,牛牛们乐呵乐呵就好啦,

关于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

[课程]Linux pwn 探索篇!

上传的附件:
收藏
免费 3
支持
分享
最新回复 (4)
雪    币: 219
活跃值: (738)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
2
为什么没人顶呢
2015-8-22 01:00
0
雪    币: 155
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
Kdversionblock只在startup的那颗cpu的kpcr上才会有。
2015-8-22 10:00
0
雪    币: 19
活跃值: (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
换个系统就不行了。
2015-8-22 13:25
0
雪    币: 22
活跃值: (52)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
受教了,感谢
2015-8-24 20:43
0
游客
登录 | 注册 方可回帖
返回
//