消息机制学习笔记(四)—— 内核回调机制
消息機制學習筆記(四)—— 內核回調機制
- 要點回顧
- 內核調用
- 實驗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位置
總結
總結
以上是生活随笔為你收集整理的消息机制学习笔记(四)—— 内核回调机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows消息机制学习笔记(三)——
- 下一篇: 软件调试学习笔记(一)—— 调试对象