Post

Solución ropemporium callme

Callme Ropemporium Challenge 3

Bien, comenzamos con el challenge número 3 de ropemporium llamado “callme”. Resolveré la versión de 64 bits. Primero, leamos las instrucciones.

Nos dicen lo siguiente:

“Failure is not an option. How do you make consecutive calls to a function from your ROP chain that won’t crash afterwards? If you keep using the call instructions already present in the binary your chains will eventually fail, especially when exploiting 32 bit binaries. Consider why this might be the case.”

“Procedure Linkage: The Procedure Linkage Table (PLT) is used to resolve function addresses in imported libraries at runtime, it’s worth reading up about it. See Appendix A in the Beginners’ guide for a brief explanation of how the PLT is used in lazy binding.”

“You must call the callme_one(), callme_two(), and callme_three() functions in that order, each with the arguments 0xdeadbeef, 0xcafebabe, 0xd00df00d, e.g., callme_one(0xdeadbeef, 0xcafebabe, 0xd00df00d) to print the flag. For the x86_64 binary double up those values, e.g., callme_one(0xdeadbeefdeadbeef, 0xcafebabecafebabe, 0xd00df00dd00df00d)

“The solution here is simple enough, use your knowledge about what resides in the PLT to call the callme_ functions in the above order and with the correct arguments. If you’re taking on the MIPS version of this challenge, don’t forget about the branch delay slot.”

“Don’t get distracted by the incorrect calls to these functions made in the binary, they’re there to ensure these functions get linked. You can also ignore the .dat files and encrypted flag in this challenge, they’re there to ensure the functions must be called in the correct order.”

En el enunciado podemos sacar varias conclusiones, como que si hacemos de forma continuada las llamadas a las funciones que queremos, fallará. También nos dicen que debemos llamar callme_one(), callme_two(), y callme_three(), y que estas funciones deben recibir argumentos de una longitud determinada.

Abrimos el binario con pwndbg, creamos un pattern para calcular el offset con cyclic, como muestro a continuación. Luego, ejecutamos el binario y le pasamos en el input nuestro pattern, lo cual creará un segmentation fault.

Cyclic Pattern

Si miramos el valor de la dirección ret, podemos ver que está sobrescrita con nuestro pattern. Copiamos el valor y se lo pasamos a pwndbg de la siguiente forma, obteniendo así el offset que son 40 bytes.

Offset del Desbordamiento

Tenemos ya la primera pieza para resolver el challenge. Vamos a investigar el binario con radare2, para eso seguiremos los pasos en la imagen de a continuación.

Radare2

En la imagen anterior, ejecuto afl para poder ver las funciones. Veo una que se llama usefulFunction. La investigo con pdf, y podemos ver que es una función que hace llamadas a las otras funciones que justamente son las que nos dijeron en el enunciado. También, si nos fijamos, radare nos pone usefulGadgets.

Investigando un poco los gadgets que nos pone, en Wikipedia mismo nos pone en el siguiente apartado: X86 Calling Conventions

“Integer/Pointer Arguments 1-6: RDI, RSI, RDX, RCX, R8, R9”

Es decir, son registros que nos permiten pasar argumentos, justo lo que queremos: poder pasarle argumentos a las funciones que nosotros queremos.

Vamos a hacer un resumen: tenemos el offset de 40 bytes, más las direcciones de las funciones y gadgets que nos permiten pasar parámetros a las funciones. En resumen, todo lo necesario para construir el POC.

En la web pone también que hay otra forma de solucionarlo y obtener una shell, esto lo dejo para un futuro, ya que dice antes mejor hacer el challenge de pivot.

Exploit

Exploit

This post is licensed under CC BY 4.0 by the author.