句柄表(私有句柄表)

 Windows內核分析索引目錄:https://www.cnblogs.com/onetrainee/p/11675224.htmlhtml

句柄表(私有句柄表)編程

  咱們在R3環編程中,會接觸到句柄HANDLE的概念。app

  好比OPENPROCESS,打開進程獲取其進程句柄,這些被稱爲「內核句柄」。ide

  注意,與GUI圖形界面不一樣,那些 畫刷句柄 被稱爲「用戶句柄」,不在咱們討論範圍之列。
spa

 

1、 句柄表的基本概念線程

  句柄表分爲私有私有句柄表和全局句柄表,咱們這一節只討論私有句柄表。指針

  每個進程都有本身的私有句柄表,在一個進程中使用OpenProcess打開另外一個進程時,則會將被打開進程在內核對象的 _EPROCESS 結構體完整的映射到打開進程的私有句柄表中。
code

  注意:是映射,不是建立,被打開進程的_EPROCESS在建立時就已經存儲到全局句柄表中了,其餘進程打開時直接從這裏映射一份便可。orm

 

2、句柄表有關的結構htm

1. 獲取_HANDLE_TABLE結構體

  私有句柄表存儲在_EPROCESS+0x0c4 這個位置,其指針指向一個 _HANDLE_TABLE結構體
    

2. _HANDLE_TABLE 結構體

  咱們使用 dt _HANDLE_TABLE 0xe26cc488,該結構的第一個成員 TableCode就是句柄表存儲的位置。

   kd> dt  0xe26cc488 _HANDLE_TABLE
    ntdll!_HANDLE_TABLE
       +0x000 TableCode        : 0xe10af000
       +0x004 QuotaProcess     : 0x81eedb40 _EPROCESS
       +0x008 UniqueProcessId  : 0x000001e8 Void
3. 句柄表的結構

  句柄表分爲多級結構,通常爲一級結構,當句柄值太大時則會展開多級結構,之後三位爲準。

  一個句柄值佔8個字節,一頁4KB,故一頁能存儲 512 個句柄值。

  若是採用多級結構(以兩級爲例),第一級就會存儲第二級的地址。存儲地址則能存儲 1024 個地址,這樣算下來採用兩級結構能夠存儲 512*1024 個值。

  咱們觀察是否採用多級結構,是看 TableCode的最後一位,好比 爲 1,則採用二級結構,依次類推...

  

4. 句柄值結構

  在句柄表中一個句柄值佔8字節,故咱們採用dq來查看。

  kd> dq 0xe10af000+1d1*8
    e10afe88  0000003a`816c800b 0000003a`816c800b
    e10afe98  0000003a`816c800b 0000003a`816c800b

  其前4個字節是關於屬性,後面4字節纔是真正存儲句柄的值。

  注意,後3位是關於屬性,要真正找到正確的地址,要變爲0,好比 816c800b ,b = 1011 , 正確的應該爲 1000,即 816c8008。

5. 如何使用R3環的句柄值查找R0中的句柄值

  咱們在三環,hPro = OpenProcess(),將 t = hPro / 4,所獲得的結果就是在句柄表中的索引號t,其佔8位,故須要 t*8 獲得地址。

6. 句柄的結構體

  從結構體中來看,句柄能夠看做 句柄頭+句柄體

  句柄頭是 _OHJECT_HEADER;句柄體就是其句柄的本體,好比線程的句柄體爲 _ETHREAD,進程的句柄體爲 _EPROCESS

  句柄體在句柄頭下方 +0x18 的位置。

  kd> dt _OBJECT_HEADER
    nt!_OBJECT_HEADER
       +0x000 PointerCount     : Int4B
       ····
       +0x014 SecurityDescriptor : Ptr32 Void
       +0x018 Body             : _QUAD
  所以,若是咱們打算查看 _EPROCESS,就須要偏移 +0x18個字節。

  e2808380  81b1e5b3 0000003a 81b1e5b3 0000003a
  kd> dt _EPROCESS 81b1e5b0+18
    ntdll!_EPROCESS   
      +0x174 ImageFileName    : [16]  "calc.exe"

7. 句柄值的屬性

  前面咱們介紹前句柄值佔8位,前四個字節表明屬性,下面咱們就來介紹一下。

  

  舉一個例子,咱們使用下面代碼來修改最後一個的句柄的屬性

    SetHandleInformation(hPro,HANDLE_FLAG_PROTECT_FROM_CLOSE,HANDLE_FLAG_PROTECT_FROM_CLOSE);

  而後經過windbg查看,能夠明顯看到與其餘存在的不一樣:

    e10fdc80  816899cb 0200003a 816899cb 0000003a

 

3、經過實驗來驗證句柄表有關信息:

1)實驗代碼 handle_test.exe

 1 // handle_test.cpp : Defines the entry point for the console application.
 2 //
 3 
 4 #include "stdafx.h"
 5 #include <Windows.h>
 6 #include <stdlib.h>
 7 #include <stdio.h>
 8 void Test(){
 9     DWORD PID;
10     HANDLE hPro = NULL;
11     HWND hWnd = ::FindWindow(NULL,"計算器");
12     ::GetWindowThreadProcessId(hWnd,&PID);
13     for(int i = 0; i<100;i++){
14         hPro = ::OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,TRUE,PID);
15         printf("handle value: %x \n", hPro);
16     }
17     // 修改屬性
18     SetHandleInformation(hPro,HANDLE_FLAG_PROTECT_FROM_CLOSE,HANDLE_FLAG_PROTECT_FROM_CLOSE);
19 }
20 int main(int argc, char* argv[])
21 {
22     printf("Hello World!\n");
23     Test();
24     system("pause");
25     return 0;
26 }
View Code

2)實驗原理:

  1. 先將計算器打開。

  2. handle_test.exe 會先查找計算器的窗口獲取PID,而後打開該進程。

  3. 這樣就會在 handle_test.exe 進程內部建立關於計算器的句柄的值,咱們來研究該值。

  

3)實驗流程:

  1)獲取 句柄值 640,按照  【2、5】  所描述的,地址在TableCode中的爲 640/4*8 = C80.

  2)經過 windbg 的!process 0 0來查找 handle_test.exe 的 _EPROCESS地址。

  Failed to get VadRoot
    PROCESS 81c45020  SessionId: 0  Cid: 07cc    Peb: 7ffd3000  ParentCid: 00a8
        DirBase: 1af46000  ObjectTable: e154d450  HandleCount: 123.
        Image: handle_test.exe
  3)先從 0x174 中驗證其是不是該進程

     +0x174 ImageFileName    : [16]  "handle_test.exe"

    以後從  0xc4位置找到句柄表地址 

     +0x0c4 ObjectTable      : 0xe154d450 _HANDLE_TABLE

  4)以後,咱們從 句柄表地址來查看 TableCode 0xe10fd000,加上以前算的 C80 偏移獲得句柄值。

  kd> dt 0xe154d450 _HANDLE_TABLE
    ntdll!_HANDLE_TABLE
       +0x000 TableCode        : 0xe10fd000
       +0x004 QuotaProcess     : 0x81c45020 _EPROCESS
       +0x008 UniqueProcessId  : 0x000007cc Void
       +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
       +0x01c HandleTableList  : _LIST_ENTRY [ 0xe2728354 - 0xe24faafc ]
       +0x024 HandleContentionEvent : _EX_PUSH_LOCK
       +0x028 DebugInfo        : (null)
  5)按照【2、4】所介紹的,取得的值 816899cb,變爲 816899c8,這指向 OBJECT_HEAD,偏移+0x18字節才真正指向 BODY(_EPROCESS)

    kd> dq 0xe10fd000+c80
      e10fdc80  0200003a`816899cb

  6)驗證咱們的 _EPROCESS,驗證經過,實驗成功。

    kd> dt _EPROCESS 816899c8 + 18
    ntdll!_EPROCESS

      +0x174 ImageFileName    : [16]  "calc.exe"

相關文章
相關標籤/搜索