日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

私有句柄表(内核对象,并非用户对象),全局句柄表

發布時間:2025/3/21 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 私有句柄表(内核对象,并非用户对象),全局句柄表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 私有句柄表
    • 1.什么是句柄(內核對象)
    • 2.為什么要有句柄?
    • Windows設計理念:
    • 3.句柄表在哪?
  • 全局句柄表
  • 注意

私有句柄表

1.什么是句柄(內核對象)

當一個進程創建或者打開一個內核對象時,將獲得一個句柄,通過這個句柄可以訪問內核對象
(注意:這里所說的句柄往往對應一個內核對象,調用窗口相關的函數時,也會得到所謂的句柄,但是那種句柄和這里所說的句柄是兩回事,這里所說的句柄一定對應一個內核對象,而且這個內核對象其實也就是一個結構體,在0環才能夠進行讀寫的。并非普通窗口,筆刷,字體等對象的句柄,這種對象我們通常稱為用戶對象,并非內核對象)
如:
HANDLE g_hMutex=::CreateMutex(NULL,FALSE,“XYZ”)
HANDLE g_hMutex=::OpenMutex(MUTEX_ALL_ACCESS,FALSE,“XYZ”)
HANDLE g_hEvent=::CreateEvent(NULL,TRUE,FALSE,NULL)
HANDLE g_hThread=::CreateThread(NULL,0,NULL,0,NULL)

2.為什么要有句柄?

句柄存在的目的是為了避免在應用層直接修改內核對象
HANDLE g_hEvent=::CreateEvent(NULL,TRUE,FALSE,NULL)
如果g_hEvent存儲的就是EVENT內核對象的地址,那么就意味著我們可以在應用層修改這個地址,一旦指向了無效的內核內存地址就會藍屏

如果我們在3環訪問一個無效地址,那么最多也就是程序退出。

Windows設計理念:

1.隱藏內核對象指針
2.句柄就是個索引
(每個進程都有一個的表,用來存放進程創建或者打開(Open并不會創建新的內核對象,而是直接返回這個內核對象的地址,然后在表中創建一個索引值)的內核對象的句柄值,)
然后把這個在0環創建的句柄表中的索引值,返回給3環去使用。

3.句柄表在哪?

dt _EPROCESS
+0x0c4 ObjectTable :_HANDLE_TABLE

dt _HANDLE_TABLE
+0x000 TableCode (句柄表地址)
+0x004 QuotaProcess
+0x008 UniqueProcessId
+0x00c HandleTableLock
+0x01c HandleTableList

實際測試:

運行結果

找到當前進程EPROCESS中的_HANDLE_TABLE

然后查看TableCode

684是個索引,需要用684/4=1A1(因為是以4為單位的(為了這個函數保證在其它情況下能用)),但句柄表里的句柄成員每個是8字節,

算法也就是 0xe1cf6000+1A1*8

如下圖,轉換為8個字節為一組的句柄表值

(因為是使用打開的方式并非使用創建的方式,所以內核對象都是同一個,所以地址都一樣)
下面接下來解釋一下,3環的函數對句柄表中表項的操作

(1)這一塊共兩個字節,低字節保留位恒為0,高字節是給SetHandleInformation這個函數用的,比如寫成函數SetHandleInformation(Handle,HANDLE_FLAG_PROTECT_FROM_CLOSE,HANDLE_FLAG_PROTECT_FROM_CLOSE),那么這個位置將會被寫入0x02;
HANDLE_FLAG_PROTECT_FROM_CLOSE宏的值為0x00000002,取最低字節,最終(1)這塊是0x0200

(2)這塊是訪問掩碼,是給OpenProcess這個函數用的
OpenProcess(dwDesiredAccess,BInheritHandle,dwProcessId);具體的存的就是這個函數的第一個參數的值

(3)和(4)這兩塊共計四個字節,其中bit0-bit2存的是這個句柄的屬性,其中bit2 bit0 默認為0,1;bit1表示的函數是該句柄是否可繼承;OpenProcess的第二個參數與bit1有關;
bit31-bit3則是存放的該內核對象在內核中的具體的地址

真正的內核對象都是以OBJECT_HEADER開頭的,也就是說,以前我們所看到的EPROCESS,ETHREAD都不是完整的內核對象,而是需要再加0x18的OBJECT_HEADER的頭

句柄表中指向的內核進程對象(即EPROCESS)的值,把低三位清掉,即0x86050d48,這個地址指向的是有0x18的OBJECT_HEADER頭的EPROCESS內核對象。因為程序中是OpenProcess,所以是EPROCESS內核對象

0x174偏移是進程名,毫無疑問,正確

提示:利用句柄表可以做出反調試,掃描全部進程的句柄表,觀察句柄表中是否有指向此進程的EPROCESS內核對象的地址,有的話那就說明此進程被打開(正在被調試。。)

全局句柄表

1.所有的進程和線程無論是否打開,都在這個表中。
2.每個進程和線程都有一個唯一的編號:PID和CID,這兩個值其實就是全局句柄表中的索引,

進程和線程得到查詢,主要是以下三個函數,按照給定的PID和CID從PspCidTable從查找響應的進線程對象:

PsLookupProcessThreadByCid()
PsLookupProcessProcessId()
PsLookupThreadByThreadId()

句柄表結構

如果為1級句柄表的話,那么TableCode低2位為0((4KB)個數最多512個)

如果為2級句柄表的話,那么TableCode低2位為1(第一級存儲的都是一個地址,也就是第一級可以存儲1024個地址,第二級存儲真正句柄信息,也就是可以存1024X512個)

如果為3級句柄表的話,那么TableCode低2位為2(第一級存儲的都是一個地址,第二級存儲的都是一個地址,第三級存儲真正句柄信息,句柄數量也就是1024X1024X512個)

首先通過全局變量PspCidTable查找全局句柄表

然后通過_HANDLE_TABLE查看

找到了TableCode后直接進入

然后假如PID是1044
那么1044/4=261,索引也就是261,轉換成16進制后是0x105
然后0x105乘以8


值為0x86201781,去掉低3位為0x86201780,它直接指向了EPROCESS,沒有OBJECT_HEADER頭結構

注意

全局句柄表和私有句柄表有差異,私有句柄表中指向的是帶有OBJECT_HEADER頭的內核對象,但是全局句柄表中指向的并沒有帶OBJECT_HEADER頭

總結

以上是生活随笔為你收集整理的私有句柄表(内核对象,并非用户对象),全局句柄表的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。