L'instrumentation binaire dynamique (DBI) est une technique fondamentale en rétro-ingénierie et en sécurité offensive qui permet d'observer et de modifier le comportement d'un programme en cours d'exécution, sans accès au code source et sans recompilation. Les deux frameworks dominants — Frida et DynamoRIO — offrent des approches complémentaires : Frida privilégie la simplicité avec une API JavaScript/Python injectable dans les processus, tandis que DynamoRIO fournit un contrôle instruction-level avec une instrumentation C/C++ haute performance. Ce guide technique couvre les architectures internes de ces frameworks, leurs API d'instrumentation, les cas d'usage offensifs (hooking de fonctions, bypass de protections, fuzzing guidé, évasion de détection) et défensifs (analyse de malware, reverse engineering de protocoles), avec des exemples de code complets et des techniques avancées comme le stalking, le code replacement et l'anti-anti-debug.

En bref

  • Frida : injection, hooking JavaScript, Interceptor, Stalker et CModule
  • DynamoRIO : architecture, basic block instrumentation, drmemtrace et DrCov
  • Cas d'usage offensifs : bypass SSL pinning, anti-tamper, DRM et EDR evasion
  • Analyse de malware : API tracing, unpacking automatique et protocole reversing
  • Fuzzing guidé par instrumentation : AFL+DynamoRIO, Frida+fuzzing, coverage-guided
Instrumentation Binaire Dynamique (DBI) — Technique consistant à injecter du code d'observation et de modification dans un programme en cours d'exécution. Le framework DBI interpose une couche de traduction entre le CPU et le programme, permettant d'inspecter et modifier chaque instruction, chaque appel de fonction et chaque accès mémoire en temps réel.

Frida : Architecture et Injection

Frida injecte un agent JavaScript (runtime QuickJS ou V8) dans le processus cible. L'architecture est client-serveur : le script Python/Node.js côté contrôle communique avec l'agent JavaScript injecté dans le processus cible via un canal IPC. Frida supporte Windows, Linux, macOS, iOS, Android et peut instrumenter des processus natifs, Java (Android/JVM), Objective-C (iOS/macOS) et .NET.

#!/usr/bin/env python3
# Frida — Hooking d'une fonction avec interception des arguments
import frida, sys

# Script JavaScript injecté dans le processus cible
jscode = """
Interceptor.attach(Module.getExportByName('libssl.so', 'SSL_write'), {
    onEnter: function(args) {
        // args[0] = SSL* ctx, args[1] = buffer, args[2] = length
        var len = args[2].toInt32();
        var buf = Memory.readByteArray(args[1], Math.min(len, 256));
        console.log('[SSL_write] ' + len + ' bytes:');
        console.log(hexdump(buf, {header: true, ansi: true}));
        
        // Sauvegarder le contexte pour onLeave
        this.buf = args[1];
        this.len = len;
    },
    onLeave: function(retval) {
        console.log('[SSL_write] returned: ' + retval);
    }
});

// Hooking Java sur Android
Java.perform(function() {
    var TrustManager = Java.use('javax.net.ssl.X509TrustManager');
    TrustManager.checkServerTrusted.implementation = function(chain, authType) {
        console.log('[*] SSL Pinning bypassed!');
        // Ne rien faire = accepter tous les certificats
    };
});
"""

# Attacher au processus
session = frida.attach("target_app")
script = session.create_script(jscode)
script.on('message', lambda msg, data: print(msg))
script.load()
sys.stdin.read()

Frida Stalker : Tracing Instruction-Level

Le Stalker de Frida est un traceur d'instructions qui suit l'exécution instruction par instruction. Il utilise la réécriture de code (code rewriting) : chaque basic block est copié, instrumenté avec du code de tracing, et exécuté à la place de l'original. Le Stalker supporte x86, x64, ARM et ARM64 :

// Frida Stalker — tracer toutes les instructions d'un thread
var mainThread = Process.enumerateThreads()[0];

Stalker.follow(mainThread.id, {
    events: {
        call: true,    // Tracer les CALLs
        ret: true,     // Tracer les RETs
        exec: false,   // Ne pas tracer chaque instruction (performance)
        block: true,   // Tracer les basic blocks
    },
    
    onCallSummary: function(summary) {
        // summary = {target_addr: call_count, ...}
        for (var addr in summary) {
            var sym = DebugSymbol.fromAddress(ptr(addr));
            if (sym.name) {
                console.log(sym.name + ' called ' + summary[addr] + ' times');
            }
        }
    },
    
    transform: function(iterator) {
        var instruction;
        while ((instruction = iterator.next()) !== null) {
            // Modifier les instructions à la volée
            if (instruction.mnemonic === 'rdtsc') {
                // Remplacer rdtsc par des valeurs fixes (anti-timing)
                iterator.putCallout(function(context) {
                    context.eax = 0x12345678;
                    context.edx = 0x00000001;
                });
            } else {
                iterator.keep();
            }
        }
    }
});

DynamoRIO : Instrumentation Haute Performance

DynamoRIO est un framework DBI C/C++ développé par Google, optimisé pour la performance. Contrairement à Frida (injection + scripting), DynamoRIO agit comme un process virtual machine : il traduit chaque basic block du programme avant exécution, insérant l'instrumentation dans le flux de code traduit. Cette approche est plus rapide que le hooking de Frida pour l'instrumentation massive.

// DynamoRIO — Client d'instrumentation : compter les basic blocks
#include "dr_api.h"
#include "drmgr.h"

static int bb_count = 0;
static void *count_mutex;

// Callback appelé pour chaque basic block
static dr_emit_flags_t
event_bb(void *drcontext, void *tag, instrlist_t *bb,
         bool for_trace, bool translating) {
    
    instr_t *first = instrlist_first(bb);
    
    // Insérer un appel à notre fonction de comptage
    dr_insert_clean_call(drcontext, bb, first,
                         (void *)increment_count,
                         false /* no fp save */, 0);
    
    return DR_EMIT_DEFAULT;
}

static void increment_count(void) {
    dr_mutex_lock(count_mutex);
    bb_count++;
    dr_mutex_unlock(count_mutex);
}

DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) {
    count_mutex = dr_mutex_create();
    drmgr_init();
    drmgr_register_bb_instrumentation_event(NULL, event_bb, NULL);
    dr_log(NULL, LOG_ALL, 1, "BB counter initialized\n");
}

Cas d'Usage Offensifs

  • SSL Pinning Bypass : Frida intercepte les fonctions de validation SSL/TLS (iOS: SecTrustEvaluate, Android: checkServerTrusted) pour accepter tous les certificats — essentiel pour le pentest d'applications mobiles
  • Anti-tamper/Anti-debug Bypass : hooker les appels système de détection (ptrace, IsDebuggerPresent, timing checks) pour neutraliser les protections des malwares et des applications protégées
  • EDR Evasion Research : instrumenter les hooks EDR userland (ntdll.dll) pour comprendre ce qui est surveillé et identifier les gaps de couverture
  • Game Hacking / DRM Bypass : modifier la logique des validations de licence et les protections DRM en mémoire
  • Protocol Reversing : tracer les entrées/sorties réseau pour reconstruire des protocoles propriétaires

Fuzzing Guidé par Instrumentation

DynamoRIO et Frida sont utilisés comme backends de couverture pour le fuzzing : au lieu de compiler le programme avec la couverture (source-based), le DBI instrumente le binaire à la volée pour collecter la couverture de code. WinAFL utilise DynamoRIO, Frida-fuzzer utilise le Stalker de Frida. L'avantage : fuzzer des binaires closed-source sans accès au code source ni recompilation.

Frida vs DynamoRIO : Choix du Framework

CritèreFridaDynamoRIO
LangageJavaScript/Python (simple)C/C++ (performance)
InjectionInjection dans process existantLancement sous DynamoRIO
Performance~2-5x slowdown (hooking)~1.5-3x (translation)
MobileiOS + Android natifAndroid (limité)
Cas d'usageHooking, pentest mobile, REFuzzing, taint analysis, profiling
Stalking/TracingStalker (flexible)drmemtrace (rapide)
💡 Conseil pratique — Pour le pentest mobile, Frida est incontournable. Utilisez frida-tools (pip install frida-tools) pour un accès rapide : frida-trace -U -i 'SSL*' com.target.app trace automatiquement toutes les fonctions SSL de l'application. Le repo frida-codeshare contient des scripts prêts à l'emploi pour le SSL pinning bypass, le root detection bypass et le jailbreak detection bypass.

À retenir

  • Frida = injection JavaScript dans n'importe quel processus avec hooking de fonctions, tracing et modification mémoire
  • DynamoRIO = process virtual machine C/C++ avec instrumentation instruction-level haute performance
  • Le Stalker de Frida permet le tracing instruction-level avec réécriture de code à la volée
  • Frida est le standard pour le pentest mobile (SSL pinning bypass, root detection bypass)
  • DynamoRIO est le standard pour le fuzzing closed-source (WinAFL) et l'analyse de performance
  • Les deux frameworks supportent l'anti-anti-debug en hookant les fonctions de détection

FAQ — Questions Fréquentes

Frida est-il détectable par les applications ?

Oui, les applications protégées détectent Frida via plusieurs mécanismes : présence de frida-server dans les processus, port 27042 (default Frida), strings 'frida' en mémoire, et hooks sur les fonctions de détection elles-mêmes. Les techniques d'évasion incluent : recompiler frida-server avec un nom différent, changer le port, utiliser le mode 'gadget' (injection via library loading) et hooker les fonctions de détection avant qu'elles ne s'exécutent.

Quelle est la différence entre Frida et un debugger ?

Un debugger (GDB, LLDB, x64dbg) arrête l'exécution à des breakpoints et permet l'inspection pas à pas. Frida instrumente le programme sans l'arrêter — le hooking est transparent et l'application continue de s'exécuter normalement. Frida est plus adapté à l'instrumentation massive (tracer des milliers d'appels) et à la modification de comportement à la volée, tandis qu'un debugger est meilleur pour l'analyse fine d'un crash ou d'un bug.

DynamoRIO peut-il instrumenter des programmes Windows ?

Oui, DynamoRIO supporte Windows, Linux et Android. Sur Windows, il est le backend de WinAFL (le fuzzer de référence pour les binaires Windows). DynamoRIO peut instrumenter des programmes 32-bit et 64-bit, des DLLs, et même des services Windows. Il est particulièrement efficace pour le fuzzing de parsers (PDF, Office, navigateurs) sur Windows.

Besoin d'un accompagnement expert ?

Nos consultants spécialisés en reverse engineering et sécurité applicative vous accompagnent dans l'évaluation de votre posture de sécurité.

Contactez-nous
Article recommandé : ETW Tampering : Évasion et Détection sur Windows