关于Stack Frame

时间:2016-01-06 16:59:26

标签: c gdb stack

我了解堆栈框架。但如果我是对的,在调用函数之前,该函数的参数将被推入堆栈框架。

例如,

int main(void)
{
  printf("hi everyone %d \n", 3);
  return 0;
}

在这种情况下,在主堆栈框架中,“Hi everyone%d \ n”的地址和3应该被推,然后必须调用printf,如果我是对的。

但是当我使用gdb时没有这样的指令。

我正在研究字符串格式漏洞。但我上面写的内容并没有发生。我怎么了?

3 个答案:

答案 0 :(得分:2)

对于您的简单程序:

#include <stdio.h>

int main(void)
{
    printf("hi everyone %d \n", 3);
    return 0;
}

编译为gcc -g -ansi -pedantic -Wall test.c -o test(在使用gcc版本4.8.4的Ubuntu 14.04系统上),似乎printf的参数正在寄存器中传递。在printf命令上设置断点并进行反汇编会产生以下结果:

Dump of assembler code for function main:
   0x000000000040052d <+0>:     push   rbp
   0x000000000040052e <+1>:     mov    rbp,rsp
=> 0x0000000000400531 <+4>:     mov    esi,0x3
   0x0000000000400536 <+9>:     mov    edi,0x4005d4
   0x000000000040053b <+14>:    mov    eax,0x0
   0x0000000000400540 <+19>:    call   0x400410 <printf@plt>
   0x0000000000400545 <+24>:    mov    eax,0x0
   0x000000000040054a <+29>:    pop    rbp
   0x000000000040054b <+30>:    ret    
End of assembler dump.

我们可以看到值3(在这种情况下作为文字被编码到指令中)开始移入%esi寄存器,你的字符串的地址被移动到{{ 1}}注册。您可以通过查看内存来验证这一点:

%edi

另外,你可以检查堆栈和基本指针,你会发现在这个简单的程序中没有使用堆栈:

(gdb) x/16cb 0x4005d4
0x4005d4:   104 'h' 105 'i' 32 ' '  101 'e' 118 'v' 101 'e' 114 'r' 121 'y'
0x4005dc:   111 'o' 110 'n' 101 'e' 32 ' '  37 '%'  100 'd' 32 ' '  10 '\n

由于(gdb) print $rbp $4 = (void *) 0x7fffffffe460 (gdb) print $rsp $5 = (void *) 0x7fffffffe460 $rpb都具有相同的值。

希望这会有所帮助。 -T。

答案 1 :(得分:1)

这篇文章介绍了GCC compiler can optimize code to replace some types of call with equivalent, but not identical, operations如何提供帮助。

您提供的示例将是此类优化的主要目标。

答案 2 :(得分:-1)

遵循__cdecl调用约定(大多数编译器的默认值)https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl,我们可以看到编译器可能产生的内容。

首先,调用者创建一个堆栈帧。

push    ebp
mov     ebp, esp

上述代码的作用很简单。首先,它将ebp的当前值推送到堆栈,然后将堆栈指针的值移动到ebp。

现在它将函数的参数从右向左推送到堆栈。

push    3; The number
push    ?; Placeholder for the pointer to the string

现在它调用该函数。

call    ?; Placeholder for the address of printf

当函数返回时,我们通过简单地重置堆栈框架来清理堆栈

mov esp, ebp

并恢复ebp

pop ebp

只是看一下visual studio 2015为我制作的一些代码,我可以确认这个调用约定有变化,但这是堆栈帧的一般概念。