Solución Ropemporium Badchars
Desafío Ropemporium Badchars
En este reto de Ropemporium, nos encontramos con la presencia de badchars, que son caracteres de bajo nivel que podrían causar la terminación del programa y complicar el control del flujo del mismo según nuestras necesidades, algo común en el desarrollo de exploits.
El enunciado sugiere que para evitar los badchars, podemos utilizar herramientas como ropper para encontrar gadgets que no contengan estos caracteres. La identificación de los badchars se realizará ejecutando el programa, según indica el enunciado. Además, se nos informa que este desafío es similar al anterior, write4, pero con la dificultad adicional de manejar badchars en la función print_file()
.
Se nos plantean dos enfoques para resolver el desafío: la primera opción consiste en proporcionar direcciones y funcionalidad evitando por completo los badchars, mientras que la segunda opción es utilizar gadgets para modificar el contenido del string en memoria.
Para este análisis, optaremos por utilizar pwndbg en lugar de radare, ya que nos parece más adecuado en este contexto. Al abrir pwndbg y ejecutar inf func
para visualizar las funciones, identificamos una llamada a usefulGadgets
.
Análisis de la Función usefulGadgets
Al inspeccionar la función usefulGadgets
mediante el desensamblador (disas), describiremos la funcionalidad de las instrucciones presentes en el código:
Instrucciones:
1. xor BYTE PTR [r15], r14b
- La instrucción
xor
realiza una operación de exclusión OR (XOR) bit a bit entre los operandos. BYTE PTR [r15]
se refiere a la dirección de memoria almacenada en el registror15
, yr14b
es el registro de 8 bitsr14
.- Se realiza una operación XOR entre el byte almacenado en la dirección de memoria apuntada por
r15
y el contenido der14b
.
2. ret
- La instrucción
ret
se utiliza para realizar un retorno de función. La dirección de retorno se carga desde la pila y el control se transfiere a esa dirección.
3. add BYTE PTR [r15], r14b
- La instrucción
add
suma los valores de los operandos. - Se suma el byte almacenado en la dirección de memoria apuntada por
r15
con el contenido der14b
.
4. ret
- La instrucción
ret
realiza un retorno de función.
5. sub BYTE PTR [r15], r14b
- La instrucción
sub
realiza una operación de resta. - Resta el contenido de
r14b
del byte almacenado en la dirección de memoria apuntada porr15
.
6. ret
- La instrucción
ret
realiza un retorno de función.
7. mov QWORD PTR [r13+0x0], r12
- La instrucción
mov
copia el contenido del registror12
a la dirección de memoria calculada comor13+0x0
(8 bytes). QWORD PTR
indica que se está moviendo un cuádruple palabra (8 bytes) de datos.
8. ret
- La instrucción
ret
realiza un retorno de función.
9. nop DWORD PTR [rax+0x0]
- La instrucción
nop
(no operation) no realiza ninguna operación y se utiliza para llenar espacio o como marcador de posición. DWORD PTR [rax+0x0]
indica que se está aplicando a un doble palabra (4 bytes), pero debido a que es unnop
, no tiene efecto real en los datos.
Búsqueda de Badchars
Los badchars identificados son: x
, g
, a
, .
(en hexadecimal: 0x78
, 0x67
, 0x61
, 0x2E
).
Se ejecutará ropper
con un filtro para buscar gadgets sin estos badchars:
El enunciado sugiere el uso de XOR para sortear los badchars. Utilizaremos un gadget que permite cargar datos y aplicaremos una operación XOR con clave 2 en Python, utilizando la librería pwn
:
1
string = xor(b"flag.txt", 2)
Vale recopilacion que tenemos hasta ahora,
1
2
3
4
5
6
7
8
from pwn import process, xor, p64, log
shell = process("./badchars")
offset = 40
junk = b"A" * offset
string = xor(b"flag.txt", 2)
Configuración y Preparación
En esta parte, se realiza la configuración inicial del proceso y se definen las variables necesarias, incluyendo el string cifrado, la dirección de la sección BSS y la dirección de la función print_file.
En la imagen, se muestra la dirección de memoria de la función print_file
obtenida mediante radare.
1
2
3
4
5
6
7
8
9
10
11
12
from pwn import process, xor, p64, log
shell = process("./badchars")
offset = 40
junk = b"A" * offset
# Cifrado XOR del string "flag.txt" con clave 2
string = xor(b"flag.txt", 2)
# Dirección de la función print_file obtenida con radare
print_file = p64(0x400510)
Gadgets Necesarios
Los gadgets necesarios para realizar operaciones XOR y otras instrucciones esenciales en el exploit.
Dirección de la Sección BSS
Nos faltaría ahora la dirección de memoria donde podremos escribir. Utilizaremos radare y el comando iS para obtener esta dirección.