驅動開發:內核枚舉PspCidTable句柄表

在上一篇文章《驅動開發:內核枚舉DpcTimer定時器》中我們通過枚舉特征碼的方式找到了DPC定時器基址并輸出了內核中存在的定時器列表,本章將學習如何通過特征碼定位的方式尋找Windows 10系統下面的PspCidTable內核句柄表地址 。
首先引入一段基礎概念;

  • 1.在windows下所有的資源都是用對象的方式進行管理的(文件、進程、設備等都是對象) , 當要訪問一個對象時,如打開一個文件,系統就會創建一個對象句柄,通過這個句柄可以對這個文件進行各種操作 。
  • 2.句柄和對象的聯系是通過句柄表來進行的 , 準確來說一個句柄就是它所對應的對象在句柄表中的索引 。
  • 3.通過句柄可以在句柄表中找到對象的指針,通過指針就可以對 , 對象進行操作 。
PspCidTable 就是這樣的一種表(內核句柄表),表的內部存放的是進程EPROCESS和線程ETHREAD的內核對象,并通過進程PID和線程TID進行索引 , ID號以4遞增,內核句柄表不屬于任何進程,也不連接在系統的句柄表上 , 通過它可以返回系統的任何對象 。
內核句柄表與普通句柄表完全一樣,但它與每個進程私有的句柄表有以下不同;
  • 1.PspCidTable 中存放的對象是系統中所有的進程線程對象,其索引就是PID和TID 。
  • 2.PspCidTable 中存放的直接是對象體EPROCESS和ETHREAD , 而每個進程私有的句柄表則存放的是對象頭OBJECT_HEADER 。
  • 3.PspCidTable 是一個獨立的句柄表,而每個進程私有的句柄表以一個雙鏈連接起來 。
  • 4.PspCidTable 訪問對象時要掩掉低三位,每個進程私有的句柄表是雙鏈連接起來的 。
那么在Windows10系統中該如何枚舉句柄表;
  • 1.首先找到PsLookupProcessByProcessId函數地址,該函數是被導出的可以動態拿到 。
  • 2.其次在PsLookupProcessByProcessId地址中搜索PspReferenceCidTableEntry函數 。
  • 3.最后在PspReferenceCidTableEntry地址中找到PspCidTable函數 。
首先第一步先要得到PspCidTable函數內存地址,輸入dp PspCidTable即可得到 , 如果在程序中則是調用MmGetSystemRoutineAddress取到 。
驅動開發:內核枚舉PspCidTable句柄表

文章插圖
PspCidTable是一個HANDLE_TALBE結構,當新建一個進程時,對應的會在PspCidTable存在一個該進程和線程對應的HANDLE_TABLE_ENTRY項 。在windows10中依然采用動態擴展的方法,當句柄數少的時候就采用下層表,多的時候才啟用中層表或上層表 。
接著我們解析ffffdc88-79605dc0這個內存地址 , 執行dt _HANDLE_TABLE 0xffffdc8879605dc0得到規范化結構體 。
驅動開發:內核枚舉PspCidTable句柄表

文章插圖
內核句柄表分為三層如下;
  • 下層表:是一個HANDLE_TABLE_ENTRY項的索引,整個表共有256個元素 , 每個元素是一個8個字節長的HANDLE_TABLE_ENTRY項及索引,HANDLE_TABLE_ENTRY項中保存著指向對象的指針,下層表可以看成是進程和線程的稠密索引 。
  • 中層表:共有256個元素,每個元素是4個字節長的指向下層表的入口指針及索引,中層表可以看成是進程和線程的稀疏索引 。
  • 上層表:共有256個元素 , 每個元素是4個字節長的指向中層表的入口指針及索引 , 上層表可以看成是中層表的稀疏索引 。
總結起來一個句柄表有一個上層表 , 一個上層表最多可以有256個中層表的入口指針,每個中層表最多可以有256個下層表的入口指針,每個下層表最多可以有256個進程和線程對象的指針 。PspCidTable表可以看成是HANDLE_TBALE_ENTRY項的多級索引 。
如上圖所示TableCode是指向句柄表的指針,低二位(二進制)記錄句柄表的等級:0(00)表示一級表 , 1(01)表示二級表,2(10)表示三級表 。這里的 0xffffdc88-7d09b001 就說名它是一個二級表 。
驅動開發:內核枚舉PspCidTable句柄表

文章插圖
一級表里存放的就是進程和線程對象(加密過的,需要一些計算來解密),二級表里存放的是指向某個一級表的指針 , 同理三級表存放的是指向二級表的指針 。
x64 系統中,每張表的大小是 0x1000(4096),一級表中存放的是 _handle_table_entry 結構(大小 = 16),二級表和三級表存放的是指針(大小 = 8) 。

推薦閱讀