【舊文章搬運】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來隱藏的程序,在退出時必須把進執行緒物件再放回去,欲知後事如何,請看下回分解~~