探究
章节大纲
-
要利用目标程序中的缓冲区溢出漏洞,最重要的是要知道缓冲区起始位置与返回地址存储位置之间的距离。我们将使用调试方法来找出该距离。 由于我们有目标程序的源代码,我们可以用调试标志将其编译出来,这样会更方便调试。
我们需要向 gcc 命令添加 -g 标志,因此二进制文件中包含了调试信息。如果你运行 make,已经创建了调试版本。我们将使用 gdb 来调试 stack-L1-dbg。在运行程序之前需要先创建一个名为 badfile 的文件。
$ touch badfile ← 创建一个空的 badfile $ gdb stack-L1-dbg gdb-peda$ b bof ← 在函数 bof() 设置断点 Breakpoint 1 at 0x124d: file stack.c, line 18. gdb-peda$ run ← 开始执行程序 ... Breakpoint 1, bof (str=0xffffcf57 ...) at stack.c:18 18 { gdb-peda$ next ← 执行下一条语句 ... 22 strcpy(buffer, str); gdb-peda$ p $ebp ← 查看 ebp 的地址 $1 = (void *) 0xffffdfd8 gdb-peda$ p &buffer $2 = (char (*)[100]) 0xffffdfac ← 查看缓冲区的地址 gdb-peda$ quit
- 当 gdb 停在 bof() 函数内部时,它会在设置 ebp 寄存器以指向当前栈帧之前停止,因此如果我们在此处打印出 ebp 的值,将会获得调用者的 ebp 值。我们需要使用 next 执行几条指令,并在修改了 ebp 寄存器以指向 bof() 函数的栈帧之后停止。 gdb 的行为与 SEED 书籍基于 Ubuntu 16.04,因此书中没有包含 next 步骤。
- 请注意,从 gdb 获取的框架指针值在实际执行时是不同的,因为 gdb 在运行调试程序之前将一些环境数据推入栈中。 当直接运行程序而不是使用 gdb 时,栈不包含这些数据,所以实际的帧指针值更大。当你构建你的 payload 时请记住这一点。