OD定位消息-事件

admin 2023年11月30日08:55:24评论7 views字数 4220阅读14分4秒阅读模式

什么是消息-事件


Windows中的事件是一个动作,这个动作可能是用户操作应用程序产生的,也可能是Windows自己产生的。

那么又有其他的问题来了:

这个动作是什么时候产生的?哪个应用程序产生的?在什么位置产生的?...

Windows为了能够准确的描述这些信息,提供了一个结构体:MSG,该结构体里面记录的事件的详细信息.

typedef struct tagMSG {
HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG, *PMSG;

参数说明:

  • hwnd:表示消息所属的窗口,一个消息一般都是与某个窗口相关联的,在Windows中 HWND类型的变量通常用来标识窗口。

  • message:在Windows中,消息是由一个数值来表示的,但是由于数值不便于记忆,所以Windows将消息对应的数值定义为WM_XXX宏(WM == Window Message),鼠标左键按下WM_LBUTTONDOWN,键盘按下 WM_KEYDOWN

  • wParam 和 lParam:32位消息的特定附加信息,具体表示什么处决于message

  • time:消息创建时的时间

  • pt:消息创建时的鼠标位置

消息触发与处理过程

  1. 系统/用户触发的某个动作

  2. 系统将这些信息存储到MSG结构体中

  3. 系统将该消息存储到相关应用程序的消息队列中

  1. MSG Msg;

	MSG msg;  	
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
  1. DispatchMessage将加工过的消息传递给操作系统

  2. 系统调用窗口过程函数

LRESULT CALLBACK WindowProc( //回调函数 			
IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
);

过程图示:

系统消息队列与应用程序消息队列:

OD定位消息-事件

代码

// 消息.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "Tools.h"


LRESULT CALLBACK WindowProc(
IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
{
switch(uMsg)
{
//窗口消息
case WM_CREATE:
{
DbgPrintf("WM_CREATE %d %dn",wParam,lParam);
CREATESTRUCT* createst = (CREATESTRUCT*)lParam;
DbgPrintf("CREATESTRUCT %sn",createst->lpszClass);

return 0;
}
case WM_MOVE:
{
DbgPrintf("WM_MOVE %d %dn",wParam,lParam);
POINTS points = MAKEPOINTS(lParam);
DbgPrintf("X Y %d %dn",points.x,points.y);

return 0;
}
case WM_SIZE:
{
DbgPrintf("WM_SIZE %d %dn",wParam,lParam);
int newWidth = (int)(short) LOWORD(lParam);
int newHeight = (int)(short) HIWORD(lParam);
DbgPrintf("WM_SIZE %d %dn",newWidth,newHeight);

return 0;
}
case WM_DESTROY:
{
DbgPrintf("WM_DESTROY %d %dn",wParam,lParam);
PostQuitMessage(0);

return 0;
}
//键盘消息
case WM_KEYUP:
{
DbgPrintf("WM_KEYUP %d %dn",wParam,lParam);

return 0;
}
case WM_KEYDOWN:
{
DbgPrintf("WM_KEYDOWN %d %dn",wParam,lParam);

return 0;
}
//鼠标消息
case WM_LBUTTONDOWN:
{
DbgPrintf("WM_LBUTTONDOWN %d %dn",wParam,lParam);
POINTS points = MAKEPOINTS(lParam);
DbgPrintf("WM_LBUTTONDOWN %d %dn",points.x,points.y);

return 0;
}
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}


int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//窗口的类名
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, //相对于父窗口的X坐标
10, //相对于父窗口的Y坐标
600, //窗口的宽度
300, //窗口的高度
NULL, //父窗口句柄,为NULL
NULL, //菜单句柄,为NULL
hInstance, //当前应用程序的句柄
NULL); //附加数据一般为NULL

if(hwnd == NULL) //是否创建成功
return 0;

// 显示窗口
ShowWindow(hwnd, SW_SHOW);

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



return 0;
}



// Tools.cpp: implementation of the Tools class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Tools.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

void __cdecl OutputDebugStringF(const char *format, ...)
{
va_list vlArgs;
char *strBuffer = (char*)GlobalAlloc(GPTR, 4096);

va_start(vlArgs, format);
_vsnprintf(strBuffer, 4096 - 1, format, vlArgs);
va_end(vlArgs);
strcat(strBuffer, "n");
OutputDebugStringA(strBuffer);
GlobalFree(strBuffer);
return;
}

// Tools.h: interface for the Tools class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_TOOLS_H__0D7FE55E_21D9_445D_9CC3_340759DED8A2__INCLUDED_)
#define AFX_TOOLS_H__0D7FE55E_21D9_445D_9CC3_340759DED8A2__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

void __cdecl OutputDebugStringF(const char *format, ...);

#ifdef _DEBUG
#define DbgPrintf OutputDebugStringF
#else
#define DbgPrintf
#endif


#endif // !defined(AFX_TOOLS_H__0D7FE55E_21D9_445D_9CC3_340759DED8A2__INCLUDED_)

OD分析

  1. 生成Release版本

  2. 开始分析:


  1. OD打开时:OD定位消息-事件

  2. 会找到一个GetModuleHandleA,该函数返回的是一个窗口句柄,那么返回值返回到eax中,所以,下面的PUSH EAX,就是将窗口句柄传入call 消息.00401060函数中,那么该函数应该就是入口函数了。

OD定位消息-事件

  1. 跟进该函数中,我们发现了一个RegisterClassA函数,根据我们的代码,那么这个call上面的PUSH EDX应该就是我们的wndclass类,将断点下到该处:OD定位消息-事件

  2. 查看edx对应的堆栈,记住,该edx对应的就是wndclass地址。目前我们发现都是0,没关系,我们将代码继续执行,为了方便观察,我们锁定堆栈窗口OD定位消息-事件

  3. OD定位消息-事件

  4. 接着,我们继续执行代码,执行到CALL指令:OD定位消息-事件

  5. 根据上图,可以知道,我们的回调函数,就是该函数指针的第二个位置。我们跟进去OD定位消息-事件

  6. 找到esp+0x8,这个地方是什么呢?

  7. OD定位消息-事件OD定位消息-事件

  8. 根据我们的回调函数,我们知道,这个是消息ID,因此,我们可以通过条件断点,找我们需要的消息ID。

现在,我们知道如何对我们需要的消息下断点了。


原文始发于微信公众号(loochSec):OD定位消息-事件

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年11月30日08:55:24
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   OD定位消息-事件http://cn-sec.com/archives/2253803.html

发表评论

匿名网友 填写信息