我正在学习x86 Linux上基于堆栈的缓冲区溢出。如何在GDB中覆盖EIP后计算堆栈空间的大小?
(gdb) info registers
eax 0x1 1
ecx 0xffffd7a0 -10336
edx 0xffffd17b -11909
ebx 0xff5f8948 -10516152
esp 0xffffd180 0xffffd180
ebp 0x80ad26dc 0x80ad26dc
esi 0xf7fc2000 -134471680
edi 0x0 0
eip 0x66666666 0x66666666
eflags 0x10282 [ SF IF RF ]
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x63 99
(gdb) info frame
Stack level 0, frame at 0xffffd184:
eip = 0x66666666; saved eip = 0xffffd300
called by frame at 0x80ad26e4
Arglist at 0xffffd17c, args:
Locals at 0xffffd17c, Previous frame's sp is 0xffffd184
Saved registers:
eip at 0xffffd180
(gdb) info stack
#0 0x66666666 in ?? ()
#1 0xffffd300 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
编辑:感谢您的回答,GDB中给出这个问题正确答案的确切命令是info proc
(gdb) info proc all
您需要查看堆栈本身—堆栈的内存。试着自己解码堆栈,也许从x/20x $esp
这样的东西开始转储堆栈。
首先,你正在寻找存储在堆栈中的返回地址:如果你在函数的第一条指令上放置一个断点,那么返回地址就是堆栈上的顶部。因此,在执行函数的单个指令之前打印堆栈,这将告诉您堆栈位置和堆栈上的返回地址的值。
当您运行函数的初始部分时,它将为缓冲区分配堆栈空间(假设它是一个局部数组变量)。
然后,您想要查看缓冲区在堆栈空间中的位置。您可以通过多种方式做到这一点—运行代码并使用相同的命令在输入操作之后立即转储堆栈,看看您的输入字符串在哪里结束—或者,反汇编代码并查看它传递给gets
或scanf
的堆栈地址,任何一种方法都应该告诉您缓冲区从哪里开始(并且您可以使用两种方法来验证另一种方法)。
一旦你知道了缓冲区的起始位置和返回地址的存储位置,你就可以知道需要多少个字符(字节)的输入来覆盖返回地址。