Incident de sécurité ? Suspicion de compromission ? 09 71 18 27 69csirt@synacktiv.com

UFC 666 : Frontkick vs Rikugan

Rédigé par Matthieu Breuil - 13/10/2026 - dans Outils - Téléchargement

Dans le coin droit : gratuit, open source, fort de 678 étoiles sur GitHub, champion incontesté de l'agentique sous IDA et prétendant sérieux sur Binary Ninja, voici Rikugan ! Face à lui, encore méconnu mais bien décidé à prendre la relève de son cousin Sidekick, voici Frontkick, un agent spécialisé pour Binary Ninja. Qui du ToolAgent ou du CodeAct l'emportera ? Que le combat commence !

Vous souhaitez améliorer vos compétences ? Découvrez nos sessions de formation ! En savoir plus

Boucle agentique : définition

Avant d'aborder le cas de Frontkick, il est bon de comprendre ce qu'est une boucle agentique et quels sont les enjeux pour créer un agent fonctionnel et efficace.

Une boucle agentique est une architecture dans laquelle on donne à un modèle un contexte initial, une tâche et des capteurs/actionneurs. Par la génération de tokens formatés selon un schéma, le modèle peut appeler ces capteurs/actionneurs. Les tokens de sortie générés par le modèle et les résultats des capteurs/actionneurs au tour N lui sont transmis en entrée des tours N+1, N+2, etc. Un actionneur spécifique permet de mettre fin à la boucle lorsque le modèle juge avoir accompli la tâche. D'autres conditions de sortie plus formelles peuvent être définies, telles que le nombre de tokens générés, le temps consommé, ou toute autre condition pertinente.

Le schéma ci-dessous illustre le fonctionnement standard d'une boucle agentique, où les actions du modèle sont réinjectées en contexte à chaque itération :

Schéma illustrant le fonctionnement d'une boucle agentique
Schéma illustrant le fonctionnement d'une boucle agentique

Boucle agentique : ToolAgent et CodeAgent

Les capteurs/actionneurs déclarés au modèle via le contexte initial peuvent répondre à deux modes d'action : les tools et le CodeAct. Ces deux approches donnent respectivement naissance aux architectures ToolAgent et CodeAgent.

ToolAgent

Les tools sont construits comme suit :

  • Une interface qui, par sa description, indique au modèle comment appeler le tool.
  • Un bloc de code qui effectue les actions et renvoie les résultats.

Bien souvent, l'interface est décrite en JSON. L'exemple suivant décrit un tool permettant de faire des recherches sur Internet :

Le code du tool :

import requests

def web_search(query: str) -> str:
    """Recherche sur DuckDuckGo et retourne un résumé."""
    res = requests.get(
        "https://api.duckduckgo.com/", params={"q": query, "format": "json"}
    ).json()

    return res.get("AbstractText") or "Aucun résultat synthétique trouvé."

La description de l'interface :

{
  "name": "web_search",
  "description": "Effectue une recherche sur le Web.",
  "parameters": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "La requête de recherche."
      }
    },
    "required": ["query"]
  }
}

Un exemple d'appel par le modèle (style OpenAI) :

[
  {
    "id": "call_abc123",
    "type": "function",
    "function": {
      "name": "web_search",
      "arguments": "{\"query\": \"Pourquoi Frontkick est si génial ?\"}"
    }
  }
]

Les intérêts de ce paradigme sont nombreux :

  • Sécurité : limite la surface d'attaque accessible au modèle.
  • Fiabilité : les arguments sont validés par un schéma, ce qui permet de détecter les erreurs de syntaxe.
  • Simplicité d'infrastructure : s'exécute directement dans votre application sans nécessiter de sandbox isolée.
  • Observabilité : les appels de fonctions structurés génèrent des journaux clairs, faciles à tracer et à analyser.
  • Contrôle humain : interception simple des actions critiques (ex. suppression, paiement) avant exécution.
  • Efficacité : pour des tâches simples ou bien définies, générer un objet JSON consomme moins de tokens que de rédiger un script Python complet.

CodeAgent

D'un autre côté, le paradigme CodeAct laisse au modèle, comme interface principale, un environnement d'exécution de code (souvent Python). Le modèle peut ainsi exécuter du code placé entre deux balises de repérage (par exemple <code> et </code>).

Ainsi, si l'on reprend l'exemple précédent, le modèle génère :

<code>
import requests

def web_search(query: str) -> str:
    url = "https://api.duckduckgo.com/"
    res = requests.get(url, params={"q": query, "format": "json"}).json()
    return res.get("AbstractText") or "Aucun résultat synthétique."

resultat = web_search("Pourquoi Frontkick est si génial ?")
print(resultat)
</code>

Les avantages de ce paradigme sont également multiples :

  • Expressivité : permet de combiner boucles, conditions et traitements complexes au sein d'un même script.
  • Réduction des tours de boucle : enchaîne des actions séquentielles en un seul tour de modèle, ce qui réduit la latence.
  • Économie de contexte : traite et filtre les données brutes directement dans la sandbox au lieu de surcharger la fenêtre de contexte.
  • Extensibilité dynamique : capacité à écrire ses propres fonctions ou à importer des bibliothèques sans déclaration préalable.
  • Auto-correction : exploite les tracebacks réinjectées pour déboguer le code de manière autonome.
  • Puissance applicative : donne un accès direct à tout l'écosystème Python (bibliothèque standard et modules externes).

Cette page Huggingface est très instructive quant à ce paradigme, et comment implémenter des CodeAgents avec leur bibliothèque : smolagent.

Le paradigme privilégié

Anthropic, OpenAI et leurs cousins privilégient le ToolAgent principalement pour des raisons de sécurité, de gouvernance et de scalabilité industrielle. Exécuter du code arbitraire (CodeAct) à l'échelle de millions d'utilisateurs exige d'isoler chaque session dans des sandboxes lourdes et coûteuses, tout en exposant les systèmes à des risques accrus. Le ToolAgent offre à l'inverse un contrôle d'accès strict, une auditabilité totale des actions et une intégration directe avec les architectures API existantes.

Pour combler l'écart de flexibilité avec le CodeAct, les éditeurs déploient d'importants efforts d'ingénierie :

  • Structured Outputs : garantit un respect à 100 % des schémas JSON/Pydantic, éliminant les erreurs de syntaxe.
  • Parallel Tool Calling : entrainement natif des modèles à planifier et exécuter plusieurs actions indépendantes en un seul tour de génération.
  • Standardisation des protocoles : création de normes d'interopérabilité pour connecter n'importe quelle API ou base de données de façon plug-and-play.
  • Tool Retrieval : techniques de RAG appliquées aux fonctions pour permettre à un agent de choisir le bon outil parmi un catalogue de milliers d'APIs sans engorger la fenêtre de contexte. Le Retrieval-augmented generation étant le fait d'associer un LLM à une base de données de référence ; dans notre cas des scripts Binary Ninja.

Frontkick : L'agent qui va à contre-courant

Même si des approches basées sur le ToolAgent (comme Rikugan) ont prouvé leur efficacité en rétro-ingénierie, Frontkick fait le pari du CodeAgent. Frontkick s'exécute directement dans l'environnement Python de Binary Ninja et manipule son API native.

Ce choix d'architecture repose sur deux enjeux majeurs : la flexibilité et la maintenabilité.

La flexibilité face à l'immensité de l'API

L'API de Binary Ninja est riche en fonctionnalités : elle couvre la manipulation des différents niveaux d'IL (LLIL, MLIL, HLIL), la gestion des types, l'analyse mémoire, les xrefs ou encore l'interaction avec le désassembleur.

Plutôt que d'abstraire chaque action derrière un tool JSON dédié (get_function, get_xrefs, rename_symbol), Frontkick donne au modèle un accès direct au runtime Python de Binary Ninja. L'agent peut ainsi composer lui-même la logique dont il a besoin pour naviguer dans des milliers d'instructions ou croiser des structures complexes en une seule exécution, et ce sur tous les binaires ouverts dans l'application.

La maintenabilité de l'agent

Wrapper une API aussi vaste que celle de Binary Ninja dans des schémas JSON impose un coût de maintenance considérable : chaque évolution du décompilateur nécessite de mettre à jour, tester et redéployer des dizaines de tools.

En adoptant le CodeAct, l'infrastructure de Frontkick reste minimale. C'est le modèle qui s'adapte directement à l'API Python de Binary Ninja, tirant parti de la documentation existante et des capacités naturelles de développement du LLM.

Un script exécuté dans le contexte de Binary Ninja

Concrètement, l'agent génère du code Python exécuté directement sur une BinaryView (bv) préservée dans son contexte :

# Recherche et renommage des fonctions appelant une routine spécifique
target = bv.get_functions_by_name("check_license")[0]
for caller in target.callers:
    caller.name = f"auth_handler_{caller.start:x}"
    print(f"Renommé : {caller.name}")

Concrètement, comment fonctionne Frontkick

Pour maintenir des performances optimales sur de longues sessions d'analyse, Frontkick combine trois mécanismes clés de gestion de contexte et de connaissances. La réduction progressive des anciens tours (shrinking) tronque le contenu des étapes passées, tandis que la compaction de la tâche résume l'historique dès que la fenêtre de contexte est saturée, tout en verrouillant la consigne initiale pour éviter toute dérive. En parallèle, un RAG basé sur un corpus de recettes Python vérifiées vient ancrer la génération de code dans la réalité de l'API de Binary Ninja. Ce corpus a été généré via un modèle capable (Opus 5.5).

Le diagramme suivant détaille la boucle d'exécution de Frontkick, mettant en évidence ses stratégies de shrinking, de compaction et son RAG intégré :

Diagramme de la boucle d'exécution de Frontkick
Diagramme de la boucle d'exécution de Frontkick

Le schéma ci-dessus illustre la boucle complète, on y retrouve :

  • l'injection du prompt initial, combinant les instructions statiques, et quelques faits dynamiques comme les bibliothèques présentes dans l'interpréteur ou les binaires déjà chargés ;
  • l'obligation pour le modèle de générer un bloc de code après deux tours sans en générer ;
  • l'injection de recettes provenant du RAG dans le retour au modèle si le code exécuté produit une erreur ;
  • la stratégie de tronquage, qui consiste à ne garder que 500 caractères pour les étapes plus anciennes que N-4 ;
  • l'injection des trouvailles enregistrées par le modèle dans l'entrée du tour suivant ;
  • le rappel quant à l'obligation de produire du code dans un tour, et d'éviter de résoudre les problèmes par la parole : code over prose.

Une note importante : la stratégie de shrinking actuelle garde une fenêtre des 4 tours les plus récents sans modification et tronque à partir du 5ème tour. Ce qui induit qu'à partir de 5 tours, chaque boucle va tronquer une étape. Ce n'est pas efficient au vu des techniques de cache des moteurs d'inférence. La stratégie sera améliorée, en groupant par exemple les tronquages par X tours.

Cette gestion dynamique du contexte (qui gère la mémoire à long terme de l'agent) est complétée par un ensemble de prompts (qui cadre la génération à court terme et long terme) pour donner son caractère unique à l'agent.

Le schéma ci-dessous illustre l'architecture et le pipeline d'assemblage de ces prompts avant chaque appel au LLM :

Architecture et pipeline d'assemblage des prompts
Architecture et pipeline d'assemblage des prompts

Les points importants :

  • Le prompt est construit selon les recommandations de Qwen en mode CO-STAR : on utilise des marqueurs peu présents dans le corpus pour définir différentes sections dédiées à un but précis (contexte, format des résultats souhaité, audience, etc.).
  • Afin de profiter au maximum des fonctionnalités de Binary Ninja, les différentes bibliothèques Python présentes par défaut sont renseignées dans le prompt.
  • Afin de bénéficier d'un démarrage plus rapide, les binaires déjà ouverts sont renseignés avec des informations de base (nom, architecture, taille, etc.).

Autres agents Binary Ninja

Présentation des autres agents pour Binary Ninja
Produit Origine Source Inclus dans ce comparatif
Sidekick Vector 35 (officiel) Propriétaire (fermé) Non (pas d'accès aux mécanismes internes)
Rikugan Plugin communautaire Open source Oui (vérifiable)

Ces deux agents ont fait le choix du ToolAgent. Leur paradigme est donc différent de celui de Frontkick.

Comparatif des fonctionnalités

Tableau comparatif des fonctionnalités entre Frontkick et Rikugan
Fonctionnalité Frontkick Rikugan
Outils intégrés execute_python (action principale), search_recipes, spawn_subagent 63+ outils natifs
Validation par action Aucune (exec brut) Validation par schéma avant exécution
Intégration d'outils externes — Gestionnaire MCP
Procédures réutilisables Corpus de recettes (RAG) Registre de compétences (skills), 12 intégrés¹
Templates de prompts Macros nommées (invoquées par l'utilisateur) —
Multi-agent spawn_subagent (niveau unique) Création de sous-agents
Gestion de l'état / Planification Deux outils pour ajouter ou retirer des faits. Ceux-ci sont automatiquement intégrés aux prompts. Objet KnowledgeBase
Mémoire inter-sessions — RIKUGAN.md (rechargé par binaire)
API de scripting Oui — documentée (frontkick.api) Oui — non documentée (découverte via le code source)

Évaluation et Benchmark — CREBench

Afin de comparer Rikugan et Frontkick, deux cas de test du benchmark CREBench ont été retenus. CREBench permet d'évaluer des modèles sur des tâches de rétro-ingénierie et de cryptanalyse. Pour chaque cas de test, fourni sous la forme d'un binaire strippé, les modèles doivent identifier l'algorithme de chiffrement et la clé, puis réimplémenter une routine de déchiffrement pour retrouver le flag. Notre configuration de test est la suivante :

  • Le modèle choisi est Claude Sonnet 5.5 : suffisamment puissant pour ne pas buter sur la forme (comment appeler les outils), mais plutôt pour évaluer le fond (quel jeu d'outils et quel prompt sont les plus efficaces).
  • Les cas de test sont AES-128-CBC et ChaCha20, en configuration hardcode_plain/O0, avec 4 répétitions par cas et une limite maximale de 1M de tokens (entrée/sortie et tours cumulés).

Le graphique ci-dessous résume les performances comparées entre Frontkick et Rikugan sur les deux tâches du benchmark :

Graphiques des résultats du benchmark
Graphiques des résultats du benchmark

Les résultats sont en faveur de Frontkick : que ce soit sur le nombre de tokens dépensés, 2x moins en moyenne, ou le score de réussite qui est presque 3x supérieur.

Cependant, l'inspection des journaux d'exécution (transcripts) confirme un biais important : sur AES-128-CBC, Rikugan tente systématiquement d'importer from Crypto.Cipher import AES (bibliothèque pycryptodome, non installée). Après cet échec, il réimplémente l'algorithme à la main, octet par octet, sans jamais utiliser cryptography (pourtant installée et exploitée par Frontkick à chaque essai). Résultat : 31 à 35 tours et ~1M de tokens côté Rikugan, contre 15 à 24 tours et ~400K tokens côté Frontkick pour la même tâche.

Frontkick bénéficie ici d'un mécanisme dédié : un bloc Available libraries injecté dynamiquement dans son prompt system, listant les bibliothèques réellement disponibles. Rikugan tente de deviner une bibliothèque au lieu d'en avoir la liste explicite.

Ce benchmark ne démontre donc pas une supériorité intrinsèque du CodeAct sur ce test précis, mais plutôt l'impact décisif d'une astuce d'ingénierie de prompt. Dans une étude ultérieure, il serait pertinent de relancer ce benchmark en ajoutant l'injection dynamique des bibliothèques au prompt system de Rikugan. Les prompts initiaux étant alors alignés, le mode d'appel des outils (ToolAgent vs CodeAct) deviendrait le facteur différenciant principal.

Pour plus d'exhaustivité, voici le tableau détaillant les résultats run par run :

Résultats détaillés du benchmark CREBench par exécution
Cas d'usage / Run Métrique frontkick rikugan
AES-128-CBC (run1) Tokens (↓) 1 007 262 1 021 773
Temps écoulé (s) (↓) 664,1 460,0
Nombre de tours (↓) 42 34
Score / 100 (↑) 0,0 0,0
Efficacité (↑) 0,0 0,0
AES-128-CBC (run2) Tokens (↓) 292 800 1 006 836
Temps écoulé (s) (↓) 171,9 770,6
Nombre de tours (↓) 15 33
Score / 100 (↑) 100,0 25,0
Efficacité (↑) 34,2 0,6
AES-128-CBC (run3) Tokens (↓) 321 758 1 036 767
Temps écoulé (s) (↓) 229,3 610,4
Nombre de tours (↓) 17 35
Score / 100 (↑) 100,0 0,0
Efficacité (↑) 31,1 0,0
AES-128-CBC (run4) Tokens (↓) 476 364 1 008 528
Temps écoulé (s) (↓) 176,5 418,5
Nombre de tours (↓) 24 31
Score / 100 (↑) 100,0 25,0
Efficacité (↑) 21,0 0,6
ChaCha20 (run1) Tokens (↓) 662 011 818 209
Temps écoulé (s) (↓) 384,3 311,2
Nombre de tours (↓) 32 28
Score / 100 (↑) 87,5 87,5
Efficacité (↑) 11,6 9,4
ChaCha20 (run2) Tokens (↓) 914 565 1 034 160
Temps écoulé (s) (↓) 560,7 476,5
Nombre de tours (↓) 39 32
Score / 100 (↑) 100,0 0,0
Efficacité (↑) 10,9 0,0
ChaCha20 (run3) Tokens (↓) 591 089 639 219
Temps écoulé (s) (↓) 314,3 252,8
Nombre de tours (↓) 28 24
Score / 100 (↑) 100,0 87,5
Efficacité (↑) 16,9 12,0
ChaCha20 (run4) Tokens (↓) 542 537 1 013 142
Temps écoulé (s) (↓) 381,3 452,6
Nombre de tours (↓) 26 33
Score / 100 (↑) 100,0 25,0
Efficacité (↑) 18,4 0,6

Conclusion : Le verdict des juges

Et au terme de ce premier round, les juges rendent leur verdict : égalité technique ! Si Frontkick assène un bel uppercut à Rikugan en maîtrisant sa consommation de tokens et le nombre de tours, le KO n'est pas encore prononcé en faveur du CodeAct.

L'inspection des replays le prouve : la victoire de Frontkick repose ici davantage sur une ruse d'ingénierie dans son prompt — l'injection dynamique des bibliothèques disponibles — que sur une supériorité intrinsèque de son architecture.

Pour savoir si le CodeAct mettra définitivement le ToolAgent au tapis sur Binary Ninja, il faudra attendre la revanche à armes égales, avec des prompts de départ parfaitement alignés. Une chose est sûre : le combat des agents ne fait que commencer !