Win32简单图形界面程序逆向

  • 前言

    • 为了了解与学习底层知识,从 汇编开始 -> C语言 -> C++ -> PE文件 ,直至今天的Win32 API,着实学的令我头皮发麻(笑哭)。
    • 就在昨天的课程中,老师布置了一个作业:逆向一个简单的Win32程序。
    • 本着总结与分享知识的心态,便有了这篇文章,希望能够帮到大家。
  • 本文章所逆向的Win32程序:https://files.cnblogs.com/files/02SWD/ReverseTraining_1.rar?t=1663236309

1 首先介绍一下这个win32程序

1.1 简单介绍

  1. 该程序是经 release版本 进行编译的。

  2. 打开该程序之后,使用 鼠标左键 点击窗口,会弹出标题和内容均为 1 的窗口;使用 鼠标右键 点击窗口,会弹出标题和内容均为 2 的窗口。

  3. 打开该程序之后,选中窗口,当我们按下正确的键盘按键时,会弹出该按键的键盘码,否则便会弹出Error窗口。正确的键盘码有3个。下图以其中一个按键“A”为例,请找出剩余的2个(当然你要是一个个试那就没意思了)

1.2 逆向目标任务

  1. 通过逆向,找到该程序的窗口回调函数对鼠标左/右键进行处理的代码。
  2. 通过逆向,找到另外2个正确的键盘按键。

2 “窗口回调函数WindowProc()”的定位思路

2.1 逆向思路剖析

  • 要想完成上面的2个目标,我们要做的第一件事就是:定位“窗口消息处理程序(窗口回调函数)”的位置,而若想定位“窗口回调函数”,我们就需要知道该函数的函数地址,那么我们要如何得知该函数的函数地址呢
  • 我们知道:“窗口回调函数”的函数地址保存在一个名为 WNDCLASS结构体lpfnWndProc属性 中,找到了该结构体就等于找到了回调函数,那么我们如何定位WNDCLASS结构体呢
  • 我们可以从RegisterClass()函数入手,WNDCLASS结构体的首地址是RegisterClass()函数的参数。那这就意味着:如果我们找到了RegisterClass()函数,就相当于找到了WNDCLASS结构体的首地址,那么我们又如何定位RegisterClass()函数的位置呢
  • 由于在这个程序中,RegisterClass()函数是由WinMain()函数所调用的,所以我们只要找到WinMain()函数,就自然而然的可以定位RegisterClass()函数了。
  • WinMain()函数就是win32应用程序的入口函数。

2.2 逆向思维概括

  • 定位WinMain()函数 -> 定位RegisterClass()函数 -> 定位WNDCLASS结构体 -> 得知窗口回调函数的函数地址,以致定位到回调函数的代码

3 定位回调函数的具体操作

3.1 步骤1:定位WinMain()函数

  • 先将待逆向程序拖入OD,此时要注意:

    • 现在的代码所停的位置并不是WinMain()函数的入口点,而是WinMain()函数的 父函数的 入口点,那我们该如何定位WinMain()函数呢?
  • 首先我们要清楚 WinMain()函数的必要特点
    • 第一个参数为 hInstance(代表的是该应用程序的imageBase)
    • 该函数的调用约定为 __stdcall(即:参数的压栈顺序为:从右至左,平栈方式为内平栈)
  • 这就意味着,hInstance参数是最后一个被压栈的,即 在call WinMain指令位置的上方一定会有一个instance参数的压栈
  • 并且 由于WinMain()函数的参数有4个,那么在 内平栈 时,应该使用指令:retn 0x10
  • 定位过程如下图:

3.2 步骤2:定位RegisterClass()函数

  • 该函数比较好定位:当我们进入WinMain函数后,向下寻找,根据OD给我们提供的注释,可以轻松的找到:WinMain函数 在0x401055位置处执行了call指令,调用了RegisterClass()函数

3.3 步骤3:定位WNDCLASS结构体

  • 在步骤3我们成功定位了WinMain函数调用RegisterClass函数的位置,由此我们便可以轻松的找到 RegisterClass函数的参数
  • 0x401050位置处的指令 便为RegisterClass()函数的 传参指令,而 eax寄存器 中存储的便是 WNDCLASS结构体的地址

3.4 步骤4:获得“窗口回调函数”的函数地址,以致定位其代码

  • 由步骤3我们已经知道 WNDCLASS结构体的数据。根据该结构体的定义,我们可以得知 WNDCLASS结构体的第二个属性 存储的便是 “窗口回调函数”的函数地址,跟进该地址,我们便可以找到回调函数的代码。(WNDCLASS结构体的定义可以通过MSDN查询得知)

4 “窗口回调函数”代码分析的具体操作

4.1 目标1:找到该程序对鼠标左/右键进行处理的代码

  • 定位程序对于鼠标左键的处理代码,过程如下图:

  • 定位程序对于鼠标右键的处理代码,过程如下图:

4.2 目标2:找到另外2个正确的键盘按键

  • 分析过程如下图:

4.3 在这里,对上述分析过程做一个简要说明

  • 对于回调函数WindowProc的参数做一个简单说明,详情可在MSDN中查询:
    LRESULT CALLBACK WindowProc(
    IN HWND hwnd,
    IN UINT uMsg,
    IN WPARAM wParam,
    IN LPARAM lParam
    ){...}
    • 当在窗口中按下 鼠标左键 时,该函数的 uMsg参数 会被赋值为 0x0201
    • 当在窗口中按下 鼠标右键 时,该函数的 uMsg参数 会被赋值为 0x0204
    • 当在窗口中按下 键盘按键 时,该函数的 uMsg参数 会被赋值为 0x0100wParam参数 会被赋值为 按键对应的键盘码

  • 对于 0x4010F0位置处 的汇编指令:mov eax,dword ptr ss:[esp+0x8],ss:[esp+0x8]中存储的是什么?或者说它指的是什么?
  • 对于 0x401120位置处 的汇编指令:mov eax,dword ptr ss:[esp+0x30],ss:[esp+0x30]中存储的是什么?或者说它指的是什么?
    • 答:首先我们要知道,本次分析的程序是 release版 的,也就是说此时 对于参数和局部变量 所采用的 寻址方式 不再是 ebp寻址,而是 __esp寻址__了。相比于ebp寻址,esp寻址分析起来会比较的麻烦,因为 esp的值是会不断发生变化的

    • 0x4010F0位置处的汇编指令:mov eax,dword ptr ss:[esp+0x8] 汇编指令分析

    • 0x401120位置处的汇编指令:mov eax,dword ptr ss:[esp+0x30]汇编指令分析

Win32简单图形界面程序逆向的更多相关文章

  1. 2018-09-28 用Python3和tkinter开发简单图形界面程序

    源码库: program-in-chinese/wubi_code_editor 起因在这里. 由于此项目和汉字相关, 个人也想尝试Python的图形界面开发, 于是开始尝试. 遇到的一个坑. 用户测 ...

  2. 在桌面Linux环境下开发图形界面程序的方案对比

    在Linux下开发GUI程序的方法有很多,比如Gnome桌面使用GTK+作为默认的图形界面库,KDE桌面使用Qt作为默认的图形界面库,wxWidgets则是另一个使用广泛的图形库,此外使用Java中的 ...

  3. linux启动后自动登录并运行自定义图形界面程序

    在<Ubuntu CTRL+ALT+F1~F6 进入命令模式后不支持中文显示的解决办法>一文中提到linux启动在以后运行一个独占显示器的图形程序的两种办法. 1.不启动xserver,使 ...

  4. 在ubuntu上使用wxWidgets成功开发一个图形界面程序

    编译wxWidgets 下载最新版的源码,wxWidgets-3.0.2.wxWidgets在liunx是通过wxGTK实现的.wxGTK和wxWidgets的源码打包在一起.wxGTK依赖GTK+, ...

  5. Quartz(GUI)图形界面程序----Quartz Web

    下载.设置和运行Quartz(GUI)图形界面程序----Quartz Web 一.获取Quartz Web程序(Quartz GUI).早期的 Quartz 框架开发者意识到一个 GUI 对于某类用 ...

  6. Python编写的桌面图形界面程序实现更新检测和下载安装

    在Python中我们有很多种方案来编写桌面图形用户界面程序,譬如内置的 Tkinter .强大的 PyQt5 和 PySide2 ,还有 wxPython .借助这些或内置或第三方的模块,我们可以轻松 ...

  7. 使用XMing+putty运行linux图形界面程序

    起因接下去的工作要作一些数值模拟,于是到师兄的工作站上开了个帐号.工作站运行的是RHEL4,要说远程SSH,就算是FTerm也足够胜任,不过,因为我要用的查看计算结果的软件需要使用图形界面,这一点就比 ...

  8. 第十五章 使用PyQt进行Python图形界面程序开发

    在基础知识部分的最后一章<第十三章 Python基础篇结束章>的<第13.3节 图形界面开发tkinter>简单介绍了Python内置图形界面标准库tkinter,当时特别强调 ...

  9. 使用PyQt进行Python图形界面程序开发文章目录

    ☞ ░ 前往老猿Python博文目录 ░ PyQt入门知识原来是作为老猿Python<Python基础教程目录>后的进阶学习章节存在,最近不少专栏作者提醒老猿整体的博文内容不错,但博文没有 ...

随机推荐

  1. 端口被占用的问题解决 Web server failed to start. Port ×× was already in use

    出现此问题是端口被占用了,只需要关闭正在使用的端口就行 解决思路: 1.在服务器中更改port端口号,改为不冲突,没有被占用的端口. 2.找出被占用的端口,结束被占用的端口 解决结束被占用的端口的方法 ...

  2. java常见的面试题(一)

    1.Collection 和 Collections 有什么区别? Collection 是一个集合接口(集合类的一个顶级接口).它提供了对集合对象进行基本操作的通用接口方法.Collection接口 ...

  3. 6 分钟看完 BGP 协议。

    上一篇文章见 万字长文爆肝路由协议! 上面我们聊 RIP .OSPF 协议都是基于 AS 即自治系统内的协议,可以把它们认为是域内路由协议:而下面我们要聊的就是 AS 之间的协议了,这也叫做域间路由协 ...

  4. 《AlignedReID:Surpassing Human-Level Performance in Person Re-Identification》理解

  5. Cisco Packet Tracer Student(思科网络模拟器)模拟集线器和嗅探攻击

    一.集线器简介 集线器是局域网内的基础设备,工作于OSI中的物理层,作用是将接收的信号进行放大再传输,集线器是纯硬件设施,集线器开发之初就没考虑过软件层面的操作,所以不具备像路由器.交换机等设备那样具 ...

  6. Tomcat介绍和配置使用

    目录 JavaWeb 的概念 什么是 JavaWeb? 什么是请求? 什么是响应? 请求和响应的关系 Web 资源的分类 常用的 Web 服务器 Tomcat 服务器和 Servlet 版本的对应关系 ...

  7. 什么是好的 API 设计?【eolink翻译】

    对于试图完善其 API 策略的团队来说,良好的 API 设计是一个经常出现的话题. API 设计的重要性相信不需要赘述,精心设计的 API 的好处包括:更好开发人员体验.更快的文档编制以及更高的 AP ...

  8. postgres备份与恢复

    一  利用pgAdmin工具进行备份与恢复 pgAdmin是postgres官方的客户端管理工具,可以进行数据库的涉及与维护. 示例:以logs库为例记录操作       1)  右击需要备份的数据( ...

  9. CF1703A YES or YES? 题解

    题意:输入一个长度为 \(3\) 的字符串,判断其是否为 \(YES\),忽略大小写. 做法:输入字符串,直接判断. #include<cstdio> #include<iostre ...

  10. Ngnix初步学习

    Nginx下载与安装(Linux) nginx下载 1.root用户下进入/usr/local/src su root cd /usr/local/src 2.下载nginx所需包 # nginx w ...