標籤:結果 根據 img details window event tag 編程 handle
本文藉助windbg來理解程式中的函數如何使用handle對控制代碼表進行查詢的。所以先要開啟Win7下Windbg的內和調試功能。
win7下debug預設無法進行核心調試(!process等命令無法使用),除非是雙機調試。或改用livekd進行調試。嘗試http://blog.csdn.net/hutao1101175783/article/details/50522767中提出的方法,開啟windbg的內和調試功能:
重啟之後開啟Local Kernel Debugging:
開啟成功:
載入符號表之後,就可以使用!process命令了:
添加源檔案路徑:
開啟源碼層級的調試:
給TestHandle.exe的main函數下斷點:運行後自動彈出源碼調試:
再開一個windbg用核心調試。!process 0 0 命令找到TestHandle.exe的資訊:
查看這個進程的所有控制代碼資訊(同時也顯示出了OBJECT的資訊,來給我們提供驗證):
下面,藉助對TestHandle.exe的調試我們知道38號控制代碼是hEvent:
查看0x38號控制代碼的資訊(這個資訊被我當做“結果”來驗證我的“推理”過程):
查看TestHandle的EProcess結構:
得到TableCode,這個值指向一級、二級或三級控制代碼表(具體是幾級控制代碼表由末尾數決定):
根據低兩位判斷控制代碼表的層級。TableCode低位是1,說明是一個二級控制代碼表(可以參考這個文章的分析:https://www.cnblogs.com/lsh123/p/7296423.html):
這裡顯示了兩個一級控制代碼表。不同層級的控制代碼表可以參考文章:https://www.2cto.com/kf/201609/543902.html和圖:
那麼控制代碼值乘以4再加上fffff8a0`19ca8000就是指向對應的handle_table_entry://為什麼這裡要乘以4?控制代碼是0x38,索引就是0x38/4,又由於每個handle_table_entry的大小是16位元組。那麼為什麼索引是0x38/4?後面會回答
找到對應的handle_table_entry:
其中fffffa80`11399951 就是Object指標,位移0x30-1就可以定位到OBJECT:
因為是在64位系統下,所以位移是0x30-1,位移發生了變化(32位系統下就是0x17):
這樣就通過控制代碼取到了核心對象,整個流程思路參考了:http://www.cppblog.com/sleepwom/archive/2011/10/19/72591.html並參考了圖片:
在WinNT.h中定義的handle是這樣的:typedef void* handle;
而DECLARE_HANDLE(HWND);就是: struct HWND__ { int unused;}; typedef struct HWND__ *HWND;所以DECLARE_HANDLE的作用就是將name定義為一個指向結構體的指標。handle是一個無類型指標,而HWND是一個指向結構體的指標。Handle是一個void儲存著一個整形資料類型作為“虛擬索引”。參考:https://www.cnblogs.com/zpcdbky/p/4656449.htmlhttp://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380143fd3d1027fa3c215cc79051a0071e4cf6678475886d27b135bfc1541baae6b272a4266e4dd93d957deb0902f248b2631701c844213d719a9c84524c627935ee3aa04f3ffad72c5a1888083020d9d44050bc2b4d60156&p=c449ca5f86cc41ac52a5d02d021494&newp=81798f16d9c111a058ee9e124f43c9231610db2151d4d2116b82c825d7331b001c3bbfb423251007d7c07d6304aa4858eff6357033092ba3dda5c91d9fb4c57479&user=baidu&fm=sc&query=handle+pvoid&qid=b9f8680100001e9b&p1=5
如果要根據控制代碼尋找相應的handle_table_entry,就會調用這個函數:ExMapHandleToPointer ( __in PHANDLE_TABLE HandleTable, __in HANDLE Handle )
這裡的handle就是我們本例中傳入的0x38。ExMapHandleToPointer 中又會調用ExpLookupHandleTableEntry。在使用控制代碼去尋找進程的控制代碼表時會調用函數ExpLookupHandleTableEntry,其原型如下:
參數 HandleTable 是尋找目標所在的 Handle table 地址,而 tHandle 是結構化的 Handle 值。參考:http://www.mamicode.com/info-detail-1539980.htmlhandle與exhandle的關係如下:這個 tHandle 結構將 Handle 值分為幾個部分,如所示:
這個 TagBit 值佔兩位(bit 0 到 bit 1),被清為 0 值。因此:tHandle.Value 值就是對齊在 4 bytes 邊界上。(出於某種原因)使用高30位作為索引來尋找控制代碼表,低兩位的存在沒有意義。參考:https://www.cnblogs.com/ck1020/p/5897460.html
現在低兩位沒有意義不代表將來低兩位沒有意義,handle的含義和使用可能在未來發生變化。
《Windows核心編程》第3章——深入理解handle