【文章作者】: icefisher
【作者邮箱】: 181712814@qq.com
【软件下载】: 
【软件名称】: echap518.exe(只是供学习的crackme)
【加壳方式】: 里面直接有个unpacked.ExE,是脱过壳的见【原创】我也来谈谈消息断点二
【保护方式】: 
【使用工具】: OllyICE
【文章日期】: 20080813

-----------------------------------------------------------------------
   第一篇原创希望大家支持下,首先我想和我一样菜的好多新人,一定都看过了论坛上的那个ollydbg教程,其中的消息断点真是让人难以理解,痛苦不堪啊,那么今天我就讲讲我自己的体会吧,希望望大家共勉。

首先,我觉得我们应该先了解消息,什么是消息,而谈到消息,就不能不说到windows程序设计的结构(大家放心。。。我大概讲下,不是什么重点)。
  如下,这是一个典型windows程序结构,其中很多细节地方我都略去了,

  1 /*------------------------------------------------------------------------
2 HELLOWIN.C -- Displays "Hello, Windows 98!" in client area
3
4 (c) Charles Petzold, 1998
5
6 -----------------------------------------------------------------------*/
7
8 #include <windows.h>
9 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
10
11
12 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
13
14 {
15
16 static TCHAR szAppName[] = TEXT ("HelloWin") ;
17
18 HWND hwnd ;
19
20 MSG msg ;
21 //前面都是变量定义,不关注。
22
23 WNDCLASwndclass ;
24
25
26 wndclass.style = CS_HREDRAW | CS_VREDRAW ;
27
28 wndclass.lpfnWndProc = WndProc ; //关键句,指出消息的处理函数所在位置
29
30 wndclass.cbClsExtra = 0 ;
31
32 wndclass.cbWndExtra = 0 ;
33
34 wndclass.hInstance = hInstance ;
35
36 wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
37
38 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
39
40 wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
41
42 wndclass.lpszMenuNam = NULL ;
43
44 wndclass.lpszClassName= szAppName ;
45
46 //这一连串的wndclass是在定义一类窗口的属性,形象地说就是在定义一个模子,然后后面可以用这个模子去建立更多的窗口,其中这个模子中我们需要注意的就是红字的 wndclass.lpfnWndProc = WndProc ;,他指出了这个模子的消息处理函数是哪个?也就是说这个窗口内发生的一切事件,比如说点击,双击,鼠标移动,按键,按下按钮这一切都会生消息,而系统会自动调用WndProc去处理这些问题。*/
47 if (!RegisterClass (&wndclass))
48
49 {
50
51 MessageBox ( NULL, TEXT ("This program requires Windows NT!"),
52
53 szAppName, MB_ICONERROR) ;
54
55 return 0 ;
56
57 }
58 //上面的是很简单的一个注册模子,你开始定义了这个模子wndclass,那你得让系统知道啊,这部分就是这个功能,不须太关注。
59 hwnd = CreateWindow( szAppName, // window class name
60
61 TEXT ("The Hello Program"), // window caption
62
63 WS_OVERLAPPEDWINDOW, // window style
64
65 CW_USEDEFAULT,// initial x position
66
67 CW_USEDEFAULT,// initial y position
68
69 CW_USEDEFAULT,// initial x size
70
71 CW_USEDEFAULT,// initial y size
72
73 NULL, // parent window handle
74
75 NULL, // window menu handle
76
77 hInstance, // program instance handle
78
79 NULL) ; // creation parameters
80
81 //注意上面便是利用这个模子,再加上一些自己独有的特点建立了一个窗口,大家不需关注
82
83 ShowWindow (hwnd, iCmdShow) ;
84
85 UpdateWindow (hwnd) ;
86
87
88 while (GetMessage (&msg, NULL, 0, 0))
89
90 {
91
92 TranslateMessage (&msg) ;
93
94 DispatchMessage (&msg) ;
95
96 }
97 //上面这个需要关注,前面提到过,如果窗口产生了消息我们需要调用WndProc来处理,那么之前我们需要上面的哪个while循环先处理下,这个现在我们也不需要了解。
98 return msg.wParam ;
99
100 }
101
102
103 LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
104 {
105
106 HDC hdc ;
107
108 PAINTSTRUCT ps ;
109
110 RECT rect ;
111
112 //重点来了,大家注意当我们到了WndProc这个消息处理函数中时,我们会不自然地想到:那么多种的消息,系统如何分辨是那个呢,这是我们就要注意到UINT message,他说明了消息的种类,而WPARAM,LPARAM都是消息具体的参数,大家这时看下面,因为message表示的消息不同,系统使用了switch来选择对应的处理程序,这里要注意WM_CREATE:像这些WM_开头的都是消息,而实质上都是数字,不过是头文件定义了一些等价字符串而已。
113 switch (message)
114
115 {
116
117 case WM_CREATE:
118
119 PlaySound (TEXT ("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC) ;
120
121 return 0 ;
122
123 case WM_PAINT:
124
125 hdc = BeginPaint (hwnd, &ps) ;
126
127 GetClientRect (hwnd, &rect) ;
128
129 DrawText (hdc, TEXT ("Hello, Windows 98!"), -1, &rect,
130
131 DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
132
133 EndPaint (hwnd, &ps) ;
134
135 return 0 ;
136
137 case WM_DESTROY:
138
139 PostQuitMessage (0) ;
140
141 return 0 ;
142 }
143 return DefWindowProc (hwnd, message, wParam, lParam) ;
144 }

Ok,大家是不是觉得很抽象,大家只要把我的注释看下,大概了解这是干嘛就可以了,其实为了理解消息,只需要注意我红字标出的部分,wndclass.lpfnWndProc  = WndProc ;这个就是我们的重点,他指出了这类windows窗口的消息处理交给了那个函数。然后重点就是CALLBACK,里面根据不同的消息转到不同的处理地方。

而大家在crackme中广为使用的则是对话框,比窗口实现方便些,他调用

1 DialogBox (    hInstance,
2 TEXT("AboutBox"),
3 hwnd,
4 AboutDlgProc
5 )

来实现,其中最后一个参数即为消息处理函数,等同于上面所说的WndProc

===========================================================================

好了当我们大概理解消息处理函数后我们就可以来看看这个例子了,首先ollyice载入unpacked.exe。F8单步运行。

如图地方F7,进入后F8,

如图地方F7,进入后可以看到F8几步就可以看到

回想起上篇我提到过的DialogBox (
hInstance,
TEXT("AboutBox"),
hwnd,
AboutDlgProc
)

因为DialogBoxParamA比DialogBox 最后多一个参数用来做记录,不影响我们理解,
(当然我们也可以用Ctrl+N查找函数DialogBoxParamA来直接定位到这里

我们看到DLGProc=004015A1,那么我们明显可以理解4015A1处是消息处理函数所在。我们Ctrl+G跟过去看,

我们会看到cmp eax,110 或者cmp eax,111之类的比较,

回想起上篇,这就等同于
switch (message)
        
    {
        
    case WM_CREATE:

case   WM_PAINT:
        
           
        
    case   WM_DESTROY:

}

而其中我们需要知道的是WM_COMMAD =111(用来定位按钮的消息) 
WM_LBUTONUP =202(鼠标左键放开)
而且我们还要注意一个地方回想上次我提到的
WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
当我们产生一个消息时,必然是调用这个函数,那么根据windows函数调用进栈法则,我们不难得到在消息处理函数开头如果下断点,栈结果必然如此
{
返回地址
hwnd
message
wParam
lParam
}

好了,基础讲完,就再看程序(因为前面push ebp,所以后面在取message时,为ebp+C,大家应该能明白吧),好了我们先F9运行次程序,在查看->窗口明显我们可以看到Check的id值为1。

     现在我们来仔细看看这个消息处理函数,他首先从ebp+C中取出了message,存入了eax中,然后开始switch的过程,他不断比较这些以确定是哪个消息,
     好了,我们知道按下按钮会产生WM_COMMAD(111) 消息,那么当我们看到cmp eax,111,je跳走时,我们离目标已经很近了,跟踪je到目的地,我们会奇怪,怎么还比较啊,这是因为按钮有很多个,每一个按下都会产生WM_COMMAD(111),那么这时我们需要再次判断是哪个按钮?

我们利用的就是wParam的低四位,他记录了按下按钮的ID值,所以就有了movz eax,
[ebp+10],好了我们已经知道了Check的ID值为1,那么我们看到
cmp eax,1 
je xxxxxxxx
跟过去下断点,这时我们就完成了对check的断点,只要一按check必然会来到此处,后续的也会从这里开始,一切就会光明无比

方法二 
当我们面对一个很庞杂的系统时我们又该如何来找那关键的消息处理函数呢?茫茫多的程序中又如何去发现
cmp eax,111 与cmp eax,1呢
回到前题,我觉得消息处理函数无论他在那里,当他被调用时,栈中的内容必然是
{
返回地址
hwnd
message
wParam
lParam
}只要我们能抓住他时,我觉得我们就能抓住一切。

首先当我们无法找到消息处理函数时,也许代码太多我们遗漏了,也许有别的技巧可以隐藏。但是我们可以先F9运行起来,在查看->窗口中,我们选择他们的共有父窗口,点击跟随ClassProc

////////////////////////////////

关于为什么在ClassProc上下断点

引用msdn上对DefDlgProc的描述:

The DefDlgProc function is the window procedure for the predefined class of dialog box. This procedure provides internal processing for the dialog box by forwarding messages to the dialog box procedure and carrying out default processing for any messages that the dialog box procedure returns as FALSE. Applications that create custom window procedures for their custom dialog boxes often use DefDlgProc instead of the DefWindowProc function to carry out default message processing.

当对话框有消息时,消息会先进入DefDlgProc 然后由他传递给自定义的对话框处理函数 如果对话框处理函数返回FALSE,DefDlgProc接着进行默认处理

这也就解释了为什么在DefDlgProc上下WM_COMMAND断点 F9之后会进入自定义对话框处理函数(分布在代码段上),所以在代码段上下内存断点会直接停下来


然后我们进入了系统领空,然后在第一句上下条件断点:
[ESP+8]==WM_COMMAND&&[ESP+c]==1

然后我们在对话框中输入数据,点击check,我们发现我们会中断在系统领空,并且注意观察栈


大家都明白了吧,然后在查看->内存,代码段下内存访问断点,F9运行下,直接到达消息处理函数

这时我们这需要静静的F8一路跟踪就可以了

个人总结,记住[ESP+8]==WM_COMMAND&&[ESP+c]==按钮ID

OD消息断点的更多相关文章

  1. 零基础逆向工程30_Win32_04_资源文件_消息断点

    1 资源文件,创建对话框 详细步骤: 1.创建一个空的Win32应用程序 2.在VC6中新增资源 File -> New -> Resource Script 创建成功后会新增2个文件:x ...

  2. OD常用断点

    OD常用断点 很全很全 常用断点 拦截窗口: bp CreateWindow 创建窗口 bp CreateWindowEx(A) 创建窗口 bp ShowWindow 显示窗口 bp UpdateWi ...

  3. OD常用断点之CC断点

    在做Windows平台软件逆向时,Ollydbg是极其常用的逆向工具,动态调试功能非常强大.在调试过程中,断点的使用有助于确定关键的破解位置,今天讲解的内容是OD常用断点中的CC断点. CC断点有很多 ...

  4. OD断点操作

    原文链接:https://www.cnblogs.com/qiyeboy/p/6815988.html 在做Windows平台软件逆向时,Ollydbg是极其常用的逆向工具,动态调试功能非常强大.在调 ...

  5. OD使用经验【转载】

    文章整理发布:黑客风云  1.我的os是winXP,无法使用trw2000,而softice装了多次均未成功,还蓝屏死机多次.郁闷. 2.友好的gui界面,不像softice.可以边干活边听歌,不像s ...

  6. 32位汇编第五讲,逆向实战干货,(OD)快速定位扫雷内存.

    32位第五讲,逆向实战干货,快速定位扫雷内存. 首先,在逆向之前,大家先对OD有一个认识. 一丶OD的使用 标号1: 反汇编窗口 (显示代码的地址,二进制指令,汇编代码,注释) 标号2: 寄存器窗口( ...

  7. ABAP断点调试

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  8. OD: Vulnerabilities Analyze Skills

    第五篇了,漏洞分析案例 漏洞利用的灵活程度让这门技术变得似乎没有什么原则可言,只有实践后总结提高才能挥洒自如. 漏洞分析方法 目标:弄清攻击原理.评估潜在利用方式及风险等级.扎实的漏洞利用技术是进行漏 ...

  9. 强大反调试cm的奇葩破解

    系统 : Windows xp 程序 : Crackme-xp 程序下载地址 :http://pan.baidu.com/s/1slUwmVr 要求 : 编写注册机 使用工具 : OD & I ...

随机推荐

  1. sh_08_打印分隔线

    sh_08_打印分隔线 def print_line(char, times): print(char * times) print_line("hi ", 40)

  2. promql 常用函数介绍

    Metrics类型 根据不同监控指标之间的差异,Prometheus定义了4中不同的指标类型(metric type):Counter(计数器).Gauge(仪表盘).Histogram(直方图).S ...

  3. Apache配置详解(最好的APACHE配置教程)

    From: http://aiks.blog.com.cn/archives/2006/1748482.shtml Apache的配置 Apache的配置由httpd.conf文件配置,因此下面的配置 ...

  4. java 用redisTemplate 的 Operations存取list集合

    一 .存取为list类型 @RestController @RequestMapping("/test") @Slf4j public class TestController { ...

  5. Linux shell - shift命令用法(转载)

    位置参数可以用shift命令左移.比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1.$2.$3丢弃,$0不移动.不带参数的shift命令相当于shift 1. 非常 ...

  6. 题目1.A乘以B

    看我没骗你吧 —— 这是一道你可以在10秒内完成的题:给定两个绝对值不超过100的整数A和B,输出A乘以B的值. 1实验代码 #include<stdio.h>int main(void) ...

  7. 一、基础篇--1.1Java基础-面向对象的特征

    面向对象的特征 封装.继承和多态 https://blog.csdn.net/jianyuerensheng/article/details/51602015 封装: 定义:封装就是将数据或函数等集合 ...

  8. ls -i

    ls的不同选项有不同的含义: -l 是用long的长格式显示 条目信息 -a 显示所有的文件, 包括隐藏文件 -i: 是显示inode, 主要是用来查看硬链接的

  9. 用Vue来实现音乐播放器(四十):歌单详情页布局以及Vuex实现路由数据通讯

    1.歌单详情页是推荐页面的二级路由页面 将推荐页面歌单的数据传到歌曲详情页面  利用vuex 1.首先在state下定义一个歌单对象 disc{} 2.在mutaions-types中  定义一个别名 ...

  10. 用Vue来实现音乐播放器(二十一):歌手详情数据抓取

    第一步:在api文件夹下的singer.js中抛出getSingerDetail方法 第二步:在singer-detail.vue组件中引入api文件夹下的singer.js和config.js 第三 ...