大量 mov 指令进入 ebp+offset - 发生了什么?

逆向工程 拆卸 部件 二元分析 x86
2021-06-22 05:32:26

在学习 RE 时,我遇到了包含大部分mov [ebp+offset], value指令的这一大段指令。我相信那ebp + offset是局部变量?我认为?它真的只是很多局部变量吗?或者它实际上是一种数据结构,这就是 IDA 表示它的方式?我有一个关于这可能是什么的理论,但如果有人知道这可能意味着什么,那就太好了。

这是一个屏幕截图: 指示

我的猜测是这实际上是一种数据结构。ebp是结构的基地址。mov所述指令之间mov [...], offset value的填充字节。我猜他们只是填充字节,因为esi不包含一个值(它xor在截图的顶部本身-ed),是mov“depb + offset不少在此块。

对此屏幕截图中发生的事情的任何想法和建议将不胜感激。谢谢。

2个回答

数据结构(structs、unions、classes 等)是在编译步骤发生后完全消失的更高级别的元素。这意味着概念本身在二进制中完全不可见。当然,某些代码模式可能仍然暗示或暗示代码中存在数据结构,没有与struct,unionclass关键字等效的程序集(也不需要)

提供上述上下文后,我将解决您在整个问题中提出的具体问题和陈述:

我相信那ebp + offset是局部变量?

您准确地理解ebp用于引用堆栈,因此任何ebp基于引用的引用都可能是对基于堆栈的变量的引用。

它真的只是大量的局部变量吗?

它可以。然而,正如我在第一段中所解释的那样,无法确定原始源代码是否有很多局部变量或单个、几个甚至嵌套结构。

但是,没有必要(除非您的目标是实现二进制相同的代码重构)专门使用原始代码中使用的相同结构。如果你的目标是对代码有一个很好的理解,你应该可以随意实现你认为合适的数据结构,这对你来说是最直观的表示。您应该依赖 IDA 的结构定义,使汇编代码对您尽可能具有可读性,而不必过多考虑原始源代码的编写方式。

或者它实际上是一种数据结构,这就是 IDA 表示它的方式?

因此,这不是“IDA 表示它”的方式,而是任何编译器将代码转换为汇编的方式。IDA 只是帮助提供反汇编机器代码的交互界面。

ebp 是结构的基地址

由于函数以一个相当标准的方式开始,mov ebp, esp / sub esp, IMMebp本身不太可能指向一个结构。它指向创建新堆栈帧的堆栈偏移量。这是一种非常普遍的做法。然而,一个结构很可能从堆栈上的某个偏移量开始,并ebp使用从堆栈帧开始的偏移量来引用它。

mov所述指令之间mov [...], offset value的填充字节

假设您在谈论mov, REG, IMM指令,这些可能是进一步使用的寄存器初始化。mov出于性能原因,它们分布在基于堆栈的指令之间简单地说,流水线优化允许现代处理器在某种程度上与较慢的 RAM 写操作并行分配寄存器值,从而提高整体执行速度。

我猜它们只是填充字节,因为esi不包含值(它xor在屏幕截图的顶部)并且mov ebp + offset在这个块中相当多。

esi寄存器确实包含一个值,该值只是零。xor将寄存器与它自己一起是将其设置为零的常用方法,这比mov REG, 0编码指令要此外,mov OFFSET, REG比 短mov OFFSET, 0,因此编译器总体上为我们节省了几个字节的代码。

mov ebp, esp套在EBP堆叠,顶部sub esp, 0F34h分配0xF34字节上堆叠。EBP 用作写入和读取字节的基础。这是您可以在许多 Windows 可执行文件中看到的标准 x86 堆栈帧。

看起来 0xF34 字节分配了变量和各种结构,可能还有 20 字节结构的数组在查看之后,这看起来不对:

DWORD pointer to name
DWORD - no idea what
DWORD pointer to - no idea what -, can be NULL
DWORD - no idea what -
DWORD pointer to DWORD - no idea what -

ESI 的值为零。mov [...], esi是用来代替mov [...], 0,因为后者具有较长的操作码。

不要被 中的添加弄糊涂了ebp+var所有字节实际上都位于较低的地址,低于 EBP。

您可以在此处了解有关堆栈帧的更多信息:

https://en.wikibooks.org/wiki/X86_Disassembly/Functions_and_Stack_Frames