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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

消息机制学习笔记(四)—— 内核回调机制

發布時間:2025/3/21 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 消息机制学习笔记(四)—— 内核回调机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

消息機制學習筆記(四)—— 內核回調機制

    • 要點回顧
    • 內核調用
      • 實驗1:理解內核調用
        • 第一步:編譯并運行以下代碼
        • 第二步:修改窗口過程函數,重新運行
    • KeUserModeCallback
      • 實驗2:在OD中查看回調函數地址表
        • 第一步:加載程序
        • 第二步:在內存中查看TEB
        • 第三步:查看PEB數據
        • 第四步:查看回調地址表
    • 總結

要點回顧

1)GetMessage不僅能夠取出消息,還能處理SentMessagesListHead隊列中的消息
2)DispatchMessage用于處理其它隊列中的消息。

內核調用

描述:窗口過程函數除了會在消息循環中被調用,一些0環的代碼也可以直接發起調用。

例如:窗口初始化時、窗口創建時、窗口顯示時。

目的:使窗口在被初始化、被創建、被顯示時,用戶能夠有機會做一些事情。

實驗1:理解內核調用

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

注意:運行前在while(GetMessage(&msg, NULL, 0, 0))這行設置斷點。

#include <stdio.h> #include <windows.h>#define DPRINTF_BUF_SZ 1024void OutputDebugStringf(char *fmt, ...) { #ifdef _DEBUGva_list args;char buf[DPRINTF_BUF_SZ];va_start(args, fmt);vsprintf(buf, fmt, args);OutputDebugString(buf); #endif }LRESULT CALLBACK WindowProc(IN HWND hwnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam ){switch(uMsg){case WM_DESTROY:{ExitProcess(0);return 0;}}OutputDebugStringf("消息類型:%x \n", uMsg);return DefWindowProc(hwnd, uMsg, wParam, lParam); }int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd ){//窗口的類名TCHAR className[] = "My First Window";//創建一個自己的窗口WNDCLASS wndclass = {0};wndclass.hbrBackground = (HBRUSH)COLOR_MENU;wndclass.lpfnWndProc = WindowProc;wndclass.lpszClassName = className;wndclass.hInstance = hInstance;//注冊RegisterClass(&wndclass);//創建窗口HWND hwnd = CreateWindow(className,TEXT("測試窗口"),WS_OVERLAPPEDWINDOW,10,10,600,300,NULL,NULL,hInstance,NULL);if(hwnd == NULL)return 0;//顯示窗口ShowWindow(hwnd, SW_SHOW);//消息循環MSG msg;while(GetMessage(&msg, NULL, 0, 0)){//TranslateMessage(&msg);DispatchMessage(&msg);}return 0; }

運行結果

第二步:修改窗口過程函數,重新運行

注意:仍然在while(GetMessage(&msg, NULL, 0, 0))這行設置斷點。

新窗口過程函數

LRESULT CALLBACK WindowProc(IN HWND hwnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam ){switch(uMsg){case WM_CREATE:{MessageBoxA(NULL, "窗口被創建了", "CREATE", MB_OK);return 0;}case WM_DESTROY:{ExitProcess(0);return 0;}}OutputDebugStringf("消息類型:%x \n", uMsg);return DefWindowProc(hwnd, uMsg, wParam, lParam); }

運行結果

不難發現,程序并未進入消息循環,卻調用了窗口過程函數,輸出了消息與彈窗,說明消息不是只有當調用GetMessage與DispatchMessage時才處理。

KeUserModeCallback

描述
1)從0環調用3環函數的幾種方式

  • APC
  • 異常
  • 內核回調

APC異常回三環的落腳點比較單一,而消息機制需要處理的情況較多,不能使用同一個邏輯進行處理,因此消息機制使用內核回調調用三環函數。

2)回到3環的落腳點

  • APC:ntdll!KiUserApcDispatcher
  • 異常:ntdll!KiUserExceptionDispatcher

3)內核回調在3環的落腳點:KeUserModeCallback

PEB+0x2C指向回調函數地址表。

4)凡是有窗口的程序就有可能0環直接調用3環的程序。


聲明

NTSTATUS NTAPI KeUserModeCallback(IN ULONG FunctionID, //索引,指向三環落腳點IN PVOID InputBuffer, //包含窗口回調函數與相關重要信息IN ULONG InputLength,OUT PVOID *OutputBuffer,OUT PULONG OutputLength );

FunctionID索引列表

#define USER32_CALLBACK_WINDOWPROC (0) #define USER32_CALLBACK_SENDASYNCPROC (1) #define USER32_CALLBACK_LOADSYSMENUTEMPLATE (2) #define USER32_CALLBACK_LOADDEFAULTCURSORS (3) #define USER32_CALLBACK_HOOKPROC (4) #define USER32_CALLBACK_EVENTPROC (5) #define USER32_CALLBACK_LOADMENU (6) #define USER32_CALLBACK_CLIENTTHREADSTARTUP (7) #define USER32_CALLBACK_MAXIMUM (7)

實驗2:在OD中查看回調函數地址表

第一步:加載程序

第二步:在內存中查看TEB


第三步:查看PEB數據

PEB位于TIB+0x30位置

第四步:查看回調地址表

回調地址表位于PEB+0x2C位置

總結

  • 不是所有消息都是在進入消息循環后由GetMessageDispatchMessage進行處理的,部分內核代碼也能夠調用窗口處理函數。
  • 內核代碼通過KeUserModeCallback調用窗口處理函數,由第一個參數FunctionID決定回到三環時的落腳點。
  • FunctionID的值為回調地址表的索引,回調地址表位于PEB+0x2C位置,每個值為一個函數地址。
  • 總結

    以上是生活随笔為你收集整理的消息机制学习笔记(四)—— 内核回调机制的全部內容,希望文章能夠幫你解決所遇到的問題。

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