-
Dumpear un payload oculto de un binario con gdb
Lanzamos gdb de forma interactiva sobre el binario:
gdb /Ruta/Al/Binario
Desactivamos la paginación:
set pagination off
Desactivamos el confirm:
set confirm off
Ponemos un punto de interrupción justo antes de que el binario ejecute la primera llamada al sistema que le indiquemos. En este caso pararemos antes de la syscall mprotect, que es la llamada al sistema que reserva memoria para luego cargar algo allí:
catch syscall mprotect
Ejecutamos el binario:
run
Veremos que la ejecución se detiene justo antes de ejecutar primera mprotect:
Catchpoint 1 (call to syscall mprotect), 0x0000000003fe6ee5 in ?? ()
En ese momento podemos ver que tiene el binario mapeado en memoria, ejecutando en gdb:
info proc mappings
Si nos da, por ejemplo:
process 13302 Mapped address spaces: Start Addr End Addr Size Offset Perms objfile 0x400000 0x401000 0x1000 0x0 rw-p /mnt/host/MAGIC 0x401000 0x2c1f000 0x281e000 0x0 rw-p 0x2c1f000 0x3fe8000 0x13c9000 0x0 r-xp /mnt/host/MAGIC 0x7ffff7ff8000 0x7ffff7ff9000 0x1000 0x0 rw-p 0x7ffff7ff9000 0x7ffff7ffd000 0x4000 0x0 r--p [vvar] 0x7ffff7ffd000 0x7ffff7fff000 0x2000 0x0 r-xp [vdso] 0x7ffffffde000 0x7ffffffff000 0x21000 0x0 rw-p [stack]Podemos observar que, en ese preciso momento de la ejecución, el binario tiene mapeados diferentes espacios en memoria. Los mapeos que nos interesan son los que NO tienen objfile. Esto es porque en Linux, cada línea de /proc/<pid>/maps representa una región de memoria mapeada con su origen. Las que terminan con rutas o etiquetas específicas como vvar, vdso o stack no son payloads nuevos, sino partes conocidas del proceso.
Por ello, para esa salida, nos interesa dumpear las líneas 0x401000 a 0x2c1f000 y 0x7ffff7ff8000 a 0x7ffff7ff9000. Lo hacemos con:
dump memory ~/ProbablePayloadStage2_1.bin 0x401000 0x2c1f000 dump memory ~/ProbablePayloadStage2_2.bin 0x7ffff7ff8000 0x7ffff7ff9000
Si además, revisando el strace del binario, observamos que ese mapeo de memoria (o muy cercano) fue marcado como ejecutable, pasando de prot_read a prot_exec:
12590 mprotect(0x404000, 20289869, PROT_READ|PROT_EXEC) = 0
…el dumpeo se justifica aún más.
Arriba digo que la dirección de memoria del mapeo no tiene que ser exacta y puede ser muy cercana es porque el kernel mapea memoria en múltiplos de 4 KB (0x1000). Cuando vemos en strace que el binario hace:
mprotect(0x404000, 20289869, PROT_READ|PROT_EXEC)
…el kernel alinea la dirección base hacia abajo al límite de página más cercano (0x401000). Por eso en /proc/<pid>/maps vemos el inicio real de la región como 0x401000, no 0x404000.
Entonces, teniendo ambos dumps, ya podemos empezar a trabajar con ellos. Primero salimos de gdb:
quit
Y luego, para obtener información sobre los dumps, usamos las herramientas habituales:
file ~/ProbablePayloadStage2_1.bin file ~/ProbablePayloadStage2_2.bin
o
strings -a ~/ProbablePayloadStage2_1.bin strings -a ~/ProbablePayloadStage2_2.bin
…etc.
NOTA:
Es posible hacer un script que ejecute esto de forma automática:
cat > /mnt/host/tmp/dump_stage3.gdb echo 'set pagination off' | tee -a ExtractMemoryMaps.gdb echo 'set confirm off' | tee -a ExtractMemoryMaps.gdb echo 'catch syscall mprotect' | tee -a ExtractMemoryMaps.gdb echo 'commands' | tee -a ExtractMemoryMaps.gdb echo ' silent' | tee -a ExtractMemoryMaps.gdb echo ' printf "\n[*] mprotect called at: %p, len=%d, prot=%d\n", $rdi, $rsi, $rdx' ' | tee -a ExtractMemoryMaps.gdb echo ' if ($rsi > 1000000 && ($rdx == 5 || $rdx == 4))' | tee -a ExtractMemoryMaps.gdb echo ' dump memory /mnt/host/tmp/Stage3_dump.bin $rdi ($rdi + $rsi)' | tee -a ExtractMemoryMaps.gdb echo ' printf "[+] Dumped probable Stage3 region from %p to %p\n", $rdi, ($rdi + $rsi)' | tee -a ExtractMemoryMaps.gdb echo ' detach' | tee -a ExtractMemoryMaps.gdb echo ' quit' | tee -a ExtractMemoryMaps.gdb echo ' end' | tee -a ExtractMemoryMaps.gdb echo ' continue' | tee -a ExtractMemoryMaps.gdb echo 'end' | tee -a ExtractMemoryMaps.gdb echo 'run' | tee -a ExtractMemoryMaps.gdb
Luego lo podemos ejecutar, con:
gdb -q -x /mnt/host/tmp/dump_stage3.gdb /mnt/host/MAGIC
Ignora los mprotect pequeños (como el de 3117 bytes).
Solo dumpea si la longitud (len) es mayor de 1 MB y los permisos incluyen PROT_EXEC.
Eso debería capturar la gran región de 0x404000 (unos 20 MB).
Los hacks de hacks4geeks son minitutoriales rápidos pensados para geeks con conocimiento informático avanzado. Si no entiendes o no consigues ejecutar un hack de esta web considera suscribirte a Premium para solicitar asistencia sobre el mismo.