X64下的解析句柄表

来源:互联网 发布:linux修改文件名 编辑:程序博客网 时间:2024/06/04 18:27

一: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%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(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=%4d\t EPROCESS=0x%p %s\n"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%X\n"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("二级表的个 数:%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_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("三级表的个 数:%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_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;

}

 

 

1 0