PspCidTable概述

轉自:http://hi.baidu.com/_achillis/blog/item/9857ebec7303404779f05579.html

PspCidTable也是一個句柄表,其格式與普通的句柄表是完全一樣的.但它與每個進程私有的句柄表有以下不同:
1.PspCidTable中存放的對象是系統中所有的進線程對象,其索引就是PID和TID
2.PspCidTable中存放的直接是對象體(EPROCESS和ETHREAD),而每個進程私有的句柄表則存放的是對象頭(OBJECT_HEADER)
3.PspCidTable是一個獨立的句柄表,而每個進程私有的句柄表以一個雙鏈連接起來
lkd> dt nt!_handle_table
...
+0x01c HandleTableList : _LIST_ENTRY
....
注意訪問對象時要掩掉低三位,每個進程私有的句柄表是雙鏈連接起來的,實際上ZwQuerySystemInformation枚舉系統句柄時就是走的這條雙鏈,隱藏進程的話,這條鏈也是要斷掉的~~
PspCidTable相關的調用:
1.系統初始化時調用PspInitPhase0()初始化進程管理子系統,此時創建PspCidTable
  1. PspCidTable = ExCreateHandleTable (NULL);  //創建!
  2.     if (PspCidTable == NULL) {
  3.         return FALSE;
  4.      }
  5.     //
  6.     // Set PID and TID reuse to strict FIFO. This isn't absolutely needed but
  7.     // it makes tracking audits easier.
  8.     //
  9.      ExSetHandleTableStrictFIFO (PspCidTable );
  10.      ExRemoveHandleTable (PspCidTable );  //使得PspCidTable獨立於其它句柄表

2.進程創建時,PspCreateProcess()在PspCidTable中以進程對象創建句柄,是爲PID
//

    // Create the process ID

  1.     //
  2.      CidEntry.Object = Process;
  3.      CidEntry.GrantedAccess = 0;
  4.      Process->UniqueProcessId = ExCreateHandle (PspCidTable , &CidEntry);  //進程的PID是這麼來的
  5.     if (Process->UniqueProcessId == NULL) {
  6.          Status = STATUS_INSUFFICIENT_RESOURCES;
  7.         goto exit_and_deref;
  8.      }

3.線程創建時,PspCreateThread()在PspCidTable中以線程對象創建句柄,是爲TID

  1.      Thread->ThreadsProcess = Process;
  2.      Thread->Cid.UniqueProcess = Process->UniqueProcessId;
  3.      CidEntry.Object = Thread;
  4.      CidEntry.GrantedAccess = 0;
  5.      Thread->Cid.UniqueThread = ExCreateHandle (PspCidTable , &CidEntry); //線程的TID
  6.     if (Thread->Cid.UniqueThread == NULL) {
  7.          ObDereferenceObject (Thread);
  8.         return (STATUS_INSUFFICIENT_RESOURCES);
  9.      }


這兒可以清楚地知道: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中銷燬句柄
  1. if (Thread->Cid.UniqueThread != NULL) {
  2.         if (!ExDestroyHandle (PspCidTable , Thread->Cid.UniqueThread, NULL)) {
  3.              KeBugCheck(CID_HANDLE_DELETION);
  4.          }
  5.      }


6.進程退出時,PspProcessDelete()在PspCidTable中銷燬句柄

  1. if (Process->UniqueProcessId) {
  2.         if (!(ExDestroyHandle (PspCidTable , Process->UniqueProcessId, NULL))) {
  3.              KeBugCheck (CID_HANDLE_DELETION);
  4.          }
  5.      }


這裏要注意,如果進線程退出時,銷燬句柄卻發現句柄不存在造成ExDestroyHandle返回失敗,可是要藍屏滴~
所以抹了PspCidTable來隱藏的進程,在退出時必須把進線程對象再放回去,欲知後事如何,請看下回分解~~

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章