OllyDbg学习---深入理解消息驱动原理(2)

本文详细解析了Windows消息循环的工作原理,介绍了消息循环中关键函数如GetMessage、TranslateMessage和DispatchMessage的作用,以及如何通过消息机制建立子窗口与主窗口之间的联系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://blog.sina.com.cn/s/blog_61d65e360100lgtf.html

    笔者先要申明,这节知识都是笔者根据自己的知识积累和观察做出的猜测。既然是猜测,那么肯定有不准确的地方。不过笔者还是对自己的推论和猜测很有信心。同时感谢我的搭档刘飞,关于这节内容,我们俩经过了比较深入的讨论,最后一致感觉就现在的想法比较的合理,比较的说得通。因此我写出来与大家分享。


    Windows内核是靠IRP来驱动,而Windows窗口应用程序靠的就是消息来驱动。所谓的消息驱动其意思就是靠消息作为纽带来运作。

    需要注意的是,一个窗口只能对应一个线程,用VC编写过应用程序的读者肯定对消息循环的while语句再熟悉不过,这个循环语句其实就是个死循环,这样这个窗口线程永远不会退出除非接收到WM_QUIT消息。

    这里涉及到几个和消息有关的函数,分别是GetMessage,TranslateMessage,DispatchMessage

    另外涉及几个和默认窗口过程有关的函数,分别是DefDlgProcA,DefWindowProc,DefMDIChildProc,DefFrameProc

    现在读者肯定迫不及待的会问,这节和OD的学习有必然联系么?!!我很负责的告诉你,有!因为OD中会涉及到下消息断点。我们必须了解消息驱动原理。不然,笔者绝对相信你会很茫然看到突然中断到一个陌生的地方,而这个地方的代码你完全不晓得是干什么的。

    我们开始。我们运行一个程序,最外面的大框架是一个窗口,其内部的按钮,文本框等等也都是窗口。需要注意的是,我们最熟悉不过的那个最外层窗口有消息循环。内部的按钮,文本框却没有消息循环!也就是说,最外层的窗口对应一个线程,而里面的按钮,文本框等等所有的“子窗口”都不会有线程与其对应,这些“子窗口”对应的回调函数将来都运行在“父窗口”的线程上下文中,定位更准确点的话应该说是运行在DispatchMessage函数上下文中。

    笔者先来描述下关于消息的整个过程。

    1,每个窗口都会对应一个线程,并且一个线程有且只能和一个窗口绑定,如果某个线程和窗口进行绑定,那么系统就再会为这个线程准备一个消息队列。如果此线程没有和窗口绑定,那么就是一个普通的线程,系统也不会多此一举为他加上消息列队

    2,系统会维护一种信息,此信息记录了屏幕上所有的窗口(包括按钮,文本框等等)的区域的坐标范围。并且还会为这些窗口编上号,这些编号就是窗口句柄。需要注意的是,句柄这个东西没有准确的定义,根据情况的不同而不同,具体我下一节来介绍。拿鼠标为例,当你按下鼠标,系统就会捕获此时此刻鼠标被按下时的坐标,再查看鼠标指针坐标落在哪个窗口的区域范围内。这样一来系统就会知道哪个按钮被按下,同时系统会构建一个消息数据结构

     Type MSG
       hwnd As Long       这个里面的值就是此窗口的句柄(鼠标坐标落在其内)
       message As Long     此时此刻应该是 WM_LBUTTONDOWN
       lParam As Long    
       time As Long             
       pt As POINTAPI    坐标,就是鼠标被按下时指针的坐标
    End Type

 并且会把这个结构放入系统消息列队里。

   3,每个绑定了窗口的线程都会通过GetMessage函数从系统消息列队中取出消息,其判断依据就是窗口句柄和坐标,如果发现系统列队中某个消息的窗口句柄对应的窗口包含在自身范围内,那么就拿过来。如果不包含在自身内,那么就无视。

   4,TranslateMessage的作用是把接收过来的消息加工一下,比如说把WM_KEYDOWN和WM_KEYUP消息组合成一起称为WM_CHAR消息。

   5,接下来就是DispatchMessage函数,这个函数非常的重要,首先,和上面2个函数一样,他们都存在于USER32.DLL中。此函数会分析得到的消息的结构从而得到此结构第一个参数值(窗口句柄),并且调用此按钮的默认回调函数。说要说明的是,由于按钮,文本框等控件对于程序开发人员来说都是很常用的并且这些控件的功能往往是固定,不会有特别稀奇古怪的附加功能,因此这些控件的回调函数也就可以固定下来,微软想法和我一样,同时,微软为了节约程序员的负担干脆把这些回调函数封装起来并固定存放在USER32.DLL中。需要注意的是,这些函数是非导出函数,除非你用OD跟踪,不然你还确实无法知道此回调函数在哪。这当然是后话。

   6,从上面的描述你可以发现,像按钮这样的控件,其对应的回调函数已经固化在USER32.DLL中,那么DispatchMessage函数就去调用这个函数。

   7,我们还知道,其实按钮这些东西都是作为资源存在于PE结构中,就某个按钮而言,你在写程序的时候也仅仅描述了以下几个信息,首先是明确表示你描述的东东的确是个按钮,其次就是按钮的坐标,其他几乎没有做任何描述,你并没有告诉系统此按钮的回调函数。系统是这样工作的:当程序运行的时候,系统要分析PE结构里所有的资源,通过资源里的描述得到具体的信息,拿按钮资源为例,当系统通过PE得到这个按钮的信息之后就会在内核中构建这个按钮的内核对象,此内核对象里的某个成员变量就会指向USER32.DLL里的某个地址,这个地址就是按钮的默认回调函数的首地址,以上这个步骤是系统自动完成的。当然,此按钮的内核对象里还会包含其他一些信息,比如坐标,资源号什么的。也就是因为按钮的内核对象里包含了回调函数的首地址,所以DispatchMessage函数才能调用!不然DispatchMessage函数压根不会知道从哪获取按钮回调函数的首地址!


   8,你可以发现,当你下鼠标断点之后按F9,再尝试按下某个按钮后都会中断在USER32领空的某个代码处。你反汇编USER32后会发现这段代码并没有导出函数与其对应。所以可以判断按钮的默认回调函数的确没有被导出且确实存在于USER32库里。按钮的回调函数要做的是获得WM_LBUTTONDOWN消息并且分析之,随后生成WM_COMMAND消息(带上BN_CLICKED参数和本按钮的句柄)发送给主窗口的线程消息列队中,之后GetMessage得到这个WM_COMMAND消息并通过DispatchMessage函数调用主窗口的默认回调函数来处理这样一个消息,处理好了之后生成WM_COMMAND(带上按钮资源号)的消息再次发到主窗口的消息列队中。接下来DispatchMessage函数调用的将会是用户定义好了的窗口过程函数。这样一来按钮和主窗口的联系就建立了。

  好了,这就是消息循环的细节。下节开始介绍句柄。

后记:

子窗体和父窗体的关系:

子窗体被触发时,向父窗体发送一个WM_COMMAND消息,父窗体的窗口函数处理这个消息,进行 相关的处理。lParam表示子窗口句柄,LOWORD(wParam)表示子窗口ID,HIWORD (wParam)表示通知码(例如单击,双击,SETFOCUS等)。
程序名称:OllyDBG版 本:1.10汉 化 人:cao_cong联系方式:cao_cong_hx@yahoo.com.cn汉化日期:2005.11.28汉化说明: 本来是想等 OllyDBG 2.0 出来再汉化的,可看到dyk158兄弟的修改版说明中对我原来汉化版本的汉化质量提了一点小小的意见,想想也是,我原来的汉化版是OllyDBG 1.10 的最终版本刚出来时汉化的,距今已经一年多了也没有更新过,当时只顾不出因汉化造成的Bug,汉化嘛确实不咋的。看到BoOMBoX/TSRh2004他们制作的美化界面,确实也觉得漂亮,最后决定再出个汉化版本。这个版本的汉化加测试、修改花了我整整两个星期的业余时间,其中的非标字符对照文本有4000多行,看一遍都半天。这个版本中的所有翻译我都重新过了几遍,绝大部分都重新翻译过,力求做到准确,希望能给大家一个比较完美的汉化版本。在制作过程中参考了TT小组翻译的OllyDBG帮助及dyk158修改、聆风听雨汉化的ODbyDYK修改版,主要是想让翻译更准确一点,能让新手把汉化版和TT小组汉化的帮助文档对照起来学习。在此对以上提到的各位表示衷心的感谢! 这个软件汉化起来确实是个苦差事,不光是要翻译的资源多,还有一个重要的方面就是稍不留神就会出现汉化引起的Bug。经常是用原版来调试汉化版找问题,象原来菜单上的“&Window”汉化后会出错,还是调试后才知道原来它内部加载菜单时还有个这个“&Window”,只有两个都汉化才不会出错。另外其它的许多问题都只好靠调试来解决。原来汉化时又没有把要注意的地方写下来,这次光测试就花了好几天。 这个汉化版本除因汉化必要而打补丁外,我不准备再对它打任何补丁。一是我怕打补丁影响 OllyDBG 的兼容性;二是已经有Fly和dyk158他们做了,我想我自己再做的话也不会比他们做的更好;三是我实在是感到太累了!如果大家要想要修改的版本的话,推荐使用freecat兄弟制作的AutoPath,我把这个插件放在 FixOD 目录下,我把freecat兄弟发布时所用的说明也放在同一目录下,大家可以根据说明来使用这个插件改造你的OllyDBG。 在这里我要感谢看雪论坛上的看雪老大和论坛上各位兄弟的支持,正是有了他们的测试和建议,经过多次修正后,才有了今天的这个最终版本,由衷的感谢看雪论坛上的各位兄弟!汉化第二版主要更新:1、界面采用 BoOMBoX/TSRh2004 制作的美化界面,主要为了好看一点。2、绝大部分句子都重新翻译过,力求做到准确。3、配置文件中除字体、语法高亮、颜色这几个部分保留为中文外,其它的都恢复为英文。保留字体、语法高亮、颜色这几个部分为中文的目的是因为我发现若先运行过英文版配置好后,汉化版中对应这几个部分的一些菜单也会取原英文版配置中的英文字串,而不是汉化过的字串。我觉得翻译后既能保持与英文版的兼容性,又能让英文版与中文版的界面等互不干扰。4、dyk158 建议我把配置文件中的字体、语法高亮、颜色这几个部分恢复为英文,我专门做了个恢复为英文配置的补丁(如果你以前运行过英文版进行了相应配置,则补丁后的汉化版本对应这几个部分的相应菜单将会显示英文,若你是用打过这个补丁的汉化版本生成配置文件,则相应菜单将会显示中文)放在英文配置补丁目录下,需要字体、语法高亮、颜色这部分也用英文配置的朋友可以把这个补丁放到我做的汉化版的安装目录,选择 Ollydbg.exe 补丁就可以了。这个补丁同样适用于原版界面的汉化版本。5、上一版中部分未汉化的内容这次除了不能汉化的外,基本上都已汉化。6、另有一个界面未作美化的汉化版放在原版界面目录,可以按自己的喜好选择使用哪一个。7、FixOD 目录下放的是用 freecat 的 AutoPath.dll 打过补丁的 OllyDBG,使用前请先备份好你原来的Ollydbg.exe文件,再把这个目录下的Ollydbg.exe、AutoPath.dll、AutoPath.ini复制到你的OllyDBG安装目录下就可以了。在上一版的基础上,插件做了如下更新:1、脚本插件 ODbgScript.dll (v1.23 汉化版)2、快捷命令插件 CmdBar.dll (v3.10.109c 汉化版,这个版本有支持运行 OllyScript 脚本的命令:OSC)3、标签插件 Labeler.dll (v1.33.108 汉化版)4、图表插件 OllyFlow.dll (v0.71 汉化版,我从IDA中提取了个wingraph32.exe放在插件目录下,用于配合这个插件)5、断点管理 olly_bp_man.dll (汉化版,在我机器上不能用,放在备用目录)6、字串参考修改版本 ustrrefadd.dll (汉化版)另外还添加了dyk158 汉化的两个插件:1、脱壳插件 OllyDump.dll (V3.00.110 dyk158 汉化版)2、脱壳插件 pedumper.dll (v3.03 dyk158 汉化版) 推荐大家试用一下这两个插件:ApiBreak 插件,用于在对话框、字串、注册表、时间、内存等 API 函数上设置断点,还可设置万能断点,简单易用;GODUP 插件,包含 Map 载入器、资源查看器、进程查看器、IDA 签名载入程序及自带的一个记事本这五个工具。感觉它自带的记事本用来在调试时记一些东西比较方便。 如果你以前没用过OllyDBG的话,我要提醒你使用前先在菜单的 选项->界面->目录 中把插件和 UDD 的路径设置好,以免影响使用! 此汉化版中的插件除了一个 PuntosMagicos.dll 插件没汉化外(我实在是弄不懂是哪国语言),其它的插件都已汉化。目录下的OLLYDBG.HLP帮助文件是由TT小组翻译的中文帮助,在此对TT小组的辛勤劳动表示感谢!(OLLYDBG_EN.HLP为原版英文帮助)声明: 1.本汉化软件包内的所有英文及其他语言的源程序的版权归原作者(公司)所有。 2.本人不对使用本汉化软件造成的任何情况的损失负责。 3.本汉化软件仅供学习研究之用。严禁用于商业用途。本人不对使用本汉化软件造成的任何法律纠纷负责。 4.如果你对本汉化软件有什么建议请联系我。 5.请在转载时保留此汉化版的完整性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值