滴水逆向——Win32_定位回调函数

时间:2024-05-18 19:40:15

1、Win32应用程序入口识别

Ollydbg一进入程序停留的地方并不是我们自己定义的函数入口点,因此我们需要寻找EIP。

滴水逆向——Win32_定位回调函数

前面已经讲过入口函数参数的意义,再拿来复习复习

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

WinMain的第一个参数叫实例句柄。在Windows程序中,句柄无非就是一个数值,程序用他来标识某些东西在早期Windows程序中,当多路并发运行同一个程序时,就需要为那个程序创建多个实例。同一个程序的所有实例都共享代码以及只读存储(即菜单或对话框模板之类的资源)。一个程序可以通过查看hPrevInstance参数从而知道是否有它的其他实例正在运行。

在32位Windows中,这一概念已不再采用。因此WinMain的第二个参数通常总是NULL。

WinMain的第三个参数是用来运行程序的命令行。有些Windows程序在启动时用它来把文件装入内存。

WinMain的第四个参数用来指示程序最初如何显示:或正常显示,或最大化,或最小化。

WinMain入口函数需要有4个参数压入栈,所以我们先找压入4个参数的call

 

由于Win32应用程序的调用约定是stcall,参数传递是从右向左,且是内平栈

滴水逆向——Win32_定位回调函数

 

由于IAT表的关系,ollydbg可以帮我们识别很多系统函数

滴水逆向——Win32_定位回调函数

[<&KERNEL32.GetModuleHandleA ]其实就是得到WinMain中的第一个参数实例句柄,也就是WinMain中由于stcall被压入栈的第四个参数。

压入实例句柄的下一个call,应该就是我们的WinMain函数入口,我们再跟进去看看就能确定是不是我们的真正的WinMain函数入口了。

 

2、ESP寻址的特点

进入WinMain函数后,我们发现开栈操作并不是我们常见的EBP寻址(push ebp,move ebp,esb)

而是采用了sub esp,44这种方式开栈。

其实debug版本大多采用EBP+偏移开栈,release版本大多采用ESP-偏移的方式开栈。

相比较而言ESP开栈比EBP开栈更难逆,因为EBP开栈,它的栈底是保存着不会变的。而ESP寻址,每次push压栈、pop出栈都会引起ESP的变化,所以ESP寻址相比EBP寻址是变化的,对逆向人员要求更高。

滴水逆向——Win32_定位回调函数

每次push、pop后都需要计算ESP的值,如果人工计算的话难免会有纰漏,所以ollydbg帮我们做了这份工作,看右下角的堆栈窗口。

滴水逆向——Win32_定位回调函数

双击这个区域后,就会变成时刻以ESP为基址动态追踪的堆栈,举例如下

滴水逆向——Win32_定位回调函数

 

3、窗口回调函数的定位

我们了解了ESP寻址的操作,回归正题,来寻找窗口回调函数

窗口回调函数在WinMain函数中出现就是在函数开头构造wndclass类中,wndclass中的第二个参数就是窗口回调函数的指针。

滴水逆向——Win32_定位回调函数

而wndclass类可以通过RegisterClass函数得到,RegisterClass的唯一参数就是wndclass类的指针。

滴水逆向——Win32_定位回调函数

所以我们现在的首要任务就是找的RegisterClass函数。

滴水逆向——Win32_定位回调函数

RegisterClass函数基本上在WinMain函数开始处,所以一进入WinMain函数开始跟就行了。

滴水逆向——Win32_定位回调函数

得到winclass类的指针,由此得到回调函数的地址

滴水逆向——Win32_定位回调函数

 

4、具体事件的处理的定位

滴水逆向——Win32_定位回调函数

打个条件断点,因为会接受所有的事件,不做条件断点的话,会涌来很多响应。

底下这个条件断点的意思就是点击鼠标左键时断下

滴水逆向——Win32_定位回调函数

看看一看Windows定义的事件编号。

滴水逆向——Win32_定位回调函数

点击鼠标左键跟进断点

滴水逆向——Win32_定位回调函数

同理

滴水逆向——Win32_定位回调函数

总共有三种不同的事件被作者创建

滴水逆向——Win32_定位回调函数