ebp值如何在此函数中更改

时间:2015-04-20 22:33:55

标签: assembly stack stack-overflow

在主要功能中:

 0x08049230 <+0>:   push   %ebp
 0x08049231 <+1>:   mov    %esp,%ebp
 0x08049233 <+3>:   sub    $0x28,%esp
 0x08049236 <+6>:   movl   $0xdeadbeef,-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    $0x28,%esp
0x08048eda <+6>:    lea    -0x14(%ebp),%eax
0x08048edd <+9>:    mov    %eax,(%esp)
0x08048ee0 <+12>:   call   0x8048de4 <Gets>
0x08048ee5 <+17>:   mov    $0x1,%eax
0x08048eea <+22>:   leave  
0x08048eeb <+23>:   ret    

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

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

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

我知道$ ebp会进入堆栈。当getbuf返回时,$ ebp将从堆栈中弹出。 main函数的$ ebp是否从getbuf接收$ ebp?

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

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

谢谢

1 个答案:

答案 0 :(得分:1)

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

  

我的输入字符串是aaaabbbbccccddddeeee,这是24个字节。

不,那是20个字节,加上一个终止零。这仍然会溢出缓冲区,并导致ebp的低字节被清零。请注意,如果您使用长度为24的字符串,例如aaaabbbbccccddddeeeeffff,则会将ebp覆盖为ffff,其中0x66666666为十六进制,但终止零将覆盖低位返回地址的字节,所以你甚至不会回到正确的地方。您可以使用长度为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
$6 = 0x666666