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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows句柄表学习笔记 —— 句柄表全局句柄表

發布時間:2025/3/21 windows 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows句柄表学习笔记 —— 句柄表全局句柄表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Windows句柄表學習筆記 —— 句柄表&全局句柄表

    • 句柄表
      • 實驗一:在WinDbg中查看句柄表
        • 第一步:打開一個Win32窗口程序
        • 第二步:編譯并運行以下代碼
        • 第三步:查看運行結果
        • 第四步:在WinDbg中定位句柄表
      • 句柄表結構
      • 實驗二:在WinDbg中查看并分析句柄表結構
        • 第一步:打開一個Win32窗口程序
        • 第二步:編譯以下代碼并運行
        • 第三步:查看運行結果
        • 第四步:在WinDbg中定位最后一個句柄
        • 第五步:通過句柄定位內核對象
    • 全局句柄表
      • 全局句柄表結構
      • 實驗:在WinDbg中觀察全局句柄表
        • 第一步:打開一個Win32窗口程序
        • 第二步:獲得進程PID
        • 第三步:獲得全局句柄表
        • 第四步:查看_EPROCESS結構體

句柄表

描述

  • 當一個進程創建或者打開一個內核對象時,將獲得一個句柄,通過這個句柄可以訪問對應的內核對象
  • 句柄表存儲在零環,一個進程使用了幾個句柄,在該進程的句柄表中就會存儲幾個句柄
  • 所有的句柄所對應的內核對象,都包含在 _OBJECT_HEADER 中,真正的內核對象保存在 _OBJECT_HEADER +0x018 body 的位置
  • 例如

    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, Proc, NULL, 0, NULL);

    思考:為什么微軟不直接把內核對象的地址返回給用戶,而是通過句柄的形式
    答案:句柄存在的目的是為了避免在應用層直接修改內核對象,如果直接返回內核對象的地址,那么就意味著我們可以在應用層修改這個地址,一旦指向了無效的內核內存地址就會藍屏

    注意

  • 窗口字體筆刷等句柄與本章所學句柄是兩碼事
  • 創建句柄不等同于打開句柄,當創建的時候,操作系統會在零環為內核對象分配一個結構體(例如CreateEvent),如果自己或他人打開了這個內核對象(例如OpenProcess),那么將不會再次為這個內核對象分配一個結構體,而是返回一個句柄的索引值
  • 若同一個內核對象被引用了100次,那么在句柄表中就會存儲100個內核對象的地址
  • 句柄的值并非如上圖所顯示的只占4個字節,而是占8個字節,但是句柄表的值仍然按照4個字節進行計算
  • 句柄索引定位對應句柄的計算公式:handle = index / 4 * 8

    實驗一:在WinDbg中查看句柄表

    第一步:打開一個Win32窗口程序

    本實驗選擇進程為計算器(calc.exe)

    第二步:編譯并運行以下代碼

    #include <stdio.h> #include <windows.h>int main() {DWORD PID;HANDLE hPro = NULL;HWND hWnd = ::FindWindow(NULL, "計算器");::GetWindowThreadProcessId(hWnd, &PID);for(int i=0; i<100 ;i++){hPro = ::OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE, TRUE, PID);printf("句柄:%x\n", hPro);}getchar();return 0; }

    第三步:查看運行結果

    第四步:在WinDbg中定位句柄表

    kd> !process 0 0

    kd> dt _EPROCESS 862adda0

    kd> dt _HANDLE_TABLE 0xe12ca370

    kd> dd 0xe1b6f000


    第一個句柄地址 = 0xe1b6f000 + 0x7cc / 4 * 8 = 0xe1b6ff98

    kd> dq 0xe1b6ff98

    句柄表結構


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

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

    3&4:共4個字節,其中bit0bit2存儲句柄的屬性,默認為0,bit1表示該句柄是否可繼承(參考OpenProcess的第二個參數)

    實驗二:在WinDbg中查看并分析句柄表結構

    第一步:打開一個Win32窗口程序

    本實驗選擇進程為計算器(calc.exe)

    第二步:編譯以下代碼并運行

    #include <stdio.h> #include <windows.h>int main() {DWORD PID;HANDLE hPro = NULL;HWND hWnd = ::FindWindow(NULL, "計算器");::GetWindowThreadProcessId(hWnd, &PID);for(int i=0; i<100 ;i++){hPro = ::OpenProcess(PROCESS_CREATE_THREAD, TRUE, PID);printf("句柄:%x\n", hPro);}//HANDLE_FLAG_PROTECT_FROM_CLOSE:句柄不可用CloseHandle關閉SetHandleInformation(hPro, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE);getchar();return 0; }

    第三步:查看運行結果

    第四步:在WinDbg中定位最后一個句柄

    定位過程參考實驗一

    第五步:通過句柄定位內核對象

    句柄值:0200003a 8617c7e3
    清理后三位bit,后四個字節為地址: 8617c7e0
    注意:此時該地址指向 _OBJECT_HEADER ,若想查看真正的內核對象結構體還要加上0x18
    實驗中我們使用OpenProcess打開句柄,因此查看_EPROCESS結構體

    kd> dt _EPROCESS 8617c7e0 + 0x18

    全局句柄表

    描述

  • 進程的句柄表是私有的,每個進程都有一個自己的句柄表
  • 除此之外,系統還有一個全局句柄表:PsdCidTable,為 _HANDLE_TABLE 結構,所有的進程和線程無論無論是否打開,都在這個表中
  • 每個進程和線程都有一個唯一的編號:PIDCID 這兩個值其實就是全局句柄表中的索引
  • 進程和線程的查詢,主要是以下三個函數,按照給定的PIDCIDPspCidTable從查找相應的進線程對象:

    PsLookupProcessThreadByCid()
    PsLookupProcessByProcessId()
    PsLookupThreadByThreadId()

  • 全局句柄表結構

    描述:

  • 若TableCode的值為0,說明handle_max = 4KB / 8 = 512,此時,句柄表為一級句柄表
  • 若打開句柄數量超過512個,TableCode的值就會置為1,此時,句柄表變為兩級句柄表。第一級句柄表中每個成員存儲著第二級句柄表的地址,第二級句柄表中才真正存儲著內核對象的地址,handle_max = 1024 * 512
  • 若打開句柄數量超過1024 * 512個,TableCode的值就會置為3,此時,句柄表變為三級句柄表,第一級為地址,第二級也為地址,第三級才是句柄,handle_max = 1024 * 1024 * 512
  • 實驗:在WinDbg中觀察全局句柄表

    第一步:打開一個Win32窗口程序

    本實驗選擇進程為計算器(calc.exe)

    第二步:獲得進程PID


    index = 1048 / 4 = 0x106

    第三步:獲得全局句柄表

    kd> dd PspCidTable

    kd> dt _HANDLE_TABLE e1003c58

    第四步:查看_EPROCESS結構體

    kd> dq e1005000 + 0x106*8

    kd> dt _EPROCESS 85e2d540 //后三位屬性位清零

    總結

    以上是生活随笔為你收集整理的Windows句柄表学习笔记 —— 句柄表全局句柄表的全部內容,希望文章能夠幫你解決所遇到的問題。

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