1. 程式人生 > >【舊文章搬運】PspCidTable概述

【舊文章搬運】PspCidTable概述

原文發表於百度空間,2009-03-28
==========================================================================

PspCidTable也是一個控制代碼表,其格式與普通的控制代碼表是完全一樣的.但它與每個程序私有的控制代碼表有以下不同:
1.PspCidTable中存放的物件是系統中所有的進執行緒物件,其索引就是PID和TID
2.PspCidTable中存放的直接是物件體(EPROCESS和ETHREAD),而每個程序私有的控制代碼表則存放的是物件頭(OBJECT_HEADER)
3.PspCidTable是一個獨立的控制代碼表,而每個程序私有的控制代碼表以一個雙鏈連線起來
注意訪問物件時要掩掉低三位,每個程序私有的控制代碼表是雙鏈連線起來的,實際上ZwQuerySystemInformation列舉系統控制代碼時就是走的這條雙鏈,隱藏程序的話,這條鏈也是要斷掉的~~
PspCidTable相關的呼叫:
1.系統初始化時呼叫PspInitPhase0()初始化程序管理子系統,此時建立PspCidTable

PspCidTable = ExCreateHandleTable (NULL);  //建立!
    if (PspCidTable == NULL) {
        return FALSE;
     }
    //
    // Set PID and TID reuse to strict FIFO. This isn't absolutely needed but
    // it makes tracking audits easier.
    //
     ExSetHandleTableStrictFIFO (PspCidTable);
     ExRemoveHandleTable (PspCidTable);  
//使得PspCidTable獨立於其它控制代碼表

2.程序建立時,PspCreateProcess()在PspCidTable中以程序物件建立控制代碼,是為PID

    //
    // Create the process ID
    //
     CidEntry.Object = Process;
     CidEntry.GrantedAccess = 0;
     Process->UniqueProcessId = ExCreateHandle (PspCidTable, &CidEntry);  //程序的PID是這麼來的
    if (Process->UniqueProcessId == NULL) {
         Status 
= STATUS_INSUFFICIENT_RESOURCES; goto exit_and_deref; }

3.執行緒建立時,PspCreateThread()在PspCidTable中以執行緒物件建立控制代碼,是為TID

     Thread->ThreadsProcess = Process;
     Thread->Cid.UniqueProcess = Process->UniqueProcessId;
     CidEntry.Object = Thread;
     CidEntry.GrantedAccess = 0;
     Thread->Cid.UniqueThread = ExCreateHandle (PspCidTable, &CidEntry); //執行緒的TID
    if (Thread->Cid.UniqueThread == NULL) {
         ObDereferenceObject (Thread);
        return (STATUS_INSUFFICIENT_RESOURCES);
     }

 

這兒可以清楚地知道:PID和TID分別是EPROCESS和ETHREAD物件在PspCidTable這個控制代碼表中的索引
4.程序和執行緒的查詢,主要是以下三個函式,按照給定的PID或TID從PspCidTable從查詢相應的進執行緒物件
PsLookupProcessThreadByCid()
PsLookupProcessByProcessId()
PsLookupThreadByThreadId()
其中有如下呼叫:
CidEntry = ExMapHandleToPointer(PspCidTable, ProcessId);
CidEntry = ExMapHandleToPointer(PspCidTable, ThreadId);

ExMapHandleToPointer內部仍然是呼叫ExpLookupHandleTableEntry()根據指定的控制代碼查詢相應的HANDLE_TABEL_ENTRY,
從而獲取Object
5.執行緒退出時,PspThreadDelete()在PspCidTable中銷燬控制代碼

if (Thread->Cid.UniqueThread != NULL) {
        if (!ExDestroyHandle (PspCidTable, Thread->Cid.UniqueThread, NULL)) {
             KeBugCheck(CID_HANDLE_DELETION);
         }
     }

 

6.程序退出時,PspProcessDelete()在PspCidTable中銷燬控制代碼

if (Process->UniqueProcessId) {
        if (!(ExDestroyHandle (PspCidTable, Process->UniqueProcessId, NULL))) {
             KeBugCheck (CID_HANDLE_DELETION);
         }
     }

這裡要注意,如果進執行緒退出時,銷燬控制代碼卻發現控制代碼不存在造成ExDestroyHandle返回失敗,可是要藍屏滴~

所以抹了PspCidTable來隱藏的程序,在退出時必須把進執行緒物件再放回去,欲知後事如何,請看下回分解~~