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%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
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
详细目录如下: 0.基础的基础 |-学习WIN64驱动开发的硬件准备 |-配置驱动开发环境 ------------------------------ 1.驱动级HelloWorld |-配置驱动测试环境 |-编译和加载内核HelloWorld ------------------------------ 2.内核编程基础 |-WIN64内核编程的基本规则 |-驱动程序与应用程序通信 |-内核里使用内存 |-内核里操作字符串 |-内核里操作文件 |-内核里操作注册 |-内核里操作进线程 |-驱动里的其它常用代码 ------------------------------ 3.内核HOOK与UNHOOK |-系统调用、WOW64与兼容模式 |-编程实现突破WIN7的PatchGuard |-系统服务描述结构详解 |-SSDT HOOK和UNHOOK |-SHADOW SSDT HOOK和UNHOOK |-INLINE HOOK和UNHOOK ------------------------------ 4.无HOOK监控技术 |-无HOOK监控进线程启动和退出 |-无HOOK监控模块加载 |-无HOOK监控注册操作 |-无HOOK监控文件操作 |-无HOOK监控进线程句柄操作 |-使用对象回调监视文件访问 |-无HOOK监控网络访问 |-无HOOK监视修改时间 ------------------------------ 5.零散内容 |-驱动里实现内嵌汇编 |-DKOM隐藏进程+保护进程 |-枚举和隐藏内核模块 |-强制结束进程 |-强制读写进程内存 |-枚举消息钩子 |-强制解锁文件 |-初步探索PE32+格式文件 ------------------------------ 6.用户态HOOK与UNHOOK |-RING3注射DLL到系统进程 |-RING3的INLINE HOOK和UNHOOK |-RING3的EAT HOOK和IAT HOOK ------------------------------ 7.反回调 |-枚举与删除创建进线程回调 |-枚举与删除加载映像回调 |-枚举与删除注册回调 |-枚举与对抗MiniFilter |-枚举与删除对象回调

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值