Frida, la nouvelle amie des reversers et hackers
Publié le 6 mars 2015

Il y a peu de temps, j’ai découvert Frida, un outil permettant de faire de l’instrumentation minimaliste de binaire sous Windows, Linux, iOS et Android. Rien que cela. Moi qui suis habitué du reverse à l’ancienne et de l’attaque à coup d’injection de code via des DLLs, ça m’a de suite intéressé.

Tante Frida aime le JavaScript

Frida repose sur l’injection d’un module dynamique dans un processus actif, et crée un canal de communication avec celui-ci. L’outil propose ensuite d’interagir en Python, à l’aide de bindings relativement bien conçus.

Le point intéressant (mais toutefois limitant) est que l’on peut pratiquer le détournement de fonctions et l’appel de fonctions en scriptant cela en JavaScript. Car oui, le module injecté embarque un moteur JavaScript reconnu (v8, merci Google) qui sera utilisé dans le cadre du détournement ou de l’appel de fonctions. Tout ça à partir de Python.

A ce moment là, j’ai posé un bémol sur cet outil. Employer JavaScript me posait un problème : le langage est très éloigné de l’assembleur, et je n’imaginais pas vraiment ce que l’on pouvait en tirer. J’ai poursuivi ma découverte de l’outil, et ai revu mon jugement.

Hooking simple avec Frida

Le hooking de fonctions c’est galère. Il faut développer en C des fonctions d’interception, injecter un module s’occupant de mettre en place le détournement (en prenant en compte toutes les contraintes liées à cela), mais surtout trouver un moyen d’afficher des information. Par exemple à grand renfort d’appels à MessageBoxA sous Windows.

C’est là que Frida sauve la vie. L’outil propose très simplement de placer un hook sur une fonction, et de définir une fonction de rappel en JavaScript qui se verra passer les arguments et pourra les traiter. Cela se traduit par un simple code Python intégrant un peu de JavaScript :

  1. import frida
  2. import sys
  3.  
  4. process = frida.attach("hello")
  5. script = process.session.create_script("""
  6. Interceptor.attach(ptr("%s"), {
  7. onEnter: function(args) {
  8. send(args[0].toInt32());
  9. }
  10. });
  11. """ % int(sys.argv[1], 16))
  12. def on_message(message, data):
  13. print(message)
  14. script.on('message', on_message)
  15. script.load()
  16. sys.stdin.read()

Télécharger

Du coup, ce qui était laborieux et pénible à développer est désormais beaucoup plus simple. Certes, on ne peut pas tout faire avec, mais on gagne un temps fou pour des choses relativement simples.

ImpRec en mode Frida

Lorsque je suis tombé sur cet outil, j’avais besoin de faire des bidouilles spécifiques avec des binaires, dont notamment de la reconstruction d’imports dans un PE. Là encore, Frida aide amplement. Tout d’abord, Frida permet de lister les modules actifs, et les fonctions exportées : pratique dans le cadre de la reconstruction d’imports. Ensuite, Frida permet d’accéder à la mémoire de manière relativement simple, et directement en Python.

De là, on imagine facilement un code en Python permettant de dresser un dictionnaire des exports et des fonctions associées :

  1. exports_address = {}
  2. for module in target.enumerate_modules():
  3. for export in module.enumerate_exports():
  4. addr = module.relative_address + module.base_address
  5. export_address[addr] = (module.name, export.name)

Télécharger

Pour la recherche d’une IAT par exemple, on peut aisément se baser sur la méthode read_bytes de l’objet matérialisant le processus courant :

  1. from struct import unpack
  2. ...
  3. dword = unpack('<I', target.read_bytes(0x403000, 4))[0]

Télécharger

En bref

Frida s’installe en deux temps trois mouvements, même sous Windows. Frida peut permettre le développement rapide d’outils liés au reverse-engineering voire à l’analyse dynamique de binaires ou à leur compromission. Frida se base sur du Python ("cool !") et du JavaScript ("moins cool."). Mais Frida est bougrement efficace.

A ajouter dans la trousse à outil de tout hacker/reverser/bidouilleur de PE.

(crédits image : www.frida.re + gimp)