
jemalloc framework de explotación de heap
shadow es un framework de explotación de heap de jemalloc. Ha sido diseñado para ser agnóstico respecto a la aplicación objetivo que utiliza jemalloc como su asignador de heap (ya sea Android's libc, Firefox, FreeBSD's libc, jemalloc independiente, o cualquier otra). La versión actual (2.0) ha sido probada extensamente con los siguientes objetivos:
Además del código fuente de la herramienta, este repositorio también incluye documentación sobre configuración de un entorno de depuración en espacio de usuario de Android para utilizar shadow, un resumen rápido de las estructuras de jemalloc de Android usando shadow, y algunas notas sobre cómo se comportan los bugs de doble free(), free() desalineado y free() arbitrario en el jemalloc de Android.
Cuando emites un comando específico de jemalloc por primera vez, shadow analiza todos los metadatos de jemalloc que conoce y los guarda en un archivo pickle de Python. Los comandos posteriores usan este archivo pickle en lugar de volver a analizar los metadatos desde la memoria para ser más rápidos.
Cuando sepas que el estado de los metadatos de jemalloc ha cambiado (por ejemplo cuando hayas realizado algunas asignaciones o hayas desencadenado una recolección de basura), usa el comando jeparse para volver a analizar los metadatos y recrear el archivo pickle.
El primer paso es instalar pyrsistence en tu máquina anfitriona.
En un dispositivo rooteado haz lo siguiente:
host$ adb shell
phone$ su root
phone# ps -e
De la salida de ps selecciona un proceso, por ejemplo com.google.process.gapps:
...
u0_a19 4679 3214 1668980 69216 SyS_epoll_ 7fa5f41430 S com.google.process.gapps
...
phone$ cd /data/local/tmp
phone$ ./gdbserver64 :5039 --attach 4679
Puedes encontrar los binarios del servidor GDB para ARM32 y ARM64 en el directorio "bin". O, si no confías en nosotros, haz:
host$ git clone http://android.googlesource.com/toolchain/gdb
host$ cd ./gdb/gdb-7.11
host$ mkdir build64; cd build64
host$ ../configure --program-prefix=aarch64-eabi-linux- --target=aarch64-eabi-linux --disable-werror
host$ make
host$ sudo make install
Luego en la máquina anfitriona haz:
host$ adb forward tcp:5039 tcp:5039
host$ aarch64-eabi-linux-gdb
(gdb) target remote :5039
(gdb) source /dir/with/shadow/gdb_driver.py
(gdb) jeparse -c /dir/with/shadow/cfg/android7_64.cfg
(gdb) jeruns -c
A veces el servidor GDB deja de escuchar si tardas demasiado en emitir el comando target remote :5039. Así que si ves errores extraños cuando emites el comando jeparse, simplemente comienza desde el principio.
shadow para Windows/Firefox ha sido probado con lo siguiente:
Nota: ¡Si trabajas con una versión de Firefox anterior a 36.0 usa la rama mozjs!
Primero necesitas configurar WinDBG con [el servidor de símbolos de Mozilla] (https://developer.mozilla.org/en/docs/Using_the_Mozilla_symbol_server). También necesitas instalar pykd. Luego copia el directorio shadow que has clonado de GitHub a alguna ruta (p.ej. C:\tmp\).
También puedes encontrar un script de inicialización de WinDBG de ejemplo en el archivo "windbg-init.cmd". Colócalo en C:\tmp\ e inicia WinDBG con windbg.exe -c "$$>< C:\tmp\windbg-init.cmd".
Finalmente, desde WinDBG emite los siguientes comandos:
!load pykd.pyd
!py c:\\tmp\\shadow\\pykd_driver help
[shadow] De Mysteriis Dom jemalloc
[shadow] shadow v2.0
[shadow] Firefox v56.0a1 (x86-64)
[shadow] jemalloc-specific commands:
[shadow] jechunks : dump info on all available chunks
[shadow] jearenas : dump info on jemalloc arenas
[shadow] jerun [-m] <address> : dump info on a single run
[shadow] -m : map content preview to metadata
[shadow] jeruns [-cs] : dump info on jemalloc runs
[shadow] -c : current runs only
[shadow] -s <size class> : runs for the given size class only
[shadow] jebins : dump info on jemalloc bins
[shadow] jebininfo : dump info on bin sizes
[shadow] jesize2bin : convert size to bin index
[shadow] jeregions <size class> : dump all runs that host the regions of
[shadow] the given size class
[shadow] jesearch [-cs] <hex> : search the heap for the given hex dword
[shadow] -c : current runs only
[shadow] -s <size class> : regions of the given size only
[shadow] jeinfo <address> : display all available details for an address
[shadow] jedump [path] : store the heap snapshot to the current
[shadow] working directory or to the specified path
[shadow] jestore [path] : jedump alias
[shadow] jetcaches : dump info on all tcaches
[shadow] jetcache [-bs] <tid> : dump info on single tcache
[shadow] -b <bin index> : info for the given bin index only
[shadow] -s <size class> : info for the given size class only
[shadow] jeparse [-crv] : parse jemalloc structures from memory
[shadow] -c <config file> : jemalloc target config file
[shadow] -r : read content preview
[shadow] -v : produce debug.log
[shadow] Firefox-specific (pykd only) commands:
[shadow] nursery : display info on the SpiderMonkey GC nursery
[shadow] symbol [-vjdx] <size> : display all Firefox symbols of the given size
[shadow] -v : only class symbols with vtable
[shadow] -j : only symbols from SpiderMonkey
[shadow] -d : only DOM symbols
[shadow] -x : only non-SpiderMonkey symbols
[shadow] pa <address> [<length>] : modify the ArrayObject's length (default new length 0x666)
[shadow] Android-specific commands:
[shadow] jefreecheck [-bm] : display addresses that can be passed to free()
[shadow] -b <bin index> : display addresses that will be freed to
[shadow] the tcache bin of <bin index>
[shadow] -m <name> : only search this specific module
[shadow] Generic commands:
[shadow] jeversion : output version number
[shadow] jehelp : this help message
Si no ves el mensaje de ayuda anterior, has hecho algo mal ;)
Nota: ¡Esta característica es actualmente solo para Firefox/Windows!
El comando symbol te permite buscar clases (y estructuras) de SpiderMonkey y DOM de tamaños específicos. Esto es útil cuando intentas explotar bugs de use-after-free, o cuando quieres posicionar objetos víctima interesantes para sobrescribir/corromper.
En el directorio principal de shadow puedes encontrar dos pequeñas utilidades de análisis de PDB, symhex.py y pdbdy.py (más rápida). Ejecútalos en "xul.pdb" para generar el archivo pickle de Python que shadow espera en el directorio "pdb" (como "pdb/xul-VERSION.pdb.pkl"). Antes de ejecutarlos asegúrate de haber registrado "msdia90.dll"; por ejemplo en Windows 8.1 x86-64 puedes hacerlo con:
regsvr32 "c:\Program Files (x86)\Common Files\Microsoft Shared\VC\msdia90.dll"
desde un símbolo del sistema de Administrador. También necesitas el módulo de Python "comtypes"; instala pip y luego haz pip install comtypes.
Para obtener "xul.pdb" tienes que configurar WinDBG con [el servidor de símbolos de Mozilla] (https://developer.mozilla.org/en/docs/Using_the_Mozilla_symbol_server).
unmask_jemalloc fue rediseñado inicialmente con un diseño modular para soportar los tres depuradores y plataformas principales (WinDBG, GDB y LLDB). La herramienta fue renombrada a shadow cuando se añadieron características exclusivas de Firefox/Windows/WinDBG.
Lo siguiente es una visión general del nuevo diseño (lee las flechas como "importaciones"). El objetivo es, obviamente, tener todo el código dependiente del depurador en los módulos *_driver y *_engine.
---------------------------------------------------------------------------------------
debugger-required frontend (glue)
+------------+ +-------------+ +-------------+
| gdb_driver | | lldb_driver | | pykd_driver |
+------------+ +-------------+ +-------------+
^ ^ ^
| | |
------+-------------------+-------------------+----------------------------------------
| | |
| +--------+ |
+------------------------ | +-----+ core logic (debugger-agnostic)
| | |
| | |
+-----------------+
+------+ | |
| |---------------> | shadow |<-----+
| util | +------> | | |
| | | +-----------------+ |
+------+ | ^ ^ ^ ^ |
| | | | | | | | | +--------+
| | | +-----+----------+ | +----+--------+---| symbol |
| | | | | | | | +--------+
+-+ | | | +----------+ | | | +---------+
| | | | | jemalloc | | +--------+---| nursery |
| | | | +----------+ | | +---------+
| | | | ^ ^ ^ | |
| | | | | | | | |
| | | | | | +------+--------+ |
| | | | | | | | |
| | +---+---+----+----------+--------+-----+ |
| | | | | | | | |
| +-----+---+----+----+ | | | |
| | | | | | | | |
--+---------+---+----+----+-----+--------+-----+----+----------------------------------
| | | | | | | | |
| | | | | | | | | debugger-dependent APIs
| | | | | | | | |
| | | | | | | | |
| | | | v | | v |
| +------------+ | +-------------+ | +-------------+
+->| gdb_engine | +--| lldb_engine | +--| pykd_engine |
+------------+ +-------------+ +-------------+
^ ^ ^
| | |
+---+ +---------+ +---------------+
| | |
| | |
-------+-------------+-------------+---------------------------------------------------
| | |
| | | debugger-provided backend
| | |
| | |
+-----+ +------+ +------+
| gdb | | lldb | | pykd |
+-----+ +------+ +------+
---------------------------------------------------------------------------------------