Age of Empire II

Introduction

Après avoir trouvé une vulnérabilité sur Age Of Empire I on peut se demander si la même vulnérabilité est présente sur Age Of Empire II ( Gold Edition ). L’environnement de test à mettre en place est le même que celui décrit dans l’article précédent.

Age of Empires II Gold Edition - Version 0.14.22.712

Protocole réseau

On commence par lancer deux VMs, une pour héberger une partie et une pour s’y connecter, ainsi que wireshark en parallèle. Un rapide coup d’oeil dans l’interface multijoueur montre que le jeu repose aussi sur DirectPlay.

Lorsqu’on regarde la capture, et plus précisément le paquet Enum Session Reply, il y’a une légère différence par rapport à celui produit par Age Of Empire I :

Le nom de session n’est plus encodé en utf-16 mais utilise la table ASCII étendue. Il y’a un octet null qui sépare le nom de session du nom de joueur entre crochets. D’ailleurs Wireshark décode mal le nom de session en “Pri eJuu”.

Quick win

On reprend le script d’exploit de Age Of Empire I pour envoyer un nom de session de 0x500 octets (en ascii étendu)

pkt = BuildEnumSessionReply( b"A" * 0x500)

Et c’est la quick win !

Le programme crash avec EIP qui vaut 41414141h, on contrôle pleinement l’adresse de retour. Si l’on remonte un peu les adresses de stack on remarque que notre SessionName est concaténé avec la chaîne “Restauration”. Malheureusement le debugger ne donne pas l’adresse de l’instruction qui a fait planter le programme. On va essayer de remonter à la cause du crash, grâce à la chaîne trouvée dans la stack.

La vulnérabilité

Lorsqu’on ouvre le binaire EMPIRE2.EXE avec IDA, grande surprise celui-ci est lourdement obfusqué …

Le jeu est protégé par SafeDisc1, EMPIRE2.EXE n’est qu’un loader chargé de déchiffrer le code du jeu contenu dans le fichier EMPIRE2.ICD. On peut dumper le binaire en mémoire mais la table des imports est aussi obfusquée. En ce dimanche de flemme, j’ai récupéré un patch no-cd Age Of Empire II qui est une version déchiffrée de EMPIRE2.ICD.

La chaîne “Restauration” reste introuvable dans EMPIRE2.ICD. Intéressons nous aux ressources embarquées par l’exécutable et ses dlls. L’utilitaire Ressource Hacker2 permet de parcourir les ressources. Une DLL nommée LANGUAGE.DLL contient des tables de strings pour toutes les langues du jeu. Ainsi on retrouve notre chaîne qui a l’ID 9218 (soit 2402h).

Une recherche textuelle dans IDA sur 2402h permet de retrouver le code qui utilise la chaîne.

Comme dans Age Of Empire I le nom de session est copié dans un buffer local de taille fixe via un sprintf, aucun contrôle n’est fait sur la taille de la chaîne. Lorsque le nom de session ne contient pas de username entre crochets, il est concaténé avec la chaîne “Restauration”. Dans l’autre cas, le code reste tout de même vulnérable car un sprintf copie le nom de session dans un même buffer. Dans le premier cas il faut envoyer 1151 bytes pour écraser l’adresse de retour de la fonction sub_004EE2B0.

Exploitation

L’exploitation est encore plus trivale que dans Age Of Empire I car seul le null byte est interdit. Cela nous empeche de sauter directement sur la stack, ou dans un bout de code de EMPIRE2.ICD. Mais un gadget jmp esp permet de sauter directement sur notre shellcode placé après l’adresse de retour. On ajoute un peu de padding derrière notre shellcode car les derniers octets de la chaine semblent être écrasés en sortie de fonction.

BOF, jmp esp et c’est la calc qui pop \o/

Références

  1. http://blog.w4kfu.com/tag/safedisc
  2. http://www.angusj.com/resourcehacker/