
Bypass de ASLR sin infoleak
En este artículo, hablaré sobre la aplicación de la técnica descrita por Samuel Groß en su Explotación remota de iPhone Parte 2: Aportando luz a la oscuridad -- un bypass remoto de ASLR, para evadir ASLR en Linux x86_64.
Para mostrarlo, voy a resolver un desafío pwnable de Buckeye CTF, guess_god.
Intentaré mantener el contenido lo más apto para principiantes posible, así que no dudes en saltarte cualquier sección si te sientes lo bastante seguro y solo quieres ver el exploit.

No jugué el CTF, pero me interesé por el desafío unas 2 horas antes de que terminara el CTF gracias a Guray00, quien pedía ayuda en el discord de fibonhack sobre unas artimañas criptográficas.
No pude ayudarle, pero eché un vistazo a los desafíos pwnable y pensé que sería bueno entender la publicación del blog de P0 y, con suerte, conseguir esa recompensa.
Address Space Layout Randomization (ASLR) es una técnica de seguridad informática que consiste en posicionar aleatoriamente la dirección base de un ejecutable y la posición de las librerías, el heap y el stack, en el espacio de direcciones de un proceso.
En Linux, puedes inspeccionar los mapeos de un proceso dado su pid a través de procfs, leyendo el archivo /proc/<pid>/maps.
Si eres un proceso y quieres conocer tus propios mapeos de memoria, puedes leer /proc/self/maps.
Por ejemplo, puedes intentar leer /proc/self/maps con cat:```
root@088ec31b2ce9:/home/ctf/challenge# cat /proc/self/maps
55faeb01c000-55faeb01e000 r--p 00000000 fe:01 2497233 /usr/bin/cat
55faeb01e000-55faeb023000 r-xp 00002000 fe:01 2497233 /usr/bin/cat
55faeb023000-55faeb026000 r--p 00007000 fe:01 2497233 /usr/bin/cat
55faeb026000-55faeb027000 r--p 00009000 fe:01 2497233 /usr/bin/cat
55faeb027000-55faeb028000 rw-p 0000a000 fe:01 2497233 /usr/bin/cat
55faeb115000-55faeb136000 rw-p 00000000 00:00 0 [heap]
7fe15dfb1000-7fe15dfd5000 rw-p 00000000 00:00 0
7fe15dfd5000-7fe15dffb000 r--p 00000000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so
7fe15dffb000-7fe15e166000 r-xp 00026000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so
7fe15e166000-7fe15e1b2000 r--p 00191000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so
7fe15e1b2000-7fe15e1b5000 r--p 001dc000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so
7fe15e1b5000-7fe15e1b8000 rw-p 001df000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so
7fe15e1b8000-7fe15e1c3000 rw-p 00000000 00:00 0
7fe15e1c7000-7fe15e1c8000 r--p 00000000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so
7fe15e1c8000-7fe15e1ef000 r-xp 00001000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so
7fe15e1ef000-7fe15e1f9000 r--p 00028000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so
7fe15e1f9000-7fe15e1fb000 r--p 00031000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so
7fe15e1fb000-7fe15e1fd000 rw-p 00033000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so
7fff4388f000-7fff438b0000 rw-p 00000000 00:00 0 [stack]
7fff43989000-7fff4398d000 r--p 00000000 00:00 0 [vvar]
7fff4398d000-7fff4398f000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
root@088ec31b2ce9:/home/ctf/challenge# cat /proc/self/maps 55ffc0b1b000-55ffc0b1d000 r--p 00000000 fe:01 2497233 /usr/bin/cat 55ffc0b1d000-55ffc0b22000 r-xp 00002000 fe:01 2497233 /usr/bin/cat 55ffc0b22000-55ffc0b25000 r--p 00007000 fe:01 2497233 /usr/bin/cat 55ffc0b25000-55ffc0b26000 r--p 00009000 fe:01 2497233 /usr/bin/cat 55ffc0b26000-55ffc0b27000 rw-p 0000a000 fe:01 2497233 /usr/bin/cat 55ffc2108000-55ffc2129000 rw-p 00000000 00:00 0 [heap] 7f1ec6e0f000-7f1ec6e33000 rw-p 00000000 00:00 0 7f1ec6e33000-7f1ec6e59000 r--p 00000000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec6e59000-7f1ec6fc4000 r-xp 00026000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec6fc4000-7f1ec7010000 r--p 00191000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec7010000-7f1ec7013000 r--p 001dc000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec7013000-7f1ec7016000 rw-p 001df000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec7016000-7f1ec7021000 rw-p 00000000 00:00 0 7f1ec7025000-7f1ec7026000 r--p 00000000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec7026000-7f1ec704d000 r-xp 00001000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec704d000-7f1ec7057000 r--p 00028000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec7057000-7f1ec7059000 r--p 00031000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec7059000-7f1ec705b000 rw-p 00033000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7ffc72fa4000-7ffc72fc5000 rw-p 00000000 00:00 0 [stack] 7ffc72fe7000-7ffc72feb000 r--p 00000000 00:00 0 [vvar] 7ffc72feb000-7ffc72fed000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
### Patrones de mapeo de memoria
Si haces esto un par de veces, podrías deducir que:
* La base PIE del binario debería estar en el rango 0x00005500_00000000-0x00005700_00000000, lo que significa 2TB de direcciones posibles.
* El heap está cerca del binario.
* Las librerías se encuentran en el rango 0x00007f00_00000000 - 0x00007fff_ffffffff, 1TB de direcciones posibles.
* La pila se encuentra \(la mayoría de las veces\) en el rango 0x00007ffc_00000000 - 0x00007fff_ffffffff, 16gb de direcciones posibles.
* El rango 0xffffffffff600000 - 0xffffffffff601000 siempre está mapeado, puedes leer [este artículo](http://terenceli.github.io/%E6%8A%80%E6%9C%AF/2019/02/13/vsyscall-and-vdso) si tienes curiosidad sobre qué es.
## 1.3 Cómo evadir ASLR sin una fuga de información
Hablemos de lo que puedes hacer para evadir ASLR cuando no es posible una fuga de información.
Este es mi intento de resumir lo que obtuve al leer la entrada del blog de Saelo.
Para evadir ASLR necesitas:
* Una técnica de memory spraying, que te permite mapear memoria contigua de un tamaño dado, en un rango de direcciones dado.
Como él dice, hay dos maneras de hacerlo:
1. Abusando de una fuga de memoria (¡no una fuga de información!), un bug en el que un fragmento de memoria queda “olvidado” y nunca se libera, y disparándolo múltiples veces hasta que se haya fugado la cantidad de memoria deseada.
2. Encontrando y abusando de un “gadget de amplificación”: un fragmento de código que toma un fragmento de datos existente y lo copia, potencialmente varias veces, permitiendo así al atacante hacer spray de una gran cantidad de memoria con solo enviar un número relativamente pequeño de bytes.
* Un oráculo `isAddressMapped`, que dada una dirección te dice si esa dirección está mapeada o no.