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;
}