我是靠谱客的博主 清脆鸡翅,最近开发中收集的这篇文章主要介绍X64下的解析句柄表,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一:X64下的句柄表的查找:

关于PspCidTable的寻找,我是通过PsLookupProcessByProcessId查找特征码寻找pspCidTable32位没什么区别。

疑问:我想在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%02Xn", *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:%pn"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:%pn"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:%pn"g_pObGetObjectType);

MyEnumHandleTable(pHandleTableMyEnumerateHandleRoutineNULL, &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

UCHARszName = PsGetProcessImageFileName((PEPROCESS)ProcessObject);

stcProcessInfo[nProcessCount].hProcessID = Handle;

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

nProcessCount++;

DbgPrint("PID=%4dt EPROCESS=0x%p %sn"HandleProcessObjectPsGetProcessImageFileName((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 ijk;

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%Xn"MaxHandle);

//判断表的等级

switch (TableLevel)

{

case 0:

{

  //一级表

  TableLevel1 = (PHANDLE_TABLE_ENTRY)CapturedTable;

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

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

  {

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

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

  {

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

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

  if (CallBackRetned)  break;

  }

  }

  ResultValue = TRUE;

 

}

break;

case 1:

{

  //二级表

  TableLevel2 = (PHANDLE_TABLE_ENTRY*)CapturedTable;

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

  DbgPrint("二级表的个 数:%dn"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_COUNTi++)

  {

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

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

  {

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

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

  if (CallBackRetned)  break;

  }

  }

  }

  ResultValue = TRUE;

}

break;

case 2:

{

  //三级表

  TableLevel3 = (PHANDLE_TABLE_ENTRY**)CapturedTable;

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

  DbgPrint("三级表的个 数:%dn"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_COUNTi++)

  {

  *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], *HandleEnumParameter);

  if (CallBackRetned)  break;

  }

  }

  }

  }

  ResultValue = TRUE;

}

break;

default:

{

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

}

break;

}

return ResultValue;

}

 

 

最后

以上就是清脆鸡翅为你收集整理的X64下的解析句柄表的全部内容,希望文章能够帮你解决X64下的解析句柄表所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部