这个函数中ebp值是如何变化的

how does ebp value changes in this function

主函数中:

 0x08049230 <+0>:   push   %ebp
 0x08049231 <+1>:   mov    %esp,%ebp
 0x08049233 <+3>:   sub    [=10=]x28,%esp
 0x08049236 <+6>:   movl   [=10=]xdeadbeef,-0xc(%ebp)
 0x0804923d <+13>:  call   0x8048ed4 <getbuf>
 0x08049242 <+18>:  mov    -0xc(%ebp),%edx

在getbuf函数中:

0x08048ed4 <+0>:    push   %ebp
0x08048ed5 <+1>:    mov    %esp,%ebp
0x08048ed7 <+3>:    sub    [=11=]x28,%esp
0x08048eda <+6>:    lea    -0x14(%ebp),%eax
0x08048edd <+9>:    mov    %eax,(%esp)
0x08048ee0 <+12>:   call   0x8048de4 <Gets>
0x08048ee5 <+17>:   mov    [=11=]x1,%eax
0x08048eea <+22>:   leave  
0x08048eeb <+23>:   ret    

基本上主要功能使用 %ebp-0xc 检查损坏的堆栈。

在getbuf 函数中,lea -0x14(%ebp),%eax 为输入字符串分配20 个字节。

如果我提供 24 个字节,$ebp 将被覆盖。我不确定为什么 getbuf 中 ebp 的变化会影响 main 函数中的 ebp 值。

我知道 $ebp 会压入堆栈。当getbufreturns时,$ebp会从栈中弹出。来自 main 函数的 $ebp 是否从 getbuf 接收 $ebp?

我也做了一些测试。我的输入字符串是 aaaabbbbbccccddddeeee,它是 24 个字节。我在 0x08049242 <+18> 处设置了一个断点:mov -0xc(%ebp),%edx,我打印 $ebp,但这不是 eeee 的十六进制表示。我注意到 $ebp 中存储的值确实发生了变化。如果输入小于 20bytes,则值为 0xbffff6c8。如果输入是 24 字节,它的值变成 0xb7fd0ac0。

任何人都可以解释它是如何变化的以及main函数中的$ebp如何知道gebuf函数中的$ebp的值?

谢谢

只有一个寄存器副本(每个线程)。函数调用和 returns 不会更改寄存器,但 esp 除外 return 地址所需。推送和弹出 ebp 的关键是为调用者保留它。因此,如果您覆盖堆栈上保存的值,则错误的值将弹出回 ebp 并 returned 给调用者。

My input string is aaaabbbbccccddddeeee, which is 24 bytes.

不,那是 20 个字节,加上一个用于终止零的字节。这仍然会溢出缓冲区,并且应该导致 ebp 的低字节被清零。请注意,如果您使用长度为 24 的字符串,例如 aaaabbbbccccddddeeeeffff,它将覆盖 ebpffff,即十六进制的 0x66666666,但终止零将覆盖低位return 地址的字节,因此您甚至不会 return 到正确的位置。您可以使用长度为 23 的字符串,例如 aaaabbbbccccddddeeeefff,在这种情况下,您的 ebp 应该是 0x00666666:

Starting program: /tmp/a.out
aaaabbbbccccddddeeeefff

Program received signal SIGSEGV, Segmentation fault.
8       mov    -0xc(%ebp),%edx
(gdb) p/a $ebp
 = 0x666666