刺激战场
六合彩
贵宾厅
  • 1819阅读
  • 1回复

X64下的解析句柄表 [复制链接]

上一主题 下一主题
离线啊冲
 

只看楼主 倒序阅读 使用道具 楼主  发表于: 2016-02-04


一: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(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;
}
善者 慈悲心常在 无怨无恨 以苦为乐
默认压缩密码www.hifyl.com
文件分享密码问题:http://www.hifyl.com/read-htm-tid-4444.html
离线v2680267313

只看该作者 沙发  发表于: 2016-04-30
用户被禁言,该主题自动屏蔽!
快速回复
限100 字节
如果您在写长篇帖子又不马上发表,建议存为草稿
 
上一个 下一个