5

我只是在 OllyDbg 中学习汇编和调试技能,以便学习如何使用未记录的函数。现在我遇到以下问题:

我有以下代码部分(来自 OllyDbg):

MOV EDI,EDI
PUSH EBP
MOV EBP,ESP
MOV EAX, DWORD PTR SS:[EBP+8]
XOR EDX,EDX
LEA ECX, DWORD PTR DS:[EAX+4]
MOV DWORD PTR DS:[EAX], EDX
MOV DWORD PTR DS:[ECX+4],ECX
MOV DWORD PTR DS:[ECX],ECX
MOV DWORD PTR DS:[EAX+C],ECX
MOV ECX, DWORD PTR SS:[EBP+C]

这是函数的开始,目标是找到数据结构。所以我发现它首先将 EBP 推入堆栈,然后将 ESP(当前堆栈指针)移动到 EBP,我认为它现在为函数定义了一个堆栈帧。现在教程说,在流行的布局中,第一个参数放在 [EBP+8] 处,第二个放在 [EBP+C] 处

这是我不明白的。我怎么知道第一个参数放在 EBP+8 ?

希望有人可以帮助我!谢谢!

4

1 回答 1

9

您是指什么样的“未记录功能”?汇编大部分时间只是编译的高级代码。几乎没有任何关于它的“无证”。

EBP最常用作函数中的堆栈帧指针,尤其是在 C 调用约定中(也称为名称cdecl)。使用这种约定,参数以相反的顺序在堆栈上传递(例如,最后一个参数首先被压入),并且被调用的函数EBP用来访问它们。根据您发布的代码,我认为第一个参数可能指向数据结构。看一看 :

MOV EAX, DWORD PTR SS:[EBP+8]
LEA ECX, DWORD PTR DS:[EAX+4]
MOV DWORD PTR DS:[EAX], EDX
MOV DWORD PTR DS:[ECX+4],ECX
MOV DWORD PTR DS:[ECX],ECX
MOV DWORD PTR DS:[EAX+C],ECX
MOV ECX, DWORD PTR SS:[EBP+C]

第一条指令将第一个参数移动到EAX. 然后将偏移量 4 添加到该参数并移至ECX. 请注意,这是通过LEA指令完成的,该指令是“加载有效地址”的简写。它用于无符号算术,编译器喜欢在进行指针算术和添加偏移量时使用它 - 所以每当你看到这条指令时,你应该警惕它所操作的任何东西都可能是指向结构的指针。当然,没有办法确定。稍后我们有一些MOVs 往返于该地址,ECX用于访问内存。这些结构(如果存在)在 C 中看起来像这样:

struct a { /* pointed to by EAX / [EBP+8] */
    int memb1; /* MOV DWORD PTR DS:[EAX], EDX */
    struct b* memb2; /* LEA ECX, DWORD PTR DS:[EAX+4] */
    int memb3; /* unused? */
    int memb4; /* MOV DWORD PTR DS:[EAX+C],ECX */
};

struct b {
    int memb1; /* MOV DWORD PTR DS:[ECX],ECX */
    int memb2; /* MOV DWORD PTR DS:[ECX+4],ECX */
};

希望这能以某种方式解决问题。逆向工程汇编代码是一项非常困难且耗时的任务,特别是如果您没有任何 API 调用可以告诉您应用程序使用的参数类型。

于 2012-06-02T10:31:32.390 回答