内核PspCidTable句柄表遍历获取隐藏进程

先从WinDBG中来看下PspCidTable.

lkd> dd pspcidtable
84196eb4  8ae011c8 00000000 80000018 00000101
84196ec4  800005e0 80000020 00000000 00000000
84196ed4  00000000 00000000 00000000 00000113
84196ee4  00000000 00000000 841484e4 00000000
84196ef4  00000000 00000000 00000000 00000008
84196f04  00000000 84196f08 84196f08 00000000
84196f14  00000000 00000000 00000000 00000000
84196f24  00000000 8d703d38 807fed38 00000000

8ae011c8 为PspCidTable指向的句柄表的指针.


用WinDBG中看下句柄表_HANDLE_TABLE的内容.

lkd> dt _handle_table 8ae011c8 
nt!_HANDLE_TABLE
   +0x000 TableCode        : 0x9da23001
   +0x004 QuotaProcess     : (null) 
   +0x008 UniqueProcessId  : (null) 
   +0x00c HandleLock       : _EX_PUSH_LOCK
   +0x010 HandleTableList  : _LIST_ENTRY [ 0x8ae011d8 - 0x8ae011d8 ]
   +0x018 HandleContentionEvent : _EX_PUSH_LOCK
   +0x01c DebugInfo        : (null) 
   +0x020 ExtraInfoPages   : 0n0
   +0x024 Flags            : 1
   +0x024 StrictFIFO       : 0y1
   +0x028 FirstFreeHandle  : 0x874
   +0x02c LastFreeHandleEntry : 0x8ae045a0 _HANDLE_TABLE_ENTRY
   +0x030 HandleCount      : 0x3aa
   +0x034 NextHandleNeedingPool : 0x1800
   +0x038 HandleCountHighWatermark : 0x413

TableCode去掉最后2位掩码后就是指向多层表的指针.

lkd> ? 0x9da23001 & FFFFFFFC
Evaluate expression: -1650315264 = 9da23000
lkd> dd 9da23000
9da23000  8ae04000 9da24000 c838f000 00000000
9da23010  00000000 00000000 00000000 00000000
9da23020  00000000 00000000 00000000 00000000
9da23030  00000000 00000000 00000000 00000000
9da23040  00000000 00000000 00000000 00000000
9da23050  00000000 00000000 00000000 00000000
9da23060  00000000 00000000 00000000 00000000
9da23070  00000000 00000000 00000000 00000000
lkd> dd 8ae04000 
8ae04000  00000000 fffffffe 86226021 00000000
8ae04010  86226d49 00000000 86245d49 00000000
8ae04020  86241851 00000000 86245789 00000000
8ae04030  86249c81 00000000 86251639 00000000
8ae04040  86251d49 00000000 86251a71 00000000
8ae04050  86255021 00000000 86255b31 00000000
8ae04060  86255859 00000000 86255581 00000000
8ae04070  8624b021 00000000 8624bd49 00000000

TableCode的后2位指定表的层数,每层表都是由512个_HANDLE_TABLE_ENTRY结构体组成.

lkd> ? 0x9da23001 & 3
Evaluate expression: 1 = 00000001
lkd> dt _HANDLE_TABLE_ENTRY 8ae04000 + 8
nt!_HANDLE_TABLE_ENTRY
   +0x000 Object           : 0x86226021 Void
   +0x000 ObAttributes     : 0x86226021
   +0x000 InfoTable        : 0x86226021 _HANDLE_TABLE_ENTRY_INFO
   +0x000 Value            : 0x86226021
   +0x004 GrantedAccess    : 0
   +0x004 GrantedAccessIndex : 0
   +0x006 CreatorBackTraceIndex : 0
   +0x004 NextFreeTableEntry : 0


_HANDLE_TABLE_ENTRY结构体中的Object去掉最后3位掩码,就是指向EPROCESS结构体的指针.

lkd> ? 0x86226021 &FFFFFFF8
Evaluate expression: -2044567520 = 86226020
lkd> dt _EPROCESS -y Image* -y Flag* 86226020
nt!_EPROCESS
   +0x16c ImageFileName : [15]  "System"
   +0x19c ImagePathHash : 0
   +0x26c Flags2 : 0x202d800
   +0x270 Flags : 0x14040800
   +0x270 ImageNotifyDone : 0y0

如果要获取进程的全路径,可以在下面的偏移处获取.

lkd> dt _EPROCESS -r -y SeA*
nt!_EPROCESS
   +0x1ec SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
lkd> dt _SE_AUDIT_PROCESS_CREATION_INFO -r
nt!_SE_AUDIT_PROCESS_CREATION_INFO
   +0x000 ImageFileName    : Ptr32 _OBJECT_NAME_INFORMATION
      +0x000 Name             : _UNICODE_STRING
         +0x000 Length           : Uint2B
         +0x002 MaximumLength    : Uint2B
         +0x004 Buffer           : Ptr32 Uint2B


来个例子看下,是系统自带的任务管理器进程的EPROCESS:

lkd> dt _SE_AUDIT_PROCESS_CREATION_INFO 8898fd40+1ec -r
nt!_SE_AUDIT_PROCESS_CREATION_INFO
   +0x000 ImageFileName    : 0x88082af0 _OBJECT_NAME_INFORMATION
      +0x000 Name             : _UNICODE_STRING "\Device\HarddiskVolume2\Windows\System32\taskmgr.exe"
         +0x000 Length           : 0x68
         +0x002 MaximumLength    : 0x6a
         +0x004 Buffer           : 0x88082af8  "\Device\HarddiskVolume2\Windows\System32\taskmgr.exe"

最后贴上我写的遍历代码

NTSTATUS CPspCidTable::EnumPspCidTable()
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG ulPspCidTable = 0;
	PHANDLE_TABLE	pHandleTable = NULL;	// 指向句柄表的指针

	ulPspCidTable = GetPspCidTableValue();
	if ( ulPspCidTable == 0 )
	{
		return STATUS_UNSUCCESSFUL;
	}
	pHandleTable = (PHANDLE_TABLE)(*(PULONG)ulPspCidTable);
	KdPrint(( "pHandleTable->%p", pHandleTable ));

	// 获取循环必须的初始值
	ULONG uTableCode = 0;
	ULONG uFlag = 0;

	uTableCode = (pHandleTable->TableCode) & 0xFFFFFFFC;
	uFlag = (pHandleTable->TableCode) & 0x03;
	KdPrint(( "uTableCode->%08X", uTableCode ));

	switch ( uFlag )
	{
	case 0:
		{
			EnumTable1(uTableCode);
			break;
		}
	case 1:
		{
			EnumTable2(uTableCode);
			break;
		}
	case 2:
		{
			EnumTable3(uTableCode);
			break;
		}
	}

	return status;
}

NTSTATUS CPspCidTable::EnumTable1( ULONG uTableCode )
{
	PHANDLE_TABLE_ENTRY pHandleTableEntry = NULL;

	pHandleTableEntry = (PHANDLE_TABLE_ENTRY)( (ULONG)(*(PULONG)uTableCode) + 8 );
	// KdPrint(( "pHandleTableEntry->%p", pHandleTableEntry ));

	// 循环遍历句柄表,循环必须从1开始,跳过第一个HANDLE_TABLE_ENTRY
	for ( ULONG uIndex = 1; uIndex < 0x200; uIndex++ )
	{
		//pHandleTableEntry += uIndex;
		if ( pHandleTableEntry->Object != NULL )
		{
			PEPROCESS pCurEProcess = (PEPROCESS)(((ULONG)pHandleTableEntry->Object)  & 0xFFFFFFF8);
			//KdPrint(( "pCurEProcess->%p", pCurEProcess ));

			// 判断进程是否结束的标记
			ULONG flag = (*(PULONG)( (PUCHAR)pCurEProcess + 0x270 ) ) & 0x0C;
			// KdPrint(( "flag=%08X", flag ));

			// 打印活动进程
			if ( *(PUCHAR)(pCurEProcess) == 0x03 && flag != 0x0C )
			{
				// +0x16c ImageFileName    : [15] UChar		进程映像名称,只有15个字节,如果进程名称太长,则被截断.
				// +0x1ec SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO 这个结构体中包含进程路径字符串
				KdPrint(( "pCurEProcess->%p----%s", pCurEProcess, (PUCHAR)pCurEProcess + 0x16C) );
			}
		}

		pHandleTableEntry++;
		//KdPrint(( "pHandleTableEntry->%p", pHandleTableEntry ));
	}
	return STATUS_SUCCESS;
}
NTSTATUS CPspCidTable::EnumTable2( ULONG uTableCode )
{
	do 
	{
		// KdPrint(( "uTableCode->%08X", uTableCode ));
		EnumTable1(uTableCode);
		uTableCode += 4;
	} while ( *(PULONG)uTableCode != 0 );

	return STATUS_SUCCESS;
}
NTSTATUS CPspCidTable::EnumTable3( ULONG uTableCode )
{
	do 
	{
		EnumTable2(uTableCode);
		uTableCode += 4;
	} while ( *(PULONG)uTableCode != 0 );

	return STATUS_SUCCESS;
}

ULONG CPspCidTable::GetPspCidTableValue()
{
	PVOID pPsLookupProcessByProcessIdAddress = NULL;
	ULONG ulPspCidTableValue = 0;
	UNICODE_STRING ustrFuncName;

	// 获取PsLookupProcessByProcessId的函数地址
	RtlInitUnicodeString( &ustrFuncName, L"PsLookupProcessByProcessId" );
	pPsLookupProcessByProcessIdAddress = MmGetSystemRoutineAddress( &ustrFuncName );
	if ( pPsLookupProcessByProcessIdAddress == NULL )
	{
		return ulPspCidTableValue;
	}
	KdPrint(( "PsLookupProcessByProcessId->%08X", pPsLookupProcessByProcessIdAddress ));

	// 根据特征定位PspCidTable的值.
	// Win7系统的定位代码如下:
	// 842b5827 8b3db45e1884    mov     edi,dword ptr [nt!PspCidTable (84185eb4)]
	// 842b582d e8f96efdff			call		nt!ExMapHandleToPointer (8428c72b)
	for ( ULONG uIndex = 0; uIndex < 0x1000; uIndex++ )
	{
		if ( *( (PUCHAR)((ULONG)pPsLookupProcessByProcessIdAddress+ uIndex) ) == 0x8B &&
			*( (PUCHAR)((ULONG)pPsLookupProcessByProcessIdAddress+ uIndex + 1) ) == 0x3D &&
			*( (PUCHAR)((ULONG)pPsLookupProcessByProcessIdAddress+ uIndex + 6) ) == 0xE8 )
		{
			KdPrint(("Found OK!!"));
			ulPspCidTableValue = *( (PULONG)((ULONG)pPsLookupProcessByProcessIdAddress+ uIndex + 2) );
			break;
		}
	}

	return ulPspCidTableValue;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值