天天看點

x64通過PspCidTable周遊程序

PspCidTable可以在PsLookupProcessByProcessId下尋找

我這寫死了 隻适用于win7 x64 其它版本需要自己改下特征碼

#include <ntddk.h>


extern "C" NTKERNELAPI PVOID NTAPI  
ObGetObjectType(  
      IN PVOID pObject  
      ); 

extern "C" NTKERNELAPI UCHAR* 
PsGetProcessImageFileName(
	  IN PEPROCESS Process
	  );

#define   MAX_ENTRY_COUNT (0x1000/16)  //一級表中的 HANDLE_TABLE_ENTRY個數
#define   MAX_ADDR_COUNT   (0x1000/8) //二級表和 三級表中的位址個數

ULONG g_ProcessCount = 0;

typedef struct _EX_PUSH_LOCK                 // 7 elements, 0x8 bytes (sizeof) 
{                                                                              
              union                                    // 3 elements, 0x8 bytes (sizeof) 
              {                                                                          
                  struct                               // 5 elements, 0x8 bytes (sizeof) 
                  {                                                                      
/*0x000*/             UINT64       Locked : 1;         // 0 BitPosition                  
/*0x000*/             UINT64       Waiting : 1;        // 1 BitPosition                  
/*0x000*/             UINT64       Waking : 1;         // 2 BitPosition                  
/*0x000*/             UINT64       MultipleShared : 1; // 3 BitPosition                  
/*0x000*/             UINT64       Shared : 60;        // 4 BitPosition                  
                  };                                                                     
/*0x000*/         UINT64       Value;                                                    
/*0x000*/         VOID*        Ptr;                                                      
              };                                                                         
}EX_PUSH_LOCK, *PEX_PUSH_LOCK;                                                 
                
typedef struct _HANDLE_TRACE_DB_ENTRY // 4 elements, 0xA0 bytes (sizeof) 
          {                                                                        
/*0x000*/     struct _CLIENT_ID ClientId;       // 2 elements, 0x10 bytes (sizeof) 
/*0x010*/     VOID*        Handle;                                                 
/*0x018*/     ULONG32      Type;                                                   
/*0x01C*/     UINT8        _PADDING0_[0x4];                                        
/*0x020*/     VOID*        StackTrace[16];                                         
}HANDLE_TRACE_DB_ENTRY, *PHANDLE_TRACE_DB_ENTRY;                                   
                                                                                   


typedef struct _HANDLE_TRACE_DEBUG_INFO       // 6 elements, 0xF0 bytes (sizeof) 
{                                                                                
/*0x000*/     LONG32       RefCount;                                                       
/*0x004*/     ULONG32      TableSize;                                                      
/*0x008*/     ULONG32      BitMaskFlags;                                                   
/*0x00C*/     UINT8        _PADDING0_[0x4];                                                
/*0x010*/     struct _FAST_MUTEX CloseCompactionLock;   // 5 elements, 0x38 bytes (sizeof) 
/*0x048*/     ULONG32      CurrentStackIndex;                                              
/*0x04C*/     UINT8        _PADDING1_[0x4];                                                
/*0x050*/     struct _HANDLE_TRACE_DB_ENTRY TraceDb[];                                    
}HANDLE_TRACE_DEBUG_INFO, *PHANDLE_TRACE_DEBUG_INFO;                                   
                                                                                           

typedef struct _HANDLE_TABLE_ENTRY                  // 8 elements, 0x10 bytes (sizeof) 
{                                                                                      
              union                                           // 4 elements, 0x8 bytes (sizeof)  
              {                                                                                  
/*0x000*/         VOID*        Object;                                                           
/*0x000*/         ULONG32      ObAttributes;                                                     
/*0x000*/         struct _HANDLE_TABLE_ENTRY_INFO* InfoTable;                                    
/*0x000*/         UINT64       Value;                                                            
              };                                                                                 
              union                                           // 3 elements, 0x8 bytes (sizeof)  
              {                                                                                  
/*0x008*/         ULONG32      GrantedAccess;                                                    
                  struct                                      // 2 elements, 0x8 bytes (sizeof)  
                  {                                                                              
/*0x008*/             UINT16       GrantedAccessIndex;                                           
/*0x00A*/             UINT16       CreatorBackTraceIndex;                                        
/*0x00C*/             UINT8        _PADDING0_[0x4];                                              
                  };                                                                             
/*0x008*/         ULONG32      NextFreeTableEntry;                                               
              };                                                                                 
}HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;                                             
                                                                                                 


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;


typedef BOOLEAN (*MY_ENUMERATE_HANDLE_ROUTINE)(
	IN PHANDLE_TABLE_ENTRY HandleTableEntry,
	IN HANDLE Handle,
	IN PVOID EnumParameter);

SIZE_T FindCidTable()
{
	SIZE_T  CidTableAddr = 0;
	UNICODE_STRING ustPsFuncName;
	RtlInitUnicodeString(&ustPsFuncName, L"PsLookupProcessByProcessId");
	PUCHAR startAddr = (PUCHAR)MmGetSystemRoutineAddress(&ustPsFuncName);
 
	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;
}


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 = (POBJECT_TYPE)ObGetObjectType(Object);
	if (MmIsAddressValid(HandleTableEntry))
	{
		if (ObjectType == *PsProcessType)//判斷是否為Process
		{
			//注意PID其實就是Handle,而 不是從EPROCESS中取,可以對付僞pid
			g_ProcessCount++;
			DbgPrint("PID=%4d\t EPROCESS=0x%p %s\n", Handle, ProcessObject, PsGetProcessImageFileName((PEPROCESS)ProcessObject));
		}
	}
	return Result;//傳回FALSE繼續
}
 
 
//自己實作一個山寨的MyEnumHandleTable,接口和ExEnumHandleTable一樣
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("BOOM!\n");
		}
		break;
	}
	DbgPrint("ProcessCount:0x%x",g_ProcessCount);
	return ResultValue;
}


void EnumProcessByPspCidTable()
{
	PHANDLE_TABLE pHandleTable = NULL;
	pHandleTable =(PHANDLE_TABLE)*(PSIZE_T)FindCidTable();
	HANDLE hHanel;
	UNICODE_STRING usObGetObjectType;
	DbgPrint("pHandleTable:%p\n", pHandleTable);
	MyEnumHandleTable(pHandleTable, MyEnumerateHandleRoutine, NULL, &hHanel);
}

void DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	UNREFERENCED_PARAMETER(pDriverObject);
	DbgPrint("GoodBye!\n");
}

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegPath)
{
	UNREFERENCED_PARAMETER(pRegPath);
	
	pDriverObject->DriverUnload = DriverUnload;

	DbgPrint("DriverEntry!\n");

	EnumProcessByPspCidTable();

	return STATUS_SUCCESS;
}