东欧赌场
东欧赌场 关于我们 业务领域 新闻中心 在线留言 联系我们
 

联系我们

网址: 东欧赌场

地址: 东莞市高埗镇振兴北路华宏西街1号

 

一、 Windows消息机制流程




作者:东欧赌场     发布时间:2020-11-11 14:07

  找到偏移之后,就是写辅助工具了。这一篇聊聊写辅助工具的原理。具体的代码细节,等到实战会展开细说。

  windows系统提供了接口(CreateRemoteThread),允许一个软件调用另一个软件的功能。

  windows系统提供了接口(ReadProcessMemory),允许一个软件获取另一个软件的数据。

  windows系统提供了调试机制,就是在目标软件设置陷阱,当软件触发到陷阱,会暂停下并且抛出报错信息

  内核调试:采用硬件调试器;bain写用于调用调试的驱动程序和中断处理函数;微软在windows内核中添加了支持调试的相关服务(主要)。

  单步压缩壳:地址有很大变动;遇到向上跳的是坑,f4跳过,直接下一条;入口点一般是push ebp或pop;找到入口点,直接右键OD默认脱;验证是否成功,peid先看看是否显示语言,再运行下

  程序插桩技术是在被测程序中插入探针,然后通过探针的执行来获得程序的控制流和数据流信息,以此来实现测试的目的;

  病毒只添有一个代码节,无法调用API函数,所以应先知道dll中API函数地址,

  大多教程说了找功能的具体过程,但没说为什么要这么找。导致自己找新的功能时,容易不知道怎么下手。

  也没找到把逆向分析这事说明白的资料,只能自己搜集零碎的信息,慢慢形成对逆向分析的整体认知 。

  学习过程,也加入一些逆向的圈子。接触下来,交流的氛围不太理想。小白能百度的不百度,只会伸手要;大佬能分享的不分享,大多是炫耀。结果就是每个人花很多时间找相同的功能。

  接触逆向有段时间了,整理整理,把逆向这事理清楚,希望对后来者有所帮忙。会从原理说起,对逆向分析有个全局的认知。也会聊下找新功能的常用方法,这样自己找新功能的时候能有思路。最后会给出几个实战的过程,理论结合实践。

  PS:一开始说的是理论的,会比较枯燥,但能打好基础。文章也是环环相扣的,建议看仔细点。

  消息系统对于一个Windows程序来说十分重要,它是一个程序运行的动力源泉。一个消息,是系统定义的一个32位的值,他唯一的定义了一个事件。消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型以及其他信息。例如,对于单击鼠标所产生的消息来说,这个记录中包含了单击鼠标时的坐标。这个记录类型叫做MSG,MSG含有来自windows应用程序消息队列的消息信息,它在Windows中声明如下:

  窗口消息是系统中最为常见的消息,它是指由操作系统和控制其他窗口的窗口所使用的消息。例如CreateWindow、DestroyWindow和MoveWindow等都会激发窗口消息。命令消息是一种特殊的窗口消息,他用来处理从一个窗口发送到另一个窗口的用户请求,例如按下一个按钮,他就会向主窗口发送一个命令消息。控件通知消息,是指一个窗口内的子控件发生了一些事情,需要通知父窗口。通知消息只适用于标准的窗口控件如按钮、列表框、组合框、编辑框,以及Windows公共控件如树状视图、列表视图等。例如,单击或双击一个控件、在控件中选择部分文本、操作控件的滚动条都会产生通知消息。其中窗口消息及控件通知消息主要由窗口类即直接或间接由CWND类派生类处理。相对窗口消息及控件通知消息而言,命令消息的处理对象范围就广得多,它不仅可以由窗口类处理,还可以由文档类,文档模板类及应用类所处理。其中,消息用消息标识符进行区分。

  从消息的发送途径来看,消息可以分成2种:队列消息和非队列消息,队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。从处理方式来看,消息队队列可以分成系统消息队列和线程消息队列。系统消息队列由Windows维护,线程消息队列则由每个GUI线程自己进行维护,为避免给non-GUI现成创建消息队列,所有线程产生时并没有消息队列,仅当线程第一次调用GDI函数时系统才给线程创建一个消息队列。

  ATOM WINAPI RegisterClass( _In_ const WNDCLASS *lpWndClass); //lpWndClass 指向一个 WNDCLASS 结构的指针

  窗口创建用到的函数理所是CreateWindow()或CreatewindowEx。这个函数是基于窗口类的,所以还需要指定几个参数来制定特定的窗口。而且像一些不带边框的窗口是怎么创建的也是具有相当的技巧的,就是创建的是不带标题和边框的窗口,然后自己在客户区绘制程序的内容,能够制作个性化的应用程序。函数原型如下,注意函数返回值为创建窗体的句柄,这一点需格外关注。

  消息队列。在发生输入事件之后,Windows将事件转换为一个消息并将消息放入程序的消息队列中。程序通过执行一块称之为消息循环的程序代码从消息队列中取出消息。具体执行流程分为三步:消息的发送、消息的接收以及消息的处理。

  消息的发送有3种方式:发送、寄送和广播。发送消息的函数有SendMessage、SendMessageCallback、SendNotifyMessage、SendMessageTimeout;寄送消息的函数主要有PostMessage、PostThreadMessage、PostQuitMessage;广播消息的函数我知道的只有BroadcastSystemMessage、BroadcastSystemMessageEx。其中 SendMessage主要是向一个或多个窗口发送一条消息,一直等到消息被处理之后才会返回。不过需要注意的是,如果接收消息的窗口是同一个应用程序的一部分,那么这个窗口的窗口函数就被作为一个子程序马上被调用;如果接收消息的窗口是被另外的线程所创建的,那么窗口系统就切换到相应的线程并且调用相应的窗口函数,这条消息不会被放进目标应用程序队列中。函数的返回值是由接收消息的窗口的窗口函数返回,返回的值取决于被发送的消息。 PostMessage则把一条消息放置到创建hWnd窗口的线程的消息队列中,该函数不等消息被处理就马上将控制返回。

  消息的接收主要有3个函数:GetMessage、PeekMessage、WaitMessage。其中GetMessage是从调用线程的消息队列里取得一个消息并将其放于指定的结构。此函数可取得与指定窗口联系的消息和由PostThreadMessage寄送的线程消息。此函数接收一定范围的消息值。GetMessage不接收属于其他线程或应用程序的消息。获取消息成功后,线程将从消息队列中删除该消息。函数会一直等待直到有消息到来才有返回值PeekMessage与GetMessage功能类似,不同之处在于GetMessage不将控制传回给程序,直到从程序的消息队列中取得消息,但是PeekMessage总是立刻传回,而不论一个消息是否出现。WaitMessage功能为线程的消息队列中无其它消息时,该函数就将控制权交给另外的线程,同时将该应用程序挂起,直到一个新的消息被放入应用程序的队列之中才返回。

  while(GetMessage(&msg, NULL, 0, 0)) { if(!TranslateAccelerator(msg.hWnd, hAccelTable, &msg)) { TranslateMessage( DispatchMessage( } }

  首先,GetMessage从进程的主线程的消息队列中获取一个消息并将它复制到MSG结构,如果队列中没有消息,则GetMessage函数将等待一个消息的到来以后才返回。如果将一个窗口句柄作为第二个参数传入GetMessage,那么只有指定窗口的的消息可以从队列中获得。GetMessage也可以从消息队列中过滤消息只接受消息队列中落在范围内的消息。这时候就要利用GetMessage/PeekMessage指定一个消息过滤器。这个过滤器是一个消息标识符的范围或者是一个窗体句柄,或者两者同时指定。当应用程序要查找一个后入消息队列的消息是很有用。WM_KEYFIRST 和 WM_KEYLAST 常量用于接受所有的键盘消息。 WM_MOUSEFIRST 和 WM_MOUSELAST 常量用于接受所有的鼠标消息。然后TranslateAccelerator判断该消息是不是一个按键消息并且是一个加速键消息,如果是,则该函数将把几个按键消息转换成一个加速键消息传递给窗口的回调函数。处理了加速键之后,函数TranslateMessage将把两个按键消息WM_KEYDOWN和WM_KEYUP转换成一个 WM_CHAR,不过需要注意的是,消息WM_KEYDOWN,WM_KEYUP仍然将传递给窗口的回调函数。处理完之后,DispatchMessage函数将把此消息发送给该消息指定的窗口中已设定的回调函数。如果消息是WM_QUIT,则 GetMessage返回0,从而退出循环体。应用程序可以使用PostQuitMessage来结束自己的消息循环。通常在主窗口的 WM_DESTROY消息中调用。通过DispatchMessage函数即将WNDCLASS中的窗体过程函数关联起来。

  窗体过程函数是一个用于处理所有发送到这个窗口的消息的函数。任何一个窗口类都有一个窗口过程。同一个类或一个父类的窗口使用同样的窗口过程来响应消息。系统发送消息给窗口过程将消息数据作为参数传递给他,消息到来之后,按照消息类型排序进行处理,其中的参数则用来区分不同的消息,窗口过程使用参数产生合适行为。一个窗口过程不经常忽略消息,如果他不处理,它会将消息传回到执行默认的处理。窗口过程通过调用

  DefWindowProc来做这个处理。窗口过程被所有属于同一个类的窗口共享,能为不同的窗口处理消息。通常窗口过程函数是通过一个switch语句来实现的,利用HANDLE_MSG消息分流器则可以把switch语句分成更小的函数,每一个消息都对应一个小函数,这样做的好处就是对消息更容易管理。

  观察两个RegisterClass函数中WNDCLASS结构体,发现三个窗体的窗体过程函数的地址均为0X77782280,且该代码位于系统代码段内(ntdll.dll中),与直观认识不符,这个是为什么呢?首先解决第一个问题,即两个窗体注册函数的窗体过程函数为什么一样,这是因为一个窗口类只有一个窗口函数,所有使用该窗口类创建的窗口都是使用同一个窗口函数,除非后来用SetWindowLong改变了窗口函数。查看窗口如下,可以看到窗口均是使用WTWindow创建的。

  LONG DispatchMessage(CONST MSG*lpmsg) //lpmsg:指向含有消息的MSG结构的指针。

  由MSG结构可知,第一个四字节为窗体句柄,第二个四字节为消息标识符,查看数据段可知,句柄为0X371394,与预期相符;消息标识符为0X202。查表可知,0X202表示按钮松开消息,与操作符合。考虑到该CM的触发条件为按钮,因此可以在此设立条件断点:

  以上均是常规分析,现在重点来了,如何定位真正的窗体处理函数用以破解该CM?

  解决这个问题的关键就在于CallWindowProc函数,WNDCLASS结构体中的地址其实只是一个跳转地址,程序是通过CallWindowProc函数调用窗体过程函数。CallWindowProc是将消息信息传送给指定的窗口过程的函数。使用函数CallWindowsProc可进行窗口子分类。通常来说,同一类的所有窗口共享一个窗口过程。子类是一个窗口或者相同类的一套窗口,在其消息被传送到该类的窗口过程之前,这些消息是由另一个窗口过程进行解释和处理的。CallWindowProc函数原型如下:

  LRESULT CallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM IParam); //hWnd:指向接收消息的窗口过程的句柄。 //Msg:指定消息类型。 //wParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。 //IParam:指定其余的、消息特定的信息。该参数的内容与Msg参数值有关。 //返回值:返回值指定了消息处理结果,它与发送的消息有关。

  既然如此,我们在回调函数地址0X77782280与CallWindowProc函数出均设置断点(也可以利用DefWindowProc设置断点,方法类似,但断点条件不一样),当消息标识符为0X202时激活这两个断点(CallWindowProc调用位置较多,需判断哪个才是需要的),利用Run逐步跟踪,记录两个断点内执行过程。结果共计1568条汇编代码。按照正序分析,重点关注应用程序段代码的起始位置代码:

  这个结构有没有很熟悉,有没有豁然开朗的感觉?下面来逐个解释。DefWindowProc函数是调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理,确保每一个消息得到处理。CWnd是MFC窗口类的基类,提供了微软基础类库中所有窗口类的基本功能。我们在0X45AB89处设端点,当消息标识符为0X202触发。

  afxMapHWND是用于保存CWnd类和HWND之间的映射。在Windows体系中,很多对象都是以句柄的形式展示给开发人员的。比如窗口句柄(HWND),绘图设备(HDC)等等。然后大部分的API函数则围绕 这些句柄做文章。比如ShowWindow,SetWindowText, TextOut等等。这些API函数的第一个参数通常就是句柄了。但是在C++ 体系中,这种对于事物细节的访问,往往是有违其封装精神的。因此MFC做了很多的封装类,来隐藏这些细节。应运而生就是CWnd,CDC等类。通过这些类暴露的方法,可以直接对句柄做操作,而又可以不去关心他。MFC中有大量的全局变量,其中一个全局变量是一张HWND与CWnd的Map表。MFC提供了全局函数afxMapHWND用于获得这个Map表。虽然在MFC中,都是对象在与对象打交道。但是MFC也要与Windows系统打交道。Windows给你的只有句柄,那么如何通过这些句柄找到相对应的类呢?通过Map表就能轻松的解决这个问题。比如在Windows的消息机制中,当WndProc接收到一个消息的时候,只会得到一个HWND hWnd的目标窗口,如何找到匹配的类?从m_pmapHWND中搜索就行了。通过调用CWnd的静态成员函数FromHandlePermanent,我们就能轻松的从Map表中找到与hWnd相对应的CWnd类。FromHandlePermanent的实现也非常简单。首先通过afxMapHWND找到m_pmapHWND,然后通过m_pmapHWND的成员函数LookupPermanent查找与hWnd对应的CWnd指针,最后返回他。CMapPtrToPtr::GetValueAt则用于获取具体值。

  /工具 /虚拟机 /汇编 /vmware /tree 8022  对于软件

  ,有称手的工具往往事半功倍,这里简单罗列出一些常用工具,不做详细介绍,供新手一个入门指引。  静态

  逆向工程(又称逆向技术),是一种产品设计技术再现过程,即对一项目标产品进行

  及研究,以反汇编阅读源码 的方式去推断其数据结构、技术实现流程。特别是当手里没有合适的文档资料,而你又很需要实现某个...

  经典的游戏扫雷,再通过Cheat Engine工具复制内存地址获取,实现一个自动扫雷程序。基础性文章,西电UI您...

  工程(reverse engineering),主要是通过一系列的技术、方法,将 已经成功编译好的程序的逻辑还原出来,从而了解该程序基本原理。了解了基本 原理后,其后续用途就比较多样化了,根据目的不同包括: 1:仿制或...

  ,用Python代码模拟了AES和RSA加密过程,并在文章的末尾提供了一些参数,可以用这些参数来获取歌曲对应的歌词及用户的评论。

  工程核心原理》的笔记重新实现整理一遍,代码重新编写实现,以方便以后查阅。 编写运行HelloWorld程序 环境主要是Win7 32位系统,使用VS2010进行编程: #include

  DLL基础 (一) 相关名词 简写 全称 DLL Dynamic Link Library PE Portable Executable COM Component Object Model COFF Common Object File Format ...在powershell查看可执行后...

  API 函数学习环境的搭建 C/C++编程:推荐VS系列 中文编程:易语言 谷歌浏览器 MSDN 什么是

  分享一下我老师大神的人工智能教程!零基础,通俗易懂!也欢迎大家转载本篇...分享知识,造福人民,实现我们中华民族伟大复兴!... 2.1

  前言 Dalvik基础 指令 文中42页详细介绍了V P两种命名法如下 文中43页详细介绍了Smali中的基本数据类型 而且这里介绍了三个知识点 文中45页 详细介绍了Dalvik指令的特点 关于数据指定指令 ...书中47页介绍到一个比较...

  注意,压缩包内附带光盘内容可能会被杀软隔离,请决定后再下载 本书既是一本全面而系统地讲解反汇编与

  技术的安全类专著,又是一部深刻揭示C++内部工作机制的程序设计类著作。理论与实践并重,理论部分系统地...

  为切入点,讲述了软件安全领域相关的基础知识和技能,可以说是安全人士必读书籍之一了。《加密与解密》(第四版)国庆后将出版上市,...

  法  搜索字符串Hello World并进入,跳转到上层函数(信息窗口),寻找标志:函数参数(main函数后两个参数是指针),exit等。 2、API下断栈回溯法  找到main函数中的Hello World并...

东欧赌场



  • 上一篇:区域管理
  • 下一篇:radare2逆向学习笔记
  •  
    24小时咨询热线:
    东欧赌场 关于我们 业务领域 新闻中心 在线留言 联系我们 网站地图
     
     
    手机:  地址:东莞市高埗镇振兴北路华宏西街1号
    ©2018 东莞市天发物流公司 版权所有京ICP备10013901号