Le deuxième acte : la chimère au BreizhCTF

Cet article est la suite directe de mon retex sur le stunt au 404CTF 2026 :

Le contexte, le setup technique de la chimère et le débat de fond sont dans le premier.

Ici je me concentre sur ce qui change quand on rejoue à un autre format, sur un autre événement, dans un autre cadre vis-à-vis de l’IA.


Le contexte

Deux semaines après le 404CTF, direction Rennes pour le BreizhCTF. 4ème année que j’y vais. C’est devenu un rendez-vous.

Une bonne occasion de revoir noobosaurus, thelaluka, penthium2, pierreadams (note à moi meme : ne jamais commencé une liste quand il y a trop de monde) – et d’en rencontrer plein d’autres pour la première fois, ce qui est probablement la moitié de la valeur d’un on-site.

Cette fois, pas le même angle que le 404CTF. Je viens en équipe de 3 contre des équipes de 5, je suis le seul à pousser le curseur IA côté équipe qui s’occupe principalement des chall OSINT, gros big up à Ben et Malia, et il n’y a pas de règle qui l’interdit explicitement. Le terrain est différent : on-site, sur ~8h, le bruit ambiant, le café froid, la salle qui balance le son « FIRST BLOOD » de Counter-Strike à chaque premier sang.

C’est l’inverse du 404CTF dans tous les paramètres : pas en solo, pas chez moi, pas sans cadre temporel, et avec une posture organisation qui n’est pas la même vis-à-vis de l’IA.

Le retex express

MétriqueValeur
FormatOn-site, ~8h, équipe de 5
Setup IAMême setup qu’au 404CTF mais fait manuellement pendant l’épreuve avec 40 minutes de préparation pendant l’épr (Claude Opus + Codex partiel + skill CTFd), moi seul utilisateur IA dans l’équipe qui s’occupe des chall OSINT.
Challenges résolus31 / 57
Score final~10 750 pts
Rang final11ème / 116 équipes (top 10%)
First bloodsPlusieurs – dont Assistant InverseBreizh Ledger AppSoaperlipopetteSavoureux Filet
Catégories couvertesToutes sauf OSINT (abandonné en cours – choix d’équipe)
Pic de rang5ème (avant le gel du scoreboard en fin d’épreuve)

Un autre format, une autre dynamique

Là où le 404CTF était un sprint solo de 2h30 avec un objectif limpide (provoquer le débat), le BreizhCTF est un marathon collectif. Et ça change presque tout dans la manière de faire bosser une IA.

En solo chez soi, tu pilotes l’IA en temps réel, tu vois chaque sortie, tu corriges immédiatement les trajectoires. Sur 8h en équipe, c’est impossible de garder le même niveau d’attention. J’ai donc poussé beaucoup plus loin l’usage des sous-agents asynchrones : un agent par challenge, lancés en parallèle, qui rapportent quand ils ont fini. Ça a payé sur les wins déterministes (forensic, reverse avec source, crypto exploitable), et ça a saigné sur tout ce qui demandait de l’itération à l’aveugle – exactement le pattern décrit dans le retex 404CTF.

Le résultat : un taux de succès élevé quand le chemin existait dans le code/les artefacts, et des plantages francs sur les rabbit holes (un agent YAQACC bloqué 68 minutes à attendre passivement un monitor au lieu de piloter la session, un agent Glitch [2/3] qui balayait dans le vide, un agent No-thanks-AI bloqué sur la chaîne XSS verrouillée par CSP). À chaque fois, le diagnostic est le même : sans humain dans la boucle, l’IA tourne. Pareil qu’au 404CTF, mais à plus grande échelle.

Le flag qui rit jaune

Petite anecdote au passage : sur Allo Papa Tango Charlie (un crypto à 465 pts, oracle XOR récursif sur le flag – vuln élégante : envoyer une intensité de chiffrement multiple de la longueur du flag annule le masque), une fois la solution scriptée et le service interrogé, le flag qui tombe est :

BZHCTF{en_renseignant_ce_flag_je_certifie_ne_pas_avoir_utilise_de_LLM}

Le flag lui-même est une attestation sur l’honneur. Posé pile par l’auteur du challenge pour piéger ceux qui résoudraient via LLM. La situation s’est posée d’elle-même : valider ce flag via mon dispositif piloté par LLM, c’était certifier quelque chose de faux. J’ai signalé la chose à mon équipe ; on l’a soumis quand même, au titre de l’humour de la situation et parce que le règlement de l’évènement, lui, ne l’interdit pas. Mais le clin d’œil de l’auteur valait son pesant – et il pose exactement la question soulevée dans le retex 404CTF, mais sous forme de blague intégrée au challenge.

La conversation avec Saax

À un moment de la journée, je suis sorti prendre l’air dans la petite cour intérieure. Saax (Clément Domingo), un des organisateurs, était là. On a parlé. Pas du scoreboard – du futur du CTF. De la trajectoire qu’il prend. De comment les outils changent la donne, du fait que la frontière entre « assisté » et « automatisé » est devenue trop poreuse pour être tranchée par un règlement, des CTF qui font le pari de l’IA-friendly versus ceux qui s’arc-boutent dessus. La discussion qu’on a tous en ce moment, mais en off, sans posture.

On a comparé les deux écoles : celle qui interdit pour préserver l’esprit d’origine, et celle qui acccepte et conçoit des challenges qui résistent. Les deux ont du sens, aucune n’a tort, mais aucune n’est tenable dans l’absolu. Échange honnête entre quelqu’un qui organise et quelqu’un qui essaye de provoquer la conversation. Je suis ressorti de cette discussion avec l’impression rare et précieuse que le sujet est pris au sérieux par les bonnes personnes.

La démo – et le first blood en direct

10 minutes avant la fin de l’épreuve, je propose à Saax de venir voir mon setup en action. On retourne dans la salle, je lui ouvre les terminaux : le pilote Claude Opus, les agents en arrière-plan, le skill CTFd qui parle à l’API, le RAG local Llama qui répond aux questions de contexte, le dossier partagé avec les notes par challenge. Je lui explique la chimère – la même que pour le 404CTF, mais sous stéroïdes pour un marathon.

Pendant que je commente l’écran, un agent qui tournait depuis quelques minutes sur Savoureux Filet (Meshtastic, 48 solves, « Facile » mais qui résistait depuis des heures – clé par défaut AQ== qu’il fallait prendre zero-paddée sur 16 octets, pas l’expansion d4f1bb3a que j’avais essayée à la main une heure plus tôt) crache son verdict. Le flag est correct. Je le valide via le helper de soumission.

Une demi-seconde plus tard, les enceintes de la salle explosent : le sample CS « FIRST BLOOD ». La salle se retourne. Saax aussi. On vient de prendre le premier sang du Meshtastic pendant qu’il regardait l’écran. Timing parfait. Pas scénarisé, juste un coup de chance qui a transformé une démo de stack technique en moment où la salle entière a entendu, en direct, le truc envoyer un flag.

Tu peux passer une demi-heure à expliquer un pipeline d’agents – tu n’auras jamais le même impact qu’une demi-seconde où la machine te répond « correct » et où la salle hurle un sample Counter-Strike par-dessus.

C’est probablement le souvenir que je garderai en premier de cette édition.

Le même outil, pas les mêmes résultats

L’observation la plus intéressante de cette édition, je ne l’ai pas faite pendant l’épreuve mais après. Sur les pauses, autour des bières, à plusieurs reprises, j’ai eu la même conversation avec des gens qui utilisent aussi Claude au quotidien : ils me demandaient comment j’avais fait. Pas dans le sens « quelle était la solution du challenge X » – dans le sens « j’utilise le même outil que toi, et je ne vais pas aussi loin, qu’est-ce que tu fais différemment ? ».

C’est probablement l’élément qui valide le mieux la thèse du retex 404CTF : l’outil n’est pas le résultat. Claude est une commodité maintenant – n’importe qui peut taper son prompt dans une fenêtre de chat et obtenir une réponse. La différence ne vient pas du modèle, elle vient de tout ce qu’il y a autour. Et ce « tout ce qu’il y a autour », c’est exactement ce que j’avais mis des semaines à construire avant le 404CTF :

  • La préparation. Le skill CTFd custom qui automatise la plomberie (énumération, téléchargement, soumission, gestion des instances). Le RAG local Llama avec des centaines de writeups indexés. Les fichiers de configuration qui spécialisent les agents pour le hacking. Les conventions du dossier partagé pour que les agents puissent se passer le relais. Tout ce travail invisible n’apparaît jamais dans une démo de 30 secondes, mais c’est ce qui fait que mes agents partent avec 80% du contexte déjà construit au moment où je leur file une tâche.
  • L’expérience d’usage. Savoir comment piloter Claude est une compétence à part entière, qui s’acquiert à l’usage et pas en lisant la doc. Quand donner un objectif large, quand au contraire le découper en sous-tâches précises. Comment écrire un prompt qui empêche l’agent de partir en monitor passif. Quand lui passer un hint pour éviter un rabbit hole, quand au contraire le laisser explorer. Reconnaître les patterns de « l’agent commence à tourner en rond » et l’interrompre avant qu’il ne brûle 100 tool uses pour rien. Tout ça, ça ne s’apprend qu’en se plantant des dizaines de fois.
  • La compréhension de ce qui est nécessaire pour optimiser. Le travail d’identification des frictions est probablement le moins glamour mais le plus rentable. Quelles sont les actions répétitives qu’on peut scripter (helpers de soumission de flag, helpers de spawn d’instance). Quels sont les contextes que les agents redemandent en boucle et qu’on peut leur fournir une fois pour toutes (les chemins, les conventions, les outils dispo). Quelles sont les limites du modèle qu’on peut contourner par un changement d’architecture (sous-agents en parallèle plutôt qu’un seul agent gigantesque). C’est de l’ingénierie de workflow, pas du prompt-engineering au sens marketing du terme.

Plusieurs personnes m’ont dit, en gros : « j’ai essayé de faire pareil sur d’autres CTF, ça n’avance pas forcément aussi vite ». Et ma réponse a chaque fois été la même : « tu utilises Claude vanilla dans une fenêtre de chat, sans skill, sans RAG, sans helpers, sans dossier de notes partagées, sans la moitié des jailbreaks nécessaires pour qu’il accepte de faire du CTF.

c’est normal que ça n’aille pas loin. Le modèle n’est qu’un composant – le pipeline autour, c’est 80% du travail. » Aucun de ces composants n’est révolutionnaire pris isolément. C’est leur combinaison et la rigueur avec laquelle ils s’enchaînent qui fait la différence.

C’est exactement la même histoire que pour les outils traditionnels du métier. Tout le monde a Burp Suite. Tout le monde a Wireshark. Tout le monde a Ghidra. Pourtant les résultats varient énormément d’un opérateur à l’autre. Personne ne s’en étonne. Le jour où on cessera de s’étonner que ce soit pareil pour les LLM, on aura fait un pas de plus dans la maturation du débat.

Ce que je retiens, en lien avec le retex 404CTF

Sur le 404CTF, je voulais lancer un débat en étant le seul à utiliser l’IA dans un cadre où c’était explicitement interdit. Sur le BreizhCTF, je viens dans un cadre qui ne l’interdit pas, je suis seul dans l’équipe à l’utiliser à fond, et je finis 11ème sur 116. L’écart entre « personne ne le fait » et « tout le monde peut le faire » est beaucoup plus petit que ce que beaucoup imaginent. Mais il n’est pas nul non plus.

Ce qui fait la différence reste les mêmes éléments qu’au 404CTF :

  • Le pilote. Sans humain dans la boucle qui dit « non, ne va pas par là », « tente cet angle », « abandonne, on switch », les agents asynchrones s’enterrent. Les morts par rabbit hole (YAQACC, Glitch [2/3], No-thanks-AI, Meshtastic en première tentative à la main, Gomz, etc.) sont à chaque fois la conséquence d’un manque de supervision sur une tâche qui demandait un pivot.
  • L’expérience de CTF. Reconnaître une attaque connue, savoir quand un challenge « Très Facile » doit prendre 5 minutes et pas 50, distinguer un piège artificiel d’une vraie vuln, juger qu’un agent qui n’a rien produit en 30 minutes ne produira rien en 30 de plus. L’IA n’a pas ça en mémoire à long terme – mes 10 ans, si.
  • La capacité à arrêter. Le savoir-arrêter est probablement la compétence la plus sous-cotée du CTF moderne. J’ai coupé une demi-douzaine d’agents en cours de route, parce qu’ils étaient soit techniquement bloqués (XSS CSP-verrouillée, infra AD inaccessible, ESP32 indisponible), soit dans une impasse cognitive. Chaque coupure libère un slot, du focus, et permet de reverser le budget restant.

Et puis il y a la dimension humaine, qu’on a tendance à oublier quand on parle uniquement d’outils. La conversation avec Saax dans la cour, les retrouvailles avec noobosaurus et thelaluka, les têtes nouvelles, la salle qui hurle un sample CS au bon moment – tout ça n’a rien à voir avec mon stack technique, et c’est pourtant la moitié de la raison d’aller à un on-site. Un CTF, ce n’est pas qu’un scoreboard.

Verdict perso : le 404CTF était un stunt pour ouvrir une porte. Le BreizhCTF est l’illustration de ce qu’il y a derrière, dans des conditions normales, sans posture. L’IA accélère, le cerveau dirige, la communauté reste. Et c’est probablement la formulation la plus honnête que je puisse donner aujourd’hui.

Les chiffres finaux

MétriqueValeur
Durée effective~8h on-site
Challenges résolus31 / 57
Score final~10 750 pts
Rang final11ème / 116 équipes (top 10%)
Rang pic5ème (avant gel du scoreboard)
First bloods4 confirmés (Assistant Inverse, Breizh Ledger, Soaperlipopette, Savoureux Filet)
Catégories couvertesCrypto · Reverse · Web · Forensic · Pwn · Mobile · Hardware · Misc · Game Hacking · Sponsors
Catégorie écartéeOSINT (décision d’équipe en cours d’épreuve)
Sous-agents lancés~35 au total
Sous-agents tués pour cause de rabbit hole~10
Samples Counter-Strike « FIRST BLOOD » déclenchés en démo live à un organisateur1

GG à tous les participants. Merci aux orgas du BreizhCTF pour leur boulot, et à Saax pour la conversation. À l’année prochaine pour la 5ème.

31 challenges. 10 750 pts. 11/116. 4 first bloods. Une démo live avec un sample CS en bonus. À l’an prochain.


Publié

dans

, ,

par

Étiquettes :

Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *