消息机制学习笔记(四)—— 内核回调机制
消息機(jī)制學(xué)習(xí)筆記(四)—— 內(nèi)核回調(diào)機(jī)制
- 要點(diǎn)回顧
- 內(nèi)核調(diào)用
- 實(shí)驗(yàn)1:理解內(nèi)核調(diào)用
- 第一步:編譯并運(yùn)行以下代碼
- 第二步:修改窗口過(guò)程函數(shù),重新運(yùn)行
- KeUserModeCallback
- 實(shí)驗(yàn)2:在OD中查看回調(diào)函數(shù)地址表
- 第一步:加載程序
- 第二步:在內(nèi)存中查看TEB
- 第三步:查看PEB數(shù)據(jù)
- 第四步:查看回調(diào)地址表
- 總結(jié)
要點(diǎn)回顧
1)GetMessage不僅能夠取出消息,還能處理SentMessagesListHead隊(duì)列中的消息
2)DispatchMessage用于處理其它隊(duì)列中的消息。
內(nèi)核調(diào)用
描述:窗口過(guò)程函數(shù)除了會(huì)在消息循環(huán)中被調(diào)用,一些0環(huán)的代碼也可以直接發(fā)起調(diào)用。
例如:窗口初始化時(shí)、窗口創(chuàng)建時(shí)、窗口顯示時(shí)。
目的:使窗口在被初始化、被創(chuàng)建、被顯示時(shí),用戶能夠有機(jī)會(huì)做一些事情。
實(shí)驗(yàn)1:理解內(nèi)核調(diào)用
第一步:編譯并運(yùn)行以下代碼
注意:運(yùn)行前在while(GetMessage(&msg, NULL, 0, 0))這行設(shè)置斷點(diǎn)。
#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";//創(chuàng)建一個(gè)自己的窗口WNDCLASS wndclass = {0};wndclass.hbrBackground = (HBRUSH)COLOR_MENU;wndclass.lpfnWndProc = WindowProc;wndclass.lpszClassName = className;wndclass.hInstance = hInstance;//注冊(cè)RegisterClass(&wndclass);//創(chuàng)建窗口HWND hwnd = CreateWindow(className,TEXT("測(cè)試窗口"),WS_OVERLAPPEDWINDOW,10,10,600,300,NULL,NULL,hInstance,NULL);if(hwnd == NULL)return 0;//顯示窗口ShowWindow(hwnd, SW_SHOW);//消息循環(huán)MSG msg;while(GetMessage(&msg, NULL, 0, 0)){//TranslateMessage(&msg);DispatchMessage(&msg);}return 0; }運(yùn)行結(jié)果:
第二步:修改窗口過(guò)程函數(shù),重新運(yùn)行
注意:仍然在while(GetMessage(&msg, NULL, 0, 0))這行設(shè)置斷點(diǎn)。
新窗口過(guò)程函數(shù):
LRESULT CALLBACK WindowProc(IN HWND hwnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam ){switch(uMsg){case WM_CREATE:{MessageBoxA(NULL, "窗口被創(chuàng)建了", "CREATE", MB_OK);return 0;}case WM_DESTROY:{ExitProcess(0);return 0;}}OutputDebugStringf("消息類型:%x \n", uMsg);return DefWindowProc(hwnd, uMsg, wParam, lParam); }運(yùn)行結(jié)果:
不難發(fā)現(xiàn),程序并未進(jìn)入消息循環(huán),卻調(diào)用了窗口過(guò)程函數(shù),輸出了消息與彈窗,說(shuō)明消息不是只有當(dāng)調(diào)用GetMessage與DispatchMessage時(shí)才處理。
KeUserModeCallback
描述:
1)從0環(huán)調(diào)用3環(huán)函數(shù)的幾種方式:
- APC
- 異常
- 內(nèi)核回調(diào)
APC與異常回三環(huán)的落腳點(diǎn)比較單一,而消息機(jī)制需要處理的情況較多,不能使用同一個(gè)邏輯進(jìn)行處理,因此消息機(jī)制使用內(nèi)核回調(diào)調(diào)用三環(huán)函數(shù)。
2)回到3環(huán)的落腳點(diǎn):
- APC:ntdll!KiUserApcDispatcher
- 異常:ntdll!KiUserExceptionDispatcher
3)內(nèi)核回調(diào)在3環(huán)的落腳點(diǎn):KeUserModeCallback
PEB+0x2C指向回調(diào)函數(shù)地址表。
4)凡是有窗口的程序就有可能0環(huán)直接調(diào)用3環(huán)的程序。
聲明:
NTSTATUS NTAPI KeUserModeCallback(IN ULONG FunctionID, //索引,指向三環(huán)落腳點(diǎn)IN PVOID InputBuffer, //包含窗口回調(diào)函數(shù)與相關(guān)重要信息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)實(shí)驗(yàn)2:在OD中查看回調(diào)函數(shù)地址表
第一步:加載程序
第二步:在內(nèi)存中查看TEB
第三步:查看PEB數(shù)據(jù)
PEB位于TIB+0x30位置
第四步:查看回調(diào)地址表
回調(diào)地址表位于PEB+0x2C位置
總結(jié)
總結(jié)
以上是生活随笔為你收集整理的消息机制学习笔记(四)—— 内核回调机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Windows消息机制学习笔记(三)——
- 下一篇: 软件调试学习笔记(一)—— 调试对象