使用局部变量查找函数的返回地址

时间:2018-03-13 22:00:33

标签: c assembly memory buffer-overflow

所以对于这段代码我怎样才能使用局部变量" x"在函数fun()中查找存储在fun()的堆栈返回地址的位置(启用了aslr)?

void fun()
{
    int x;
}
int main()
{
    printf("blah blah blah");
}

3 个答案:

答案 0 :(得分:1)

我不认为单独使用x查找返回地址是可能的,但我会尽力让您亲近。

进入函数时,堆栈看起来像

*---------------------*
*   return address    *
*---------------------*
*  prev base pointer  *
*---------------------*
*                     *
*     local vars      *
*                     *
*---------------------*

在这种情况下,唯一的局部变量是x,因此堆栈看起来像:

*---------------------*
*   return address    *
*---------------------* <-- addr of return address
*  prev base pointer  *
*---------------------*
*         x           *
*---------------------* <-- addr of x

您可以通过

获取x的地址
printf("%p", (void*)&x)

然后你只需要找到x和返回地址之间的字节数。假设没有byte alignment/padding之间的距离应该是x的大小+前一个基指针的大小。在32位机器上,每个值应为~32位或4个字节,但为了确保您可以使用sizeof

sizeof(x)
sizeof(unsigned long*) // This is the tpye of the base pointer

将所有这些结合在一起

unsigned long* x_addr = (unsigned long*) &x;
ret_addr = x_addr + sizeof(x) + sizeof(unsignled long*);

答案 1 :(得分:0)

考虑添加到您的程序:

void callfun()
{
    return fun(); // Return address pushed on stack after callfun()'s.
}

int main()
{
    fun(); // Return address pushed on stack after main()'s.
    printf("blah blah blah");
}

返回地址的不同取决于堆栈在fun()调用点的深度。即使这些假设也基于一个C编译器实现,它具有一组特定的编译器参数,这些参数可能不会从该编译器的版本产生相同的结果。 C标准没有规定这些细节。

答案 2 :(得分:0)

您不会在示例中显示任何返回的内容。

通常,函数返回值存储在寄存器中。因此,没有地址。对于太大而无法存储在寄存器(例如,结构)中的值,通常会将一个隐藏参数传递给函数。

如果您正在讨论对func()的特定调用返回的地址,则需要知道特定处理器的调用帧格式。然后你可以用汇编语言编写一个函数来扫描堆栈,找到地址的前一个调用帧。