前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

逆向学习记录3:寻找窗口处理函数与条件断点

qiguaw 2024-09-05 19:36:04 资源文章 19 ℃ 0 评论

#行家计划#书接上文,逆向学习如积沙成塔,如古人言:“不积跬步,无以至千里.不积小流,无以成江海”。逆向学习非常枯燥,非常需要时间。废话不多说,直接进入主题。

所需知识

上文我们在反汇编找到了winmain函数,接下来我们需要寻找到窗口的处理函数,才能针对不同的消息(如针对鼠标左右击等)下条件断点。

typedef struct {
    UINT style;
    WNDPROC lpfnWndProc; //窗口处理函数
    int cbClsExtra;
    int cbWndExtra;
    HINSTANCE hInstance; //实例句柄,winmain的第一个参数,ImageBase
    HICON hIcon;
    HCURSOR hCursor;
    HBRUSH hbrBackground; //背景画刷
    LPCTSTR lpszMenuName;
    LPCTSTR lpszClassName;  //一类窗口类名
} WNDCLASS, *PWNDCLASS;

The WNDCLASS structure contains the window class attributes that are registered by the RegisterClass function.

结构WNDCLASS包含一个窗口类的全部信息,也是Windows编程中使用的基本数据结构之一,应用程序通过定义一个窗口类确定窗口的属性,为了快速进入主题,在此只介绍比较重要的成员。其他的成员可以通过MSDN Library或网络进行查询。

第二个成员

WNDPROC lpfnWndProc;

Pointer to the window procedure. You must use the CallWindowProc function to call the window procedure.

指向窗口处理函数的指针,而具体的窗口处理函数形式如下:

LRESULT CALLBACK WindowProc(HWND hwnd, //窗口句柄
    UINT uMsg,   //消息类型,常量标识
    WPARAM wParam,//消息的附加信息
    LPARAM lParam);//消息的附加信息

The WindowProc function is an application-defined function that processes messages sent to a window. The WNDPROC type defines a pointer to this callback function. WindowProc is a placeholder for the application-defined function name.

窗口处理函数的主要作用是处理该窗口所需的消息,即从应用程序消息队列中取出消息进行处理。如针对该窗口的移动,初始化,拉伸等等。其成员组成和MSG结构体成员很类似。如下是一个简单的消息处理函数:

LRESULT CALLBACK WindowProc(   HWND hwnd,UINT uMsg, WPARAM wParam, LPARAM lParam  	
)  	{  								
		switch(uMsg){	
			case WM_CREATE: {	//窗口创建								
				return 0;					
			}						
		case WM_MOVE:{	//窗口移动					
				return 0;					
			}						
		case WM_DESTROY:{	//窗口销毁		
				return 0;					
			}				
		case WM_KEYUP:{	//按下键	
				return 0;					
			}						
		case WM_KEYDOWN:{		//抬起键							
				return 0;					
			}										
		case WM_LBUTTONDOWN:{//鼠标左击
				return 0;					
			}							
			}
		return DefWindowProc(hwnd,uMsg,wParam,lParam);//不需要的消息,交由系统处理							
	} 

其他成员可以初始化为0,窗口类属性定义好以后,还需要注册。而RegisterClass()就是在系统注册某一类型的窗体。也就是将你提供的WNDCLASS数据注册为一个窗口类,在WNDCLASS.lpszClassName中定义该WNDCLASS的标识。

typedef WORD ATOM;
ATOM RegisterClass(CONST WNDCLASS *lpWndClass);

在反汇编中定位窗口处理函数

根据上一篇文章的步骤进入winmain领空:

图片的标号1是将wndclass的地址放到eax寄存器中,标号2就是RegisterClassA的参数也就是wndclass结构体的地址。所以我在标号2处下断点就可以知道wndclass结构体在哪。按F2下断点,然后放开程序,让程序停到断点处,此时eax存的就是wndclass地址。

将鼠标放在eax上单击鼠标右键,选择follow in stack (此时EBP 0019FF70,ESP 0019FE9C,eax 0019FEC0,此地址在栈中)

此时标号1就是第一个成员,标识2就是第二个成员,也就是窗口处理函数所在地址,标识3就是最后一个成员即窗口的类名。然后将鼠标放置在第二成员上,然后单击鼠标右键,选择Follow in Disassembler(追到反汇编)。窗口处理函数领空如下图:

条件断点

esp+8就是窗口处理函数的第二参数即消息类型。

为什么esp+8就是消息类型?初步推理,上层调用消息处理函数时,压栈4个参数(从右向左压栈,窗口处理函数使用stdcall),然后使用call 0x4xxxx,即将自身下一行地址压栈。

下个条件断点证明一下,条件断点方法如下图

//左右击常量
#define WM_LBUTTONDOWN 513
#define WM_LBUTTONUP 514
#define WM_RBUTTONDOWN 516
#define WM_RBUTTONUP 517

然后在该应用程序的窗口中点击鼠标左键。

此时我们看到[esp+8]为0x201,即十进制的513,而左击常量WM_LBUTTONDOWN为513。故esp+8为消息类型。

此篇到此结束,欲知后事如何,且看下文分解(可能还没写)。该文仅为学习记录,如有不足,望海涵批评指正。本文及该合集文章仅限学习,不可用于非法用途,一切后果与本人无关。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表