问题描述
我正在 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
之类的东西开始转储堆栈。
首先,您正在寻找存储在堆栈中的返回地址:如果您在函数的第一条指令上放置一个断点,则返回地址是堆栈中的顶部。因此,在执行函数的单个指令之前打印堆栈,这将告诉您堆栈位置和堆栈上返回地址的值。
当您运行函数的初始部分时,它将为缓冲区分配堆栈空间(假设它是一个局部数组变量)。
然后,您想查看缓冲区所在堆栈空间的位置。您可以通过多种方式执行此操作 — 运行代码并使用相同的命令查看输入字符串在输入操作后立即转储到何处结束 — 或者,反汇编代码并查看它传递给 {{1 }} 或 gets
,任何一种方法都应该告诉您缓冲区的开始位置(您可以同时使用这两种方法来验证另一个)。
一旦您知道缓冲区的起始位置和返回地址的存储位置,您就可以知道覆盖返回地址需要多少个字符(字节)的输入。