C/C++逆向:结构体逆向分析

在C/C++程序的逆向分析中,结构体的逆向分析是非常重要的。结构体是C/C++中管理和组织数据的一种主要方式。了解它们的布局可以帮助你理解程序是如何存储、处理和传递数据的,结构体常用于组织和管理复杂的数据,理解结构体有助于我们更好地还原程序的逻辑、推断数据布局,并解读与操作这些数据的函数。因此,识别并分析结构体可以帮助你更全面地理解程序的内存布局和数据流。接着我们可以来简单说一下如何识别结构体。

分析结构体内存访问模式

程序中对内存的访问偏移往往可以透露结构体的布局。我们可以通过以下几点来进行观察:

连续的偏移访问:当看到对一个地址的多次访问,每次访问的偏移不同(如 mov eax, [ebp-4] 后有 mov ecx, [eax+8]),这可能表明该地址处是一个结构体。

结构化的读取或写入:如果某个地址以特定偏移的方式反复读取或写入,通常意味着这是一个结构体或数组。

从汇编的角度,数组是一种简单的、线性连续存储的同类型元素集合,访问方式直接、计算简单。结构体则是一个包含不同类型成员的复杂数据类型,访问时需要考虑填充字节和成员的具体偏移,访问方式相对复杂(内存对齐相关文章可以看笔者前面的文章《C-结构体对齐》)。理解这些区别有助于更好地进行逆向分析和性能优化;数组和结构体的区别可以通过动态分析观察内存结构从而进一步识别。
推测成员类型

在大概分析完内存布局的基础上,再通过观察程序中访问结构体成员的方式,可以大概区分结构体和数组的区别以及推测成员的类型:

①整数或指针:如果使用32位或64位指令(如 mov),并且偏移量是4或8的倍数,这通常意味着访问的是整数或指针。
②字符串或字符数组:当使用指针偏移方式(如 mov eax, [ebx+4] 后的 mov byte ptr [eax], 'A')并且访问的是一个字节时,可能是字符或字符数组。
③浮点数或大整数:如果程序使用 fld、fstp 这样的浮点指令,可能意味着正在处理浮点数或结构体中的浮点类型成员。

分析实例

下面是一个简单的 C 语言程序,它包含一个结构体 Person,并通过这个结构体存储并打印个人信息。你可以用它来练习逆向分析结构体的过程。

#include <stdio.h>
#include <string.h>
​
// 定义一个结构体 Person
struct Person {int age;            // 年龄float height;       // 身高(米)char name[20];      // 姓名
};
​
void printPersonInfo(struct Person *p) {printf("Name: %s\n", p->name);printf("Age: %d\n", p->age);printf("Height: %.2f m\n", p->height);
}
​
int main() {struct Person person1;
​// 初始化结构体成员person1.age = 25;person1.height = 1.75;strcpy(person1.name, "Alice");
​// 打印结构体信息printPersonInfo(&person1);
​return 0;
}

在这个程序中,Person 结构体包含了三个成员变量:

  • int age:年龄,占用4字节。

  • float height:身高,占用4字节。

  • char name[20]:姓名,占用20字节。

接着在主函数中声明一个结构体变量person1,用于存储一个人的信息。接着就是对该结构体变量中的成员函数进行赋值初始化,最后通过自定义函数printPersonInfo打印该结构体中所有成员函数的内容。接着在VS中对程序进行编译,生成exe程序后,放入IDA中进行静态分析,查看反汇编代码中结构体的特征,得到代码如下:

mov     [ebp+var_24], 19h
movss   xmm0, ds:__real@3fe00000
movss   [ebp+var_20], xmm0
push    offset Source   ; "Alice"
lea     eax, [ebp+Dest]
push    eax             ; Dest
call    j__strcpy
add     esp, 8
lea     eax, [ebp+var_24]
push    eax             ; struct Person *
call    j_?printPersonInfo@@YAXPAUPerson@@@Z ; printPersonInfo(Person *)
add     esp, 4

mov [ebp+var_24], 19h首先将值 0x19(十六进制19,即十进制的25)存储到 [ebp+var_24] 处。

movss   xmm0, ds:__real@3fe00000
movss   [ebp+var_20], xmm0

movss xmm0, ds:__real@3fe00000 将全局地址 __real@3fe00000 对应的浮点数(即 1.75)加载到寄存器 xmm0 中。movss [ebp+var_20], xmm0xmm0 中的值(1.75)存储到 [ebp+var_20] 中。

接着,设置name成员,相关代码:

push    offset Source   ; "Alice"
lea     eax, [ebp+Dest]
push    eax             ; Dest
call    j__strcpy
add     esp, 8

push offset Source:将字符串 "Alice" 的地址推入堆栈;ea eax, [ebp+Dest]:加载 Dest 的地址到 eax 中。Dest 在这里表示目标字符数组的起始地址,push eax:将 Dest 的地址推入堆栈;call j__strcpy:调用 strcpy 函数来将 "Alice" 复制到 Dest 中,add esp, 8:恢复堆栈指针。

最后调用 printPersonInfo 函数:

lea     eax, [ebp+var_24]
push    eax             ; struct Person *
call    j_?printPersonInfo@@YAXPAUPerson@@@Z ; printPersonInfo(Person *)
add     esp, 4

lea eax, [ebp+var_24]:将 person1 结构体的基地址(即 var_24 的起始地址)加载到 eax 中。push eax:将 person1 的地址推入堆栈,作为参数传递给 printPersonInfo 函数。call j_?printPersonInfo@@YAXPAUPerson@@@Z:调用 printPersonInfo 函数,并传递结构体 person1 的指针。add esp, 4:恢复堆栈指针。

接着我们将程序放入x86dbg中进行解析,观察其特征;由于该程序在进行main函数定位时与此前其他的程序特征不一样,这边简单记录一下另外一种定位main函数的手法。程序载入后,发现此时模块位ntdll.dll

直接按下F9跳转模块至程序对应的模块中。

接着一直按着F8,直到程序静止不动,且通过程序的输出可以断定此时程序已经运行完毕。

在这边我们记录下程序最后call的指定地址(此处为006F1CC5)。接着点击重新运行按钮;

按下ctrl + G进行目的地址跳转。

定位到对应指令后按下F2下断点,接着按下F9将程序运行至此处。

按下F7进入函数中。

再按下F8则成功定位至main函数。

定位到main函数后接着回归正题,查看结构体特征。

上面这块是函数初始化的操作,不是本文重点,所以此不再过多赘述(相关内容可以查看笔者之前的文章《函数逆向分析-总体流程(整型&指针)》)接着往下看;

后续这串代码就是结构体的初始化相关代码了,在这边我们关注一下内存中结构体的内容。

在我们运行完上述代码后,可以看到结构体的成员数据就被放在了一个连续的内存块中(与数组有点像),但是结构体中成员变量的数据类型并不完全一致,并且一些结构体有很明显的为了数据对齐而进行的CC填充特征,所以区分数组和结构体并不困难。结构体作为参数传入函数中,与数组一样,也是传入结构体的首地址。

lea eax,dword ptr ss:[ebp-24]
push eax
call structre.6ED7E2

最后来看一下结构体的成员数据寻址相关代码,以下是第一个成员数据的读取代码:

ebp+8地址存储着结构体首地址,在这个基础上再加8就得到了结构体第三个成员变量的值,也就是Alice

第二个参数的寻址则直接传入ebp+8地址存储着结构体首地址,获得到第一个成员变量(年龄:19)的首地址。

第三个传入的参数为身高:1.78,对应代码如下:

代码先将ebp+8中存储的结构体的首地址拿出放入eax中,接着从 [eax+4] 地址(结构体中第二个元素的地址)读取一个 32 位单精度浮点数(即结构体中偏移为 4 字节处的浮点数),并将其转换为 64 位双精度浮点数,结果存储在 xmm0 寄存器中。

cvtss2sd 指令的作用是将一个 32 位的单精度浮点数(Single Precision Float)转换为 64 位的双精度浮点数(Double Precision Float)。

sub esp, 8:这条指令将 esp 指针向下移动 8 字节,预留出一个双精度浮点数的空间。最后将 xmm0 中的双精度浮点数存储到栈上,位置由 esp 指针指定。最后就是传入格式化字符串(Height:%.2f\n),调用printf函数进行打印。

可以看到,实际上汇编代码中,结构体的各成员通常与数组元素寻址一样也是通过 基址寄存器 + 偏移量 的方式访问的。在这篇文章中,我们深入探讨了结构体在逆向工程中的寻址方式和结构推断方法。结构体的逆向分析不仅需要对汇编代码的深入理解,更需要细致观察和不断验证。掌握这些技巧,可以帮助我们更准确地还原程序的数据结构,为后续的逆向分析工作打下坚实的基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/11488.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Kettle启动闪退(Couldn‘t read the database cache)

强制关机之后&#xff0c;kettle启动闪退 具体可以用debug模式运行脚本来定位问题 启动之后查看运行日志 DEBUG: Using JAVA_HOME DEBUG: _PENTAHO_JAVA_HOMEC:\Application\JDK DEBUG: _PENTAHO_JAVAC:\Application\JDK\bin\java.exeC:\Application\Kettle\data-integratio…

【机器学习】任务十:从函数分析到机器学习应用与BP神经网络

目录 1.从函数分析到机器学习应用 1.1 3D曲面图可视化报告 1.1.1 目标 1.1.2 代码分析 1.1.3 结果分析 1.1.4 观察与总结 1.1.5 结论 1.2 一元函数梯度计算报告 1.2.1 目标 1.2.2 代码分析 1.2.4 计算结果 1.2.5 优势与意义 1.2.6 结论 1.3 一元函数梯度和二阶导…

写一段python程序,利用时间序列分析的方法,预测股价的趋势

要使用时间序列分析来预测股价趋势&#xff0c;你需要使用统计学方法来分析历史股价数据&#xff0c;并基于这些数据来预测未来的股价走势。以下是一个简单的Python程序&#xff0c;使用ARIMA&#xff08;自回归积分滑动平均模型&#xff09;来预测股价趋势。 首先&#xff0c;…

C++初阶——类和对象(中)

目录 1、类的默认成员函数 2、构造函数 3、析构函数 4、拷贝构造函数 5、赋值运算符重载函数 5.1 运算符重载 5.2 赋值运算符重载函数 6、取地址运算符重载函数 6.1 const成员函数 6.2 取地址运算符重载函数 1、类的默认成员函数 默认成员函数就是用户没有显式实现&a…

蓝牙电话-如何做到无人值守(方案探讨)

蓝牙电话-如何做到无人值守&#xff08;方案探讨&#xff09; 一、前言 在蓝牙电话出现和在市场上使用的过程中&#xff0c;有好多的客户和友商隐晦或含蓄的咨询&#xff0c;问说蓝牙方案及其构建的体系&#xff0c;能不能做到无人值守&#xff1f;就是那种因业务原因需要把设备…

网络号和网络地址一样吗?真相揭晓

网络号和网络地址是两个在计算机网络领域中经常被提及的概念&#xff0c;尽管它们之间存在一定的关联性&#xff0c;但它们并不等同。为了深入理解这两个概念&#xff0c;我们需要从它们的定义、功能、应用以及相互关系等方面进行详细探讨。 一、网络号的定义与功能 网络号&am…

计算机网络-1.2分层结构

文章目录 三种分层结构OSI 七层模型&#xff08;Open Systems Interconnection Model&#xff09;TCP/IP 四层模型混合模型各层之间的关系PDU,SDU,PCIPDU&#xff08;Protocol Data Unit&#xff09;SDU&#xff08;Service Data Unit&#xff09;PCI&#xff08;Protocol Cont…

css:还是语法

emmet的使用 emmet是一个插件&#xff0c;Emmet 是 Zen Coding 的升级版&#xff0c;由 Zen Coding 的原作者进行开发&#xff0c;可以快速的编写 HTML、CSS 以及实现其他的功能。很多文本编辑器都支持&#xff0c;我们只是学会使用它&#xff1a; 生成html结构 <!-- emme…

2024年第45周ETF周报

ETF 第45 周 &#xff08; 2024-11-04 至 2024-11-10 &#xff09;周报 核心观点 ETF 业绩表现 股票型ETF周度收益率中位数为4.5831%宽基ETF中&#xff0c;创业板指涨跌幅中位数为6.1644%&#xff0c;跌幅最小。按板块划分&#xff0c;金融涨跌幅中位数为9.1867%&#xff0c…

基于Python的校园爱心帮扶管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

优化时钟网络之时钟抖动

Note&#xff1a;文章内容以Xilinx 7系列FPGA进行讲解 1、什么是时钟抖动 时钟抖动就是时钟周期之间出现的偏差。比如一个时钟周期为10ns的时钟&#xff0c;理想情况下&#xff0c;其上升沿会出现在0ns&#xff0c;10ns&#xff0c;20ns时刻&#xff0c;假设某个上升沿出现的时…

ORB-SLAM2源码学习:MapPoint.cc: MapPoint::PredictScale()预测一个尺度

前言 这部分是根据帧或者关键帧的地图点的深度来预测它对应的二维特征点所在的金字塔层级。 1.函数声明 1.预测地图点对应特征点所在的图像金字塔尺度层数 /*预测地图点对应特征点所在的图像金字塔尺度层数currentDist 相机光心距离地图点距离pKF 关键帧return…

与 Magic Quadrant™ 低代码领导者一起满足您的开发需求

2024 年 Gartner 企业低代码应用平台魔力象限™Gartner Magic Quadrant™ for Enterprise Low-Code Application PlatformsDownload the Gartner Magic Quadrant to gain a deeper understanding of the fast-growing low-code market and which vendors best align with your …

【CFD教程】7分钟学会电子机箱的强迫风冷模拟

1 案例背景 电子机箱是承载电子设备的箱体&#xff0c;比如电脑主机。机箱内电子元件工作会发热&#xff0c;为了让热量及时排出&#xff0c;常用风扇强迫外界空气流经机箱&#xff0c;进行散热。本仿真目的是计算电子元件发热功率及进风量一定时&#xff0c;机箱内的温度分布…

亚信安全并购亚信科技交易正式完成

亚信安全与亚信科技联合宣布&#xff0c;亚信安全正式完成对亚信科技的控股权收购&#xff0c;由此&#xff0c;规模近百亿的中国最大的软件企业之一诞生&#xff01;双方将全面实现公司发展战略&#xff0c;以及优势能力与资源的深度融合&#xff0c;形成业界独有的“懂网、懂…

HarmonyOS NEXT应用元服务开发Intents Kit(意图框架服务)技能调用接入方案

一、方案概述 开发者需要按照意图定义&#xff0c;进行意图注册并实现意图调用&#xff1b;用户通过对小艺对话进行自然语言输入&#xff0c;小艺理解语义转换成意图调用&#xff08;含意图参数&#xff09;&#xff0c;执行意图调用实现对应交互体验。 端侧意图注册 以“搜索…

Java面试要点03 - String、StringBuilder与StringBuffer全面对比

本文目录 一、引言二、String的特性与实现原理三、StringBuilder的工作机制四、StringBuffer的同步机制五、性能对比与分析六、最佳实践与应用场景七、总结 一、引言 在Java中&#xff0c;字符串操作是最常见的编程任务之一。Java提供了三种主要的字符串处理类&#xff1a;Str…

【HCIP园区网综合拓扑实验】配置步骤与详解(已施工完毕)

一、实验要求 实验拓扑图如上图所示 1、按照图示的VLAN及IP地址需求&#xff0c;完成相关配置 2、要求SW1为VLAN 2/3的主根及主网关 SW2为vlan 20/30的主根及主网关 SW1和SW2互为备份 3、可以使用super vlan&#xff08;本实验未使用&#xff09; 4、上层…

高铁站网约车智能出行如何实现快速调度功能

在现代交通体系中&#xff0c;高铁站作为重要的交通枢纽&#xff0c;其出行效率和服务质量直接影响乘客的出行体验。随着科技的进步&#xff0c;网约车智能出行已成为高铁站的重要补充&#xff0c;通过高效调度&#xff0c;为乘客提供更加便捷、快速的出行服务。接下来我们一起…

VUE3实现好看的通用网站源码模板

文章目录 1.设计来源1.1 网站主界面1.2 登录界面1.3 注册界面1.4 图文列表模板界面1.5 简洁列表模板界面1.6 文章内容左右侧模板界面1.7 文章内容模板界面 2.效果和源码2.1 动态效果2.2 源代码2.3 目录结构 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff…