这个函数中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
,它将覆盖 ebp
为 ffff
,即十六进制的 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
主函数中:
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
,它将覆盖 ebp
为 ffff
,即十六进制的 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