缓冲区溢出在gdb中工作但不是没有它

tha*_*man 39 c security buffer-overflow memory-safety fortify-source

我在CentOS 6.4 32位上,并试图在程序中导致缓冲区溢出.在GDB中它可以工作.这是输出:

[root@localhost bufferoverflow]# gdb stack
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/bufferoverflow/stack...done.
(gdb) r
Starting program: /root/bufferoverflow/stack
process 6003 is executing new program: /bin/bash
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.107.el6_4.2.i686
sh-4.1#
Run Code Online (Sandbox Code Playgroud)

然而,当我自己运行程序堆栈时它会出现故障.为什么会这样?

mav*_*vam 98

如果您没有充分考虑将非确定性引入调试过程的因素,那么漏洞利用开发可能会导致严重的问题.特别是,调试器中的堆栈地址可能与正常执行期间的地址不匹配.发生此工件是因为操作系统加载程序在堆栈开始之前放置了环境变量和程序参数:

流程布局

由于您的易受攻击程序不接受任何参数,因此环境变量可能是罪魁祸首.确保它们在调用,shell和调试器中都是相同的.为此,您可以将调用包装在env:

env - /path/to/stack
Run Code Online (Sandbox Code Playgroud)

并使用调试器:

env - gdb /path/to/stack
($) show env
LINES=24
COLUMNS=80
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,gdb设置了两个环境变量,您可以进一步禁用它们:

unset env LINES
unset env COLUMNS
Run Code Online (Sandbox Code Playgroud)

现在show env应该返回一个空列表.此时,您可以启动调试过程以查找您想要跳转到的绝对堆栈地址(例如0xbffffa8b),并将其硬编码到您的漏洞利用中.

另一个微妙但重要的细节:调用./stack和之间有区别/path/to/stack:因为argv[0]保存程序的方式完全是你调用的,你需要确保相等的调用字符串.这就是为什么我/path/to/stack在上面的例子中使用而不仅仅是./stackgdb stack.

当学习利用内存安全漏洞时,我建议使用下面的包装程序,它可以解决繁重问题并确保相同的堆栈偏移:

$ invoke stack         # just call the executable
$ invoke -d stack      # run the executable in GDB
Run Code Online (Sandbox Code Playgroud)

这是脚本:

#!/bin/sh

while getopts "dte:h?" opt ; do
  case "$opt" in
    h|\?)
      printf "usage: %s -e KEY=VALUE prog [args...]\n" $(basename $0)
      exit 0
      ;;
    t)
      tty=1
      gdb=1
      ;;
    d)
      gdb=1
      ;;
    e)
      env=$OPTARG
      ;;
  esac
done

shift $(expr $OPTIND - 1)
prog=$(readlink -f $1)
shift
if [ -n "$gdb" ] ; then
  if [ -n "$tty" ]; then
    touch /tmp/gdb-debug-pty
    exec env - $env TERM=screen PWD=$PWD gdb -tty /tmp/gdb-debug-pty --args $prog "$@"
  else
    exec env - $env TERM=screen PWD=$PWD gdb --args $prog "$@"
  fi
else
  exec env - $env TERM=screen PWD=$PWD $prog "$@"
fi
Run Code Online (Sandbox Code Playgroud)

  • 非常有用的信息!感谢您分享脚本. (4认同)
  • 我按照你的建议做了,并将程序作为/ root/bufferflow/stack运行,它运行正常.谢谢 (3认同)

Yor*_*ork 7

在gdb中运行代码时堆栈帧指针的地址与正常运行它不同.因此,您可能会在gdb模式下损坏返回地址,但在正常模式下运行时可能不正确.主要原因是两种情况的环境变量不同.

由于这只是一个演示,您可以更改受害者代码,并打印缓冲区的地址.然后将返回地址更改为偏移量+缓冲区的地址.

但实际上,您需要猜测返回地址在恶意代码之前添加NOP sled.并且您可能会多次猜测以获得正确的地址,因为您的猜测可能不正确.

希望这可以帮到你.


Log*_*cG8 5

缓冲区溢出在gdb和segfaults下运行的原因是gdb禁用地址空间布局随机化.我相信这在gdb版本7中默认打开.

您可以通过运行此命令来检查:

show disable-randomization
Run Code Online (Sandbox Code Playgroud)

并设置它

set disable-randomization on
Run Code Online (Sandbox Code Playgroud)

要么

set disable-randomization off
Run Code Online (Sandbox Code Playgroud)


Ara*_*lox 5

以下是在终端中使用相同堆栈运行程序的简单方法gdb:

首先,确保您的程序编译时没有堆栈保护,

gcc -m32 -fno-stack-protector -z execstack -o shelltest shelltest.c -g

和ASLR被禁用:

echo 0 > /proc/sys/kernel/randomize_va_space

注意:我的机器上的默认值是2,在更改之前请注意.

然后像这样运行你的程序(终端和gdb):

env -i PWD="/root/Documents/MSec" SHELL="/bin/bash" SHLVL=0 /root/Documents/MSec/shelltest
env -i PWD="/root/Documents/MSec" SHELL="/bin/bash" SHLVL=0 gdb /root/Documents/MSec/shelltest
Run Code Online (Sandbox Code Playgroud)

gdb,确保unset LINESCOLUMNS.

注意:我通过使用测试程序获得了这些环境变量.

这两个运行将为您提供指向堆栈顶部的相同指针,因此如果您尝试利用远程托管的二进制文件,则不需要远程脚本恶作剧.