MazeOfPower

Catégorie: Reverse Difficulté: insane Flag: HTB{by_th3_p0w3r_0f_th3_m4z3!!1}

Challenge

file-archive
1MB
circle-info

Description


MazeOfPower is an Insane reversing challenge. Players will first reverse engineer a Golang binary containing a maze game. They must identify a backdoor built into the game, and abuse it to win on the server.

circle-exclamation

Analyse du binaire

Dans un logiciel de décompilation, direction main.main car c’est du Go.

Challenge Proof of Work

On trouve un appel à la fonction GenerateChallenge du module github.com/redpwn/pow

Si l’on se rend sur le github, on y trouve l’objectif du module et son fonctionement. On ne va pas réinventer la roue et regarder comment le challenge se résout.

Le module utilise gmp, comme je suis sur Windows et que c’est une galère à installer, j’ai recoder la fonction rapidemment en Python. (Sans module pour optimiser le traitement, mon ordi prend environ 20s à le résoudre)


Calculer la seed de l’aléatoire

Si l’on fait bien attention, quelques lignes après, un appel à math/rand.Seed est effectué, et cet appel est précédé étrangement de :

  • ReadString pour récupérer notre solution au challenge PoW

  • stringtoslicebyte pour transformer une string en bytes

  • hash/crc32.ChecksumIEEE pour calculer un checksum de bytes et qui retourne un entier

Effectivement, quel hasard.

Un petit tour dans GDB avec des breakpoint juste avant ces fonctions nous confirme les paramètres qui leur sont passés.

  1. On commence avec un break sur stringtoslicebyte qui confirme que c’est bien la solution au challenge PoW qui est passée en paramètre :

  1. Ensuite on passe bien le résultat de stringtoslicebyte à la fonction de checksumIEEE, à noter le ajouté à la fin :

  1. Enfin, rand.Seed qui est appelé. La fonction utilise RAX et dans RAX on a bien le résultat du checksumIEEE

On en conclu donc que la seed est le résultat du checksumIEEE sur la solution de notre challenge (avec \n un à la fin)

En python ça nous donne :


Résoudre le labyrinthe

Une fois le PoW passé et la seed de l’aléatoire cassée, on termine dans un labyrinthe sans voir les murs. Heureusement, on voit que celui-ci est généré grâce au module github.com/itchyny/maze

On peut alors explorer le github et voir que le créateur implément également une fonction de résolution. On va simplement la copier coller et la modifier un peu pour récupérer le chemin à faire en texte.

On en profite aussi pour prendre en argument la seed de l’aléatoire et générer le même labyrinthe.

Concernant la taille du labyrinthe, soit on le calcul à la main avec ce que le binaire affiche, soit on le trouve dans le code, c’est 0x19 et 0x32 , autrement dit 25 de hauteur par 50 de largeur


Script de résolution

Pour résoudre le challenge, je suis parti sur du python qui appelle le Go pour récupérer la solution au labyrinthe

Mis à jour