我正在学习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?
希望有人可以帮助我! 谢谢!
答案 0 :(得分:8)
你的意思是什么样的“无证件功能”?汇编只是大部分时间编译的高级代码。关于它几乎没有任何“无证”。
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
指令完成的,该指令是“加载有效地址”的简写。它用于无符号算术和编译器,比如在进行指针算法和添加偏移时使用它 - 所以每当你看到这条指令时,你应该警惕它在上操作的任何东西可能是指向结构的指针。当然,没有办法确定。稍后我们在该地址之间有一些MOV
,其中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调用可以告诉您应用程序使用的参数类型。