Pwn0x03
Flag: StarHack{fms_bUG5_ar3_mY_favorites_wh4t_ab0ut_y0u?ASDSAKDASDKASFFDSASDFSA}
Challenge
Ce challenge tourne sur un docker et n'est pas disponible
Solution
Le binaire n'est composé que de sa fonction main :
int main(void) {
long in_FS_OFFSET;
char secret [0x40];
char identity [0x58];
long canary;
canary = *(long *)(in_FS_OFFSET + 0x28);
init_buffering();
puts("----------------------------");
puts("-- Secret storage service --");
puts("----------------------------");
puts("Identify your self : ");
printf(" > ");
read(0x0,identity,0x50);
printf("Welcome : ");
printf(identity);
puts("----------------------------");
printf("type your secret : ");
gets(secret);
if (canary != *(long *)(in_FS_OFFSET + 0x28)) __stack_chk_fail();
return 0;
}La vulnérabilité réside dans 2 choses :
ligne 16 :
printfpermet d'envoyer une chaîne contenant du formatage et ainsi de leak des données en mémoireligne 20 :
getsne vérifie pas la longueur de notre input, on peut donc faire un BufferOverflow
Le binaire à toutes les protections activées :
RELRO (Relocation Read-Only) est une protection qui rend la table GOT en lecture seule, empêchant ainsi les attaques de modification d’adresses de fonctions.
Canary est une valeur aléatoire placée avant le retour de pile pour détecter et empêcher les débordements de tampon.
NX (No-eXecute) est une protection qui marque certaines zones mémoire comme non exécutables, empêchant l'exécution de code injecté dans la pile ou le tas.
PIE (Position-Independent Executable) est une protection qui charge le binaire à une adresse aléatoire en mémoire à chaque exécution, rendant plus difficile la prédiction des adresses pour les attaques d’exploitation.
En sachant qu'on nous donne le fichier de la libc en même temps, c'est assez clair :
Se servir de
printfpour leak lecanarypour le remettre à la bonne place après notre BoF.Se servir de
printfpour leak l'adresse de lalibc.Faire une
ropchainpour lancer un shell depuis lalibcgrâce àsystemouexecve.
Patch du binaire
Pour utiliser la librairie fournie et éviter les problèmes de compatibilité, il faut patcher notre binaire. Pour ça, j'utilise pwninit. Le tool nécessite patchelf mais absolument rien de compliqué à installer.
Il suffit de mettre notre binaire et notre librairie dans le même dossier, puis on lance simplement
À partir de maintenant, on ne travaillera que sur task_patched.
Leak des valeurs - Canary
Commençons par trouver le canary dans la mémoire. On va break à 0x55555555526a (environ ligne 8 dans notre pseudo code C), c'est-à-dire quand il est mis dans RAX pour voir sa valeur.
Puisqu'on peut rentrer un maximum de 88 caractères dans printf, on va lancer plusieurs fois le binaire avec des formatages différents jusqu'à trouver notre canary dedans.
Ok, ici notre canary est 0xbda51d63af3c1a00, on ne l'a pas dans nos valeurs, on continue. Je skip de %11$p à %20$p car il n'y est pas non plus...
Ici notre canary est 0x4e5a7598b83abb00. Bingo, ça correspond à %25$p ! On peut désormais leak la valeur du canary pour la replacer plus tard au bon endroit et faire croire au programme que tout va bien.
Leak des valeurs - LIBC
On va réutiliser les valeurs qu'on a fait fuiter pour trouver le canary. Toutes les valeurs du type 0x7fffff... peuvent être l'adresse d'une fonction, on va donc toutes les tester avec la commande info symbol. (il existe d'autres façons de faire bien sûr).
Et hop ! Notre %27$p mène bien vers une adresse appartenant à la libc. Puisque l'adresse de base de la libc change à chaque lancement, mais que l'offset de cette adresse qu'on a leak est toujours la même par rapport à l'adresse de base, on pourra en déduire celle-ci !
Dans notre programme, l'adresse de base est 0x007ffff7dd5000. Nous avons leak l'adresse 0x7ffff7df9083. Le décalage est donc de 0x7ffff7df9083 - 0x007ffff7dd5000 =0x24083.
Ret2Libc avec ropchain
Maintenant que l'on peut déduire l'adresse de la libc et le canary, place à l'exploitation de gets. On commence par chercher combien de caractères il faut mettre pour arriver au canary, pour ça on part sur des patterns avec cyclic et on break à 0x55555555532d, pendant la vérification du canary pour connaître le pattern qui est dedans (c'est dans RCX qu'il faut regarder) :
On voit que c'est naaboaab qui est dans RCX, en cherchant l'offset, on trouve 152. Il faut donc 152 caractères avant d'arriver à remplir le canary.
Juste après le canary se situe EBP, il faut 8 octets et on s'en fout, donc on le remplira avec n'importe quoi.
Ensuite, ce sera RIP, c'est là que commence la Ropchain. Voici l'exploit au complet :
Mis à jour
Ce contenu vous a-t-il été utile ?