Assembly 什么是EBP+;8在这种情况下,OllyDbg和汇编程序是什么意思?

Assembly 什么是EBP+;8在这种情况下,OllyDbg和汇编程序是什么意思?,assembly,ollydbg,stack-frame,Assembly,Ollydbg,Stack Frame,我只是在学习OllyDbg中的汇编和调试技巧,以便学习如何使用未记录的函数。现在我有以下问题: 我有以下代码部分(来自OllyDbg): 这是函数的开始,目标是找到数据结构。所以我发现它首先在堆栈上推EBP,然后将ESP(当前堆栈指针)移动到EBP,我认为它现在为函数定义了一个堆栈帧。现在,教程说,在流行的布局中,第一个参数位于[EBP+8],第二个参数位于[EBP+C] 这是我不明白的。我如何知道第一个参数位于EBP+8 希望有人能帮助我! 谢谢 你指的是什么类型的“未记录函数”?汇编在大多数

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

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

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

这是我不明白的。我如何知道第一个参数位于EBP+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
s往返于该地址,其中
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调用来告诉您应用程序使用的参数类型。

该函数从NTDLL.DLL调用为RtlInitializeGenericTable。该函数的末尾有一个RET 14,我认为这意味着它使用stdcall调用约定。对于我来说,还不清楚如何确定传递给函数的第一个参数位于EBP+8?假设函数使用C调用约定并设置基于EBP的堆栈帧,函数的第n个参数位于
EBP+4+4n
,从n=1开始
ret14
并不一定意味着完全抛出
cdecl
:它只是意味着调用方在调用函数后不必清理堆栈空间。对于这些愚蠢的问题,我深表歉意。现在我知道第一个参数是EBP+4+4n,如果n=1,那么它就是EBP+8。这很有帮助。您如何知道参数位于EBP+4+4n?你有任何链接或提示我应该学习或通过什么来获得这种知识。我想我在这里缺少一些基本知识……是的,这是关于堆栈框架的外观以及在使用C调用约定时如何处理参数的基本知识。看一看:、和(从第35页开始)。啊,我想我明白了。您能否确认我是否理解正确:参数被推送到堆栈,然后调用函数。然后按下前4个字节,这是返回地址,以便在函数后跳回。然后我们将当前EBP地址推送到堆栈中,以便保存它。又是4个字节!现在,当我们查看时,我们需要返回4个字节到返回地址,然后返回4个字节到第一个参数EBP+8。这对吗?
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 */
};