日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(65)如何根据句柄从二级、三级结构句柄表中找到内核对象

發布時間:2025/3/21 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (65)如何根据句柄从二级、三级结构句柄表中找到内核对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、回顧

上一篇博客介紹了如何遍歷一級句柄表。一級句柄表非常簡單,就是一個4KB頁,最多存儲512個句柄表項。如果句柄數量在 512 - 1024*512 之間,句柄表就是二級結構;如果句柄數量大于 1024 * 512,就是三級結構。

這篇博客作為上一篇的補充,介紹如何從二級、三級結構句柄表中找到內核對象。

二、ExpLookupHandleTableEntry 函數

實際上這個需求就是 ExpLookupHandleTableEntry 函數做的事情:

PHANDLE_TABLE_ENTRY ExpLookupHandleTableEntry (IN PHANDLE_TABLE HandleTable,IN EXHANDLE Handle)

參數1是句柄表的地址,即 TableCode,注意,這里 TableCode 的低位不能清零,函數里要判斷句柄表結構的。

參數2是句柄值,PID 的值就是一個句柄值,調用 OpenProcess 打開一個進程得到的也是句柄值,前者用來索引全局句柄表,后者用來索引進程的句柄表。

下面給出函數源碼,我給關鍵的代碼添加了注釋,我們要重點研究二級和三級結構的處理方式:

PHANDLE_TABLE_ENTRY ExpLookupHandleTableEntry (IN PHANDLE_TABLE HandleTable,IN EXHANDLE Handle)/*++Routine Description:This routine looks up and returns the table entry for thespecified handle value.Arguments:HandleTable - Supplies the handle table being queriedHandle - Supplies the handle value being queriedReturn Value:Returns a pointer to the corresponding table entry for the inputhandle. Or NULL if the handle value is invalid (i.e., too largefor the tables current allocation.--*/{ULONG_PTR i,j,k;ULONG_PTR CapturedTable;ULONG TableLevel;PHANDLE_TABLE_ENTRY Entry;typedef HANDLE_TABLE_ENTRY *L1P;typedef volatile L1P *L2P;typedef volatile L2P *L3P;L1P TableLevel1;L2P TableLevel2;L3P TableLevel3;ULONG_PTR RemainingIndex;ULONG_PTR MaxHandle;ULONG_PTR Index;PAGED_CODE();//// Extract the handle index//Handle.TagBits = 0; // 低2位清零Index = Handle.Index; // 取31-2位作為句柄表下標MaxHandle = *(volatile ULONG *) &HandleTable->NextHandleNeedingPool;//// See if this can be a valid handle given the table levels.//if (Handle.Value >= MaxHandle) {return NULL; }//// Now fetch the table address and level bits. We must preserve the// ordering here.//CapturedTable = *(volatile ULONG_PTR *) &HandleTable->TableCode;//// we need to capture the current table. This routine is lock free// so another thread may change the table at HandleTable->TableCode//TableLevel = (ULONG)(CapturedTable & LEVEL_CODE_MASK); // LEVEL_CODE_MASK == 3CapturedTable = CapturedTable & ~LEVEL_CODE_MASK;//// The lookup code depends on number of levels we have//switch (TableLevel) {case 0://// We have a simple index into the array, for a single level// handle table//TableLevel1 = (L1P) CapturedTable;Entry = &(TableLevel1[Index]);break;case 1://// we have a 2 level handle table. We need to get the upper index// and lower index into the array//TableLevel2 = (L2P) CapturedTable;// LOWLEVEL_COUNT == 512i = Index / LOWLEVEL_COUNT; // 計算屬于第幾張句柄表j = Index % LOWLEVEL_COUNT; // 計算在句柄表內的偏移Entry = &(TableLevel2[i][j]);break;case 2://// We have here a three level handle table.//TableLevel3 = (L3P) CapturedTable;//// Calculate the 3 indexes we need//// MIDLEVEL_THRESHOLD == 1024 * 512i = Index / (MIDLEVEL_THRESHOLD);RemainingIndex = Index - i * MIDLEVEL_THRESHOLD;j = RemainingIndex / LOWLEVEL_COUNT;k = RemainingIndex % LOWLEVEL_COUNT;Entry = &(TableLevel3[i][j][k]);break;default :_assume (0);}return Entry; }

三、手動從二級句柄表里找內核對象

首先給出測試程序,打開計算器進程 1000 次,這意味著該進程的句柄表是二級結構的,TableCode 低2位是1,TableCode 所在的頁可以存儲1024個4字節地址,每個地址都可以指向一個4KB的句柄表頁。因為我們打開了1000次,所以應該只有前兩個地址是有效的。

int _tmain(int argc, _TCHAR* argv[]) {DWORD PID;HANDLE hPro = NULL;HWND hwnd = FindWindowA(NULL, "計算器");GetWindowThreadProcessId(hwnd, &PID);for (int i = 0; i < 1000; i++){//hPro = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, TRUE, PID);hPro = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, TRUE, PID);printf("句柄:%x\n", hPro);}SetHandleInformation(hPro, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE);getchar();return 0; }

隨便拿一個 fcc,首先要算出它屬于第幾個句柄表, 0xfcc / 0x200 = 7,因為地址是4字節,所以要除以4,意味著要到 TableCode[1] 找;

0xfcc % 0x200 = 0x1cc,所以就是 TableCode[1][0x1cc]。下面來windbg找找看:

現在找到 TableCode:

kd> dt 0xe15bb300 _HANDLE_TABLE ntdll!_HANDLE_TABLE+0x000 TableCode : 0xe2280001+0x004 QuotaProcess : 0x81c01c10 _EPROCESS+0x008 UniqueProcessId : 0x000003dc Void+0x00c HandleTableLock : [4] _EX_PUSH_LOCK+0x01c HandleTableList : _LIST_ENTRY [ 0xe22b5b74 - 0xe23359d4 ]+0x024 HandleContentionEvent : _EX_PUSH_LOCK+0x028 DebugInfo : (null) +0x02c ExtraInfoPages : 0n0+0x030 FirstFree : 0xfdc+0x034 LastFree : 0+0x038 NextHandleNeedingPool : 0x1000+0x03c HandleCount : 0n1013+0x040 Flags : 0+0x040 StrictFIFO : 0y0

dd 一下 0xe2280001:

kd> dd 0xe2280000 e2280000 e2147000 e2281000 00000000 00000000 e2280010 00000000 00000000 00000000 00000000 e2280020 00000000 00000000 00000000 00000000 e2280030 00000000 00000000 00000000 00000000 e2280040 00000000 00000000 00000000 00000000 e2280050 00000000 00000000 00000000 00000000 e2280060 00000000 00000000 00000000 00000000 e2280070 00000000 00000000 00000000 00000000

TableCode[1] 就是 e2281000 ,dq看一下:

kd> dq e2281000 e2281000 fffffffe`00000000 0000003a`81c41543 e2281010 0000003a`81c41543 0000003a`81c41543 e2281020 0000003a`81c41543 0000003a`81c41543 e2281030 0000003a`81c41543 0000003a`81c41543 e2281040 0000003a`81c41543 0000003a`81c41543 e2281050 0000003a`81c41543 0000003a`81c41543 e2281060 0000003a`81c41543 0000003a`81c41543 e2281070 0000003a`81c41543 0000003a`81c41543

找 TableCode[1][0x1cc] :

kd> dq e2281000+1cc*8 e2281e60 0000003a`81c41543 0000003a`81c41543 e2281e70 0000003a`81c41543 0000003a`81c41543 e2281e80 0000003a`81c41543 0000003a`81c41543 e2281e90 0000003a`81c41543 0000003a`81c41543 e2281ea0 0000003a`81c41543 0000003a`81c41543 e2281eb0 0000003a`81c41543 0000003a`81c41543 e2281ec0 0000003a`81c41543 0000003a`81c41543 e2281ed0 0000003a`81c41543 0000003a`81c41543

找到對象頭了,下面看看 EPROCESS,注意低3位清零,還要加上 0x18:

kd> dt _EPROCESS 81c41540+18 ntdll!_EPROCESS+0x000 Pcb : _KPROCESS ...+0x170 Session : 0xf8bc8000 Void+0x174 ImageFileName : [16] "calc.exe"+0x184 JobLinks : _LIST_ENTRY [ 0x0 - 0x0 ] ...

相信看到這,你已經知道怎么通過句柄找內核對象了,如果還是不懂,請留言說出你的問題。

三級結構我就不找了,因為原理差不多,可以照抄 ExpLookupHandleTableEntry 函數。

總結

以上是生活随笔為你收集整理的(65)如何根据句柄从二级、三级结构句柄表中找到内核对象的全部內容,希望文章能夠幫你解決所遇到的問題。

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