windows 消息断点

windows 消息循环

以下是一个简单的处理按钮点击的示例:

#include <windows.h>

#define BUTTON_ID 1 // 定义按钮ID

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CREATE:
    {
        // 创建一个按钮
        HWND hButton = CreateWindow(
            L"BUTTON",          // 按钮类名
            L"Click Me",        // 按钮标题
            WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // 样式
            50,                 // x 坐标
            50,                 // y 坐标
            100,                // 宽度
            50,                 // 高度
            hwnd,               // 父窗口句柄
            (HMENU)BUTTON_ID,   // 按钮ID
            (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
            NULL);              // 参数
        break;
    }
    case WM_COMMAND:
        if (LOWORD(wParam) == BUTTON_ID && HIWORD(wParam) == BN_CLICKED)
        {
            MessageBox(hwnd, L"Button clicked!", L"Notification", MB_OK);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
    const wchar_t CLASS_NAME[] = L"Sample Window Class";

    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(
        0,
        CLASS_NAME,
        L"Button Click Example",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 300, 200,
        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, nCmdShow);

    MSG msg = {};
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

下面是消息循环的代码

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

当消息队列没有操作系统发来的消息时,GetMessage会阻塞等待,当消息队列有消息时,GetMessage会将消息赋值到msg,并且调用DispatchMessage分发到各个窗口的消息处理函数

下面是消息处理函数注册的代码

    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

通过SetWindowLong可以针对不同窗口设置消息处理函数

SetWindowLongA(hWnd,GWL_WNDPROC,WindowProc);

通过GetWindowLong 可以获取该窗口的消息处理函数

 LONG_PTR wndProc = GetWindowLongPtr(hwnd, GWLP_WNDPROC);

SetWindowLongGetWindowLong仅限当前进程使用,其它进程调用是会有权限不足的错误

x64dbg设置消息断点

加载程序后,运行到窗口弹出来,选择句柄选项卡,右键点击刷新
a30d73cbcdf920e942a7b93d1703157d

d04a3cc3a9c030063d2565a0357bac33
有很多关键信息,其中最关键的还是窗口过程,这个就是消息处理函数

在某个窗口右键点击消息断点
4b0ba06f8360a4b03c78f9e258f9af8a

弹出消息断点窗口
9d7c6dcbdc05fe4128f9d7af4f2aa29d
有很多消息类型,下面我列举一下点击事件的常见消息

WM_LBUTTONDOWN //用户按下鼠标左键时发送的消息。
WM_LBUTTONUP //用户释放鼠标左键时发送的消息
WM_COMMAND //当按钮被点击时,最常见的消息类型。消息携带控件 ID 和通知码,通常与按钮交互事件相关。

其中WM_COMMAND一般用的最多,因为它会携带被点击的控件ID。

x64dbg消息断点的缺陷

x64dbg的句柄窗口只能获取调用RegisterClass时的窗口过程,不能获取SetWindowLong设置的窗口过程,所以要准确获取正确的窗口过程,最好函数写个插件使用注入hook技术调用GetWindowLong获取窗口过程

posted @ 2024-11-05 00:38  乘舟凉  阅读(6)  评论(0编辑  收藏  举报