<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>GDB on Le Blog de Rebel Zhang</title>
        <link>https://rebel1725.codeberg.page/blog/fr/tags/gdb/</link>
        <description>Recent content in GDB on Le Blog de Rebel Zhang</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>fr-FR</language>
        <managingEditor>rebel1725@tilde.club (Rebel Zhang)</managingEditor>
        <webMaster>rebel1725@tilde.club (Rebel Zhang)</webMaster>
        <lastBuildDate>Wed, 27 May 2026 23:56:34 +0800</lastBuildDate><atom:link href="https://rebel1725.codeberg.page/blog/fr/tags/gdb/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>Un exemple de rétro-ingénierie avec GDB et Iaito/Radare2</title>
            <link>https://rebel1725.codeberg.page/blog/fr/post/a-reverse-engineering-example-with-gdb-and-iaito-radare2/</link>
            <pubDate>Wed, 27 May 2026 23:56:34 +0800</pubDate><author>rebel1725@tilde.club (Rebel Zhang)</author>
            <guid>https://rebel1725.codeberg.page/blog/fr/post/a-reverse-engineering-example-with-gdb-and-iaito-radare2/</guid>
            <description>&lt;p&gt;Au cours des dernières semaines, j’ai appris la rétro-ingénierie, et j’ai &lt;a class=&#34;link&#34; href=&#34;../a-brief-introduction-into-reverse-engineering/&#34; &gt;rédigé un billet de blog&lt;/a&gt; pour partager ma toute première expérience. Ces derniers temps, je vais un peu plus loin, en résolvant un défi de CTF à l’aide d’une combinaison d’analyse statique et d’analyse dynamique, et j’ai trouvé que c’était un excellent exemple pour expliquer un peu plus en profondeur la rétro-ingénierie.&lt;/p&gt;&#xA;&lt;p&gt;J’avais auparavant prévu d’écrire un article sur l’analyse dynamique avec GDB. Cependant, j’ai trouvé que ce défi était aussi un très bon exemple pour expliquer GDB. Et pour résoudre ce défi, j’utiliserai en plus un autre outil, &lt;strong&gt;iaito&lt;/strong&gt;, qui est l’interface graphique de radare2.&lt;/p&gt;&#xA;&lt;h2 id=&#34;le-défi&#34;&gt;Le défi&#xA;&lt;/h2&gt;&lt;p&gt;cIMG est en quelque sorte un format d’image destiné à représenter une image constituée de caractères de différentes couleurs dans le terminal. Il est composé de :&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;le nombre magique, qui est &lt;code&gt;cIMG&lt;/code&gt; ;&lt;/li&gt;&#xA;&lt;li&gt;le numéro de version ;&lt;/li&gt;&#xA;&lt;li&gt;la largeur et la hauteur ;&lt;/li&gt;&#xA;&lt;li&gt;les données, chaque pixel contenant R, G, B et le caractère ASCII.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;Ce défi consiste à fournir un cIMG à un exécutable qui vous donnera le drapeau uniquement si le cIMG satisfait certaines conditions.&lt;/p&gt;&#xA;&lt;h2 id=&#34;le-code-source&#34;&gt;Le code source&#xA;&lt;/h2&gt;&lt;p&gt;Obtenez ici le &lt;a class=&#34;link&#34; href=&#34;https://raw.githubusercontent.com/pwncollege/intro-to-cybersecurity-dojo/refs/heads/main/reverse-engineering/cimg-framebuffer-mini-c/_0/cimg.c&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;&#xA;    &gt;source&lt;/a&gt; du défi. Ce code source semble être sous licence BSD 2-Clause.&lt;/p&gt;&#xA;&lt;p&gt;Compilez-le avec GCC :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ gcc -O3 challenge.c -o challenge&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ouvrez Python et créez un exemple de fichier cIMG :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ python3&#xA;Python 3.13.5 (Jun 25 2025, 18:55:22) [GCC 14.2.0] on linux&#xA;Type &amp;#34;help&amp;#34;, &amp;#34;copyright&amp;#34;, &amp;#34;credits&amp;#34; or &amp;#34;license&amp;#34; for more information.&#xA;&amp;gt;&amp;gt;&amp;gt; with open(&amp;#34;example.cimg&amp;#34;, &amp;#34;wb&amp;#34;) as file:&#xA;...     file.write(b&amp;#34;cIMG\x02\0\x0a\x0a&amp;#34;)&#xA;...     file.write(b&amp;#34;\x50&amp;#34;*(10*10*4))&#xA;...     &#xA;8&#xA;400&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Utilisez le binaire du défi pour ouvrir l’exemple de fichier cIMG :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;user@learnaarch64asm:~$ ./challenge ./example.cimg &#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ce fichier affiche quelque chose, mais ne fournit pas le drapeau.&lt;/p&gt;&#xA;&lt;h2 id=&#34;analyse-statique&#34;&gt;Analyse statique&#xA;&lt;/h2&gt;&lt;p&gt;Nous devons fabriquer un fichier cIMG qui &lt;em&gt;donne le drapeau&lt;/em&gt;. Commençons par une analyse statique.&lt;/p&gt;&#xA;&lt;p&gt;Ouvrez le fichier dans iaito. Lancez une analyse &lt;code&gt;aaa&lt;/code&gt; et ouvrez le graphe de la fonction &lt;code&gt;main&lt;/code&gt;. Vous obtiendrez :&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://rebel1725.codeberg.page/blog/pic_20260527_001_417726312315916099.png&#34;&#xA;&#x9;width=&#34;3532&#34;&#xA;&#x9;height=&#34;5056&#34;&#xA;&#x9;loading=&#34;lazy&#34;&#xA;&#x9;&#xA;&#x9;&#x9;alt=&#34;le graphe de la fonction main&#34;&#xA;&#x9;&#xA;&#x9;&#xA;&#x9;&#x9;class=&#34;gallery-image&#34; &#xA;&#x9;&#x9;data-flex-grow=&#34;69&#34;&#xA;&#x9;&#x9;data-flex-basis=&#34;167px&#34;&#xA;&#x9;&#xA;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Nous pouvons voir la lecture de l’en-tête du fichier à &lt;code&gt;0x00000cac&lt;/code&gt;, la vérification du nombre magique à &lt;code&gt;0x00000cc4&lt;/code&gt;, la vérification de la version à &lt;code&gt;0x00000cd0&lt;/code&gt;, ainsi que la lecture de la largeur et de la hauteur à &lt;code&gt;0x00000ce0&lt;/code&gt;. Ensuite, &lt;code&gt;malloc&lt;/code&gt; est utilisé pour allouer un bloc de mémoire pour les données de l’image, puis les données sont lues dans cette mémoire.&lt;/p&gt;&#xA;&lt;p&gt;Le nombre magique est &lt;code&gt;cIMG&lt;/code&gt;, ce qui correspond à &lt;code&gt;63 49 4d 47&lt;/code&gt; en hexadécimal ; la version est un entier 32 bits en little-endian ; la hauteur et la largeur sont toutes deux des entiers de 8 bits.&lt;/p&gt;&#xA;&lt;h2 id=&#34;condition-pour-obtenir-le-drapeau&#34;&gt;Condition pour obtenir le drapeau&#xA;&lt;/h2&gt;&lt;p&gt;Allons à la fin de la fonction. De toute évidence, &lt;code&gt;sym.win&lt;/code&gt; est la fonction qui nous donnera le drapeau. Elle est appelée à &lt;code&gt;0x00000e8c&lt;/code&gt;, et cette exécution a lieu après une vérification à &lt;code&gt;0x00000e58&lt;/code&gt;. Cette vérification exige que &lt;code&gt;w19&lt;/code&gt; ne soit pas nul.&lt;/p&gt;&#xA;&lt;h2 id=&#34;altération-du-flot-de-contrôle&#34;&gt;Altération du flot de contrôle&#xA;&lt;/h2&gt;&lt;p&gt;Il est temps de lancer GDB.&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ gdb --args ./challenge ./example.cimg &#xA;GNU gdb (Debian 16.3-1) 16.3&#xA;Copyright (C) 2024 Free Software Foundation, Inc.&#xA;License GPLv3+ or later &amp;lt;http://gnu.org/licenses/gpl.html&amp;gt;&#xA;This is free software: you are free to change and redistribute it.&#xA;There is NO WARRANTY, to the extent permitted by law.&#xA;Type &amp;#34;show copying&amp;#34; and &amp;#34;show warranty&amp;#34; for details.&#xA;This GDB was configured as &amp;#34;aarch64-linux-gnu&amp;#34;.&#xA;Type &amp;#34;show configuration&amp;#34; for configuration details.&#xA;For bug reporting instructions, please see:&#xA;&amp;lt;https://www.gnu.org/software/gdb/bugs/&amp;gt;.&#xA;Find the GDB manual and other documentation resources online at:&#xA;    &amp;lt;http://www.gnu.org/software/gdb/documentation/&amp;gt;.&#xA;&#xA;For help, type &amp;#34;help&amp;#34;.&#xA;Type &amp;#34;apropos word&amp;#34; to search for commands related to &amp;#34;word&amp;#34;...&#xA;Reading symbols from ./challenge...&#xA;(No debugging symbols found in ./challenge)&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Placez un point d’arrêt sur la fonction main et lancez le programme :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) break *main&#xA;Breakpoint 1 at 0xc44&#xA;(gdb) run&#xA;Starting program: /home/user/challenge ./example.cimg&#xA;[Thread debugging using libthread_db enabled]&#xA;Using host libthread_db library &amp;#34;/lib/aarch64-linux-gnu/libthread_db.so.1&amp;#34;.&#xA;&#xA;Breakpoint 1, 0x0000aaaaaaaa0c44 in main ()&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous remarquons que les adresses de données de GDB ont un décalage de &lt;code&gt;0xaaaaaaaa0000&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Placez un point d’arrêt juste avant la vérification de la condition du drapeau, puis continuez :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) break *0x0000aaaaaaaa0e58&#xA;Breakpoint 2 at 0xaaaaaaaa0e58&#xA;(gdb) continue&#xA;Continuing.&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;&#xA;Breakpoint 2, 0x0000aaaaaaaa0e58 in main ()&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Modifiez le contenu du registre &lt;code&gt;w19&lt;/code&gt; et continuez :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) set $w19 = 1&#xA;(gdb) continue&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;L’exécutable nous donnera alors le drapeau. Le travail est terminé, et passez une bonne journée :-p&lt;/p&gt;&#xA;&lt;p&gt;Je plaisante. Si l’on concluait réellement le défi ainsi, toute la joie de la RE disparaîtrait. Allons plus loin.&lt;/p&gt;&#xA;&lt;h2 id=&#34;vérification-des-données&#34;&gt;Vérification des données&#xA;&lt;/h2&gt;&lt;p&gt;Retournez dans iaito. Cliquez sur &lt;code&gt;w19&lt;/code&gt; dans le graphe. Cela mettra en surbrillance ce registre dans toutes les instructions du graphe. Faites défiler le graphe en arrière pour trouver un indice.&lt;/p&gt;&#xA;&lt;p&gt;Nous pouvons voir plusieurs appels à &lt;code&gt;sym.imp.memcmp&lt;/code&gt; dans le graphe.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;memcmp&lt;/code&gt; est une fonction standard de la bibliothèque C, déclarée dans &lt;code&gt;&amp;lt;string.h&amp;gt;&lt;/code&gt;, qui compare deux blocs de mémoire octet par octet :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;int memcmp(const void *ptr1, const void *ptr2, size_t n);&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;ptr1&lt;/code&gt; et &lt;code&gt;ptr2&lt;/code&gt; pointent respectivement vers les deux blocs, et &lt;code&gt;n&lt;/code&gt; indique le nombre d’octets à comparer. Si les deux blocs sont identiques, la fonction renvoie &lt;code&gt;0&lt;/code&gt; ; sinon, elle renvoie un nombre non nul.&lt;/p&gt;&#xA;&lt;p&gt;Il y a quatre appels à &lt;code&gt;memcmp&lt;/code&gt;. Chaque appel est suivi de &lt;code&gt;cmp w0, 0&lt;/code&gt;. À l’exception du premier appel, il y a aussi un &lt;code&gt;cset w0, eq&lt;/code&gt; et un &lt;code&gt;and w19, w19, w0&lt;/code&gt; après &lt;code&gt;cmp&lt;/code&gt;. On peut en conclure que si &lt;code&gt;memcmp&lt;/code&gt; détecte une différence, &lt;code&gt;w19&lt;/code&gt; sera remis à zéro, puisque &lt;code&gt;w0&lt;/code&gt; vaudra zéro. Nous supposons donc qu’il faut rendre identiques les quatre paires de blocs mémoire.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;x0&lt;/code&gt; et &lt;code&gt;x1&lt;/code&gt; sont les deux adresses à comparer. &lt;code&gt;x2&lt;/code&gt; contient la taille ; &lt;code&gt;mov x2, 0x18&lt;/code&gt; nous indique que la taille est de 24 octets.&lt;/p&gt;&#xA;&lt;p&gt;Ouvrez à nouveau GDB et inspectez la mémoire avant le premier &lt;code&gt;memcmp&lt;/code&gt; :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) break *0x0000aaaaaaaa0e78&#xA;Breakpoint 1 at 0xaaaaaaaa0e78&#xA;(gdb) run&#xA;Starting program: /home/user/challenge ./example.cimg&#xA;[Thread debugging using libthread_db library &amp;#34;/lib/aarch64-linux-gnu/libthread_db.so.1].&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;PPPPPPPPPP&#xA;&#xA;Breakpoint 1, 0x0000aaaaaaaa0e78 in main ()&#xA;(gdb) info registers x0 x1&#xA;x0             0xaaaaaaac12a0      187649984565920&#xA;x1             0xaaaaaaac00c0      187649984561344&#xA;(gdb) x/24xb $x0&#xA;0xaaaaaaac12a0: 0x1b    0x5b    0x33    0x38    0x3b    0x32    0x3b    0x30&#xA;0xaaaaaaac12a8: 0x38    0x30    0x3b    0x30    0x38    0x30    0x3b    0x30&#xA;0xaaaaaaac12b0: 0x38    0x30    0x6d    0x50    0x1b    0x5b    0x30    0x6d&#xA;(gdb) x/24xb $x1&#xA;0xaaaaaaac00c0 &amp;lt;desired_output&amp;gt;:        0x1b    0x5b    0x33    0x38    0x3b   0x32     0x3b    0x32&#xA;0xaaaaaaac00c8 &amp;lt;desired_output+8&amp;gt;:      0x33    0x31    0x3b    0x30    0x31   0x37     0x3b    0x31&#xA;0xaaaaaaac00d0 &amp;lt;desired_output+16&amp;gt;:     0x33    0x30    0x6d    0x63    0x1b   0x5b     0x30    0x6d&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Des octets aléatoires. Je n’arrive pas à comprendre ce qu’ils signifient.&lt;/p&gt;&#xA;&lt;p&gt;Retournez dans iaito. Le premier bloc de mémoire est chargé depuis &lt;code&gt;x22&lt;/code&gt;, et &lt;code&gt;x22&lt;/code&gt; est chargé depuis l’adresse &lt;code&gt;var_48h&lt;/code&gt;. &lt;code&gt;afv&lt;/code&gt; nous indique qu’elle se trouve à &lt;code&gt;0x48&lt;/code&gt; depuis &lt;code&gt;sp&lt;/code&gt; :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[0x00000e70]&amp;gt; afv&#xA;arg signed int argc @ x0&#xA;arg char ** s @ x1&#xA;var int64_t var_50h @ sp+0x0&#xA;var int64_t var_50h_2 @ sp+0x8&#xA;var int64_t var_10h @ sp+0x10&#xA;var int64_t var_10h_2 @ sp+0x18&#xA;var int64_t var_20h @ sp+0x20&#xA;var int64_t var_20h_2 @ sp+0x28&#xA;var void * buf @ sp+0x38&#xA;var int64_t var_3ch @ sp+0x3c&#xA;var int64_t var_3eh @ sp+0x3e&#xA;var int64_t var_3fh @ sp+0x3f&#xA;var int64_t var_40h @ sp+0x40&#xA;var int64_t var_48h @ sp+0x48&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Redémarrez GDB et sautez le prologue de la fonction après l’invocation de &lt;code&gt;main&lt;/code&gt; :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) break *main&#xA;Breakpoint 1 at 0xaaaaaaaa0c44&#xA;(gdb) run&#xA;Starting program: /home/user/challenge ./example.cimg&#xA;[Thread debugging using libthread_db library &amp;#34;/lib/aarch64-linux-gnu/libthread_db.so.1].&#xA;&#xA;Breakpoint 1, 0x0000aaaaaaaa0c44 in main ()&#xA;(gdb) si&#xA;0x0000aaaaaaaa0c48 in main ()&#xA;(gdb) si&#xA;0x0000aaaaaaaa0c4c in main ()&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Vérifiez la valeur du pointeur de pile et définissez un watchpoint :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) info registers sp&#xA;sp             0xfffffffff290      0xfffffffff290&#xA;(gdb) watch *(long long *)0xfffffffff2d8&#xA;Hardware watchpoint 2: *(long long *)0xfffffffff2d8&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Continuez :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) continue&#xA;Continuing.&#xA;&#xA;Hardware watchpoint 2: *(long long *)0xfffffffff2d8&#xA;&#xA;Old value = 281474840286680&#xA;New value = 0&#xA;0x0000aaaaaaaa0c5c in main ()&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Localisez cette adresse dans iaito. Nous pouvons voir qu’à &lt;code&gt;0x00000c58&lt;/code&gt; (l’instruction précédente à &lt;code&gt;0x00000c5c&lt;/code&gt;), &lt;code&gt;var_48h&lt;/code&gt; est remise à zéro par un &lt;code&gt;str&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Poursuivez pour découvrir où la variable est définie :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) continue&#xA;Continuing.&#xA;&#xA;Hardware watchpoint 2: *(long long *)0xfffffffff2d8&#xA;&#xA;Old value = 0&#xA;New value = 187649984565920&#xA;0x0000aaaaaaaa1358 in initialize_framebuffer ()&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous voyons apparaître une nouvelle fonction que nous n’avons pas encore explorée : &lt;code&gt;initialize_framebuffer&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Dans iaito, allez à cette fonction :&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://rebel1725.codeberg.page/blog/pic_20260527_002_13426986448128896865.png&#34;&#xA;&#x9;width=&#34;1775&#34;&#xA;&#x9;height=&#34;1384&#34;&#xA;&#x9;loading=&#34;lazy&#34;&#xA;&#x9;&#xA;&#x9;&#x9;alt=&#34;le graphe de la fonction initialize\_framebuffer&#34;&#xA;&#x9;&#xA;&#x9;&#xA;&#x9;&#x9;class=&#34;gallery-image&#34; &#xA;&#x9;&#x9;data-flex-grow=&#34;128&#34;&#xA;&#x9;&#x9;data-flex-basis=&#34;307px&#34;&#xA;&#x9;&#xA;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Nous pouvons voir qu’une adresse mémoire allouée par &lt;code&gt;malloc&lt;/code&gt; est stockée dans la variable par l’instruction à &lt;code&gt;0x00001354&lt;/code&gt;. Cependant, elle est représentée par &lt;code&gt;[x22, 0x10]&lt;/code&gt;. Vérifions le contenu de &lt;code&gt;x22&lt;/code&gt; :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) info registers $x22&#xA;x22            0xfffffffff2c8      281474976707272&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;0xfffffffff2c8 + 0x10 = 0xfffffffff2d8&lt;/code&gt;. C’est exactement l’adresse de &lt;code&gt;var_48h&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;De plus, la taille fournie à &lt;code&gt;malloc&lt;/code&gt; est intéressante. Elle est calculée en multipliant les valeurs aux offsets 6 et 7, puis en multipliant le résultat par &lt;code&gt;w1&lt;/code&gt;, qui vaut &lt;code&gt;0x18&lt;/code&gt; (24), puis en ajoutant &lt;code&gt;x0&lt;/code&gt;, qui vaut 1.&lt;/p&gt;&#xA;&lt;p&gt;Vérifions aussi les valeurs de ces offsets :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) x/1xb 0xfffffffff2ce&#xA;0xfffffffff2ce: 0x0a&#xA;(gdb) x/1xb 0xfffffffff2cf&#xA;0xfffffffff2cf: 0x0a&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Toutes deux valent 10. Elles semblent correspondre à la largeur et à la hauteur de l’image que nous avons spécifiées. Vérifions cela en plaçant des watchpoints matériels. Comme AArch64 exige un alignement, plaçons le watchpoint matériel à &lt;code&gt;0xfffffffff2cc&lt;/code&gt; :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) watch *(unsigned int *)0xfffffffff2cc&#xA;Hardware watchpoint 1: *(unsigned int *)0xfffffffff2cc&#xA;(gdb) run&#xA;Starting program: /home/user/challenge ./example.cimg&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ignorez les déclenchements de la GNU C Library :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Hardware watchpoint 1: *(unsigned int *)0xfffffffff2cc&#xA;&#xA;Old value = 0&#xA;New value = 65535&#xA;0x0000fffff7fccd08 in ?? () from /lib/ld-linux-aarch64.so.1&#xA;(gdb) continue&#xA;Continuing.&#xA;&#xA;Hardware watchpoint 1: *(unsigned int *)0xfffffffff2cc&#xA;&#xA;Old value = 65535&#xA;New value = 0&#xA;0x0000fffff7fd5668 in ?? () from /lib/ld-linux-aarch64.so.1&#xA;(gdb) continue&#xA;Continuing.&#xA;[Thread debugging using libthread_db library &amp;#34;/lib/aarch64-linux-gnu/libthread_db.so.1&amp;#34;]&#xA;&#xA;Hardware watchpoint 1: *(unsigned int *)0xfffffffff2cc&#xA;&#xA;Old value = 0&#xA;New value = 65535&#xA;0x0000fffff7fcc3a4 in ?? () from /lib/ld-linux-aarch64.so.1&#xA;(gdb) continue&#xA;Continuing.&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ici, nous voyons que la mémoire est remise à zéro à &lt;code&gt;0x00000c54&lt;/code&gt; :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Hardware watchpoint 1: *(unsigned int *)0xfffffffff2cc&#xA;&#xA;Old value = 65535&#xA;New value = 0&#xA;0x0000aaaaaaaa0c58 in main ()&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous voyons un &lt;code&gt;stp xzr, xzr, [buf]&lt;/code&gt;. D’après l’&lt;code&gt;afv&lt;/code&gt; ci-dessus, nous savons que &lt;code&gt;buf&lt;/code&gt; se trouve à &lt;code&gt;0x38&lt;/code&gt; du pointeur de pile.&lt;/p&gt;&#xA;&lt;p&gt;À &lt;code&gt;0x00000cb8&lt;/code&gt;, nous pouvons voir un &lt;code&gt;ldr&lt;/code&gt; depuis &lt;code&gt;buf&lt;/code&gt;, puis une vérification du nombre magique.&lt;/p&gt;&#xA;&lt;p&gt;À &lt;code&gt;0x00000c9c&lt;/code&gt;, nous pouvons voir quelque chose d’intéressant :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;0x00000c9c      add      x21,    sp,     0x38&#xA;0x00000ca0      mov      x2,     8                          ; size_t nbyte&#xA;0x00000ca4      mov      x1,     x21                        ; void *buf&#xA;0x00000ca8      mov      w0,     0&#xA;0x00000cac      bl       sym.imp.read                       ; ssize_t read(int fildes, void *buf, size_t nbyte)&#xA;; ssize_t read(0, 0x0000000000000000, 0x00000000)&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous avons donc confirmé que les deux valeurs à ces offsets correspondent à la largeur et à la hauteur.&lt;/p&gt;&#xA;&lt;p&gt;Retournez à la fonction &lt;code&gt;initialize_framebuffer&lt;/code&gt; dans iaito et GDB. Placez un watchpoint et inspectez la mémoire :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) break *0xaaaaaaaa1354&#xA;Breakpoint 1 at 0xaaaaaaaa1354&#xA;(gdb) run&#xA;Starting program: /home/user/challenge ./example.cimg&#xA;[Thread debugging using libthread_db library &amp;#34;/lib/aarch64-linux-gnu/libthread_db.so.1].&#xA;&#xA;Breakpoint 1, 0x0000aaaaaaaa1354 in initialize_framebuffer ()&#xA;(gdb) info registers x0&#xA;x0             0xaaaaaaac12a0      187649984565920&#xA;(gdb) watch *(char *)0xaaaaaaac12a0&#xA;Hardware watchpoint 2: *(char *)0xaaaaaaac12a0&#xA;(gdb) continue&#xA;Continuing.&#xA;&#xA;Hardware watchpoint 2: *(char *)0xaaaaaaac12a0&#xA;&#xA;Old value = 0 &amp;#39;\000&amp;#39;&#xA;New value = 27 &amp;#39;\033&amp;#39;&#xA;0x0000aaaaaaaa13bc in initialize_framebuffer ()&#xA;(gdb) x/24xb 0xaaaaaaac12a0&#xA;0xaaaaaaac12a0: 0x1b    0x5b    0x33    0x38    0x3b    0x32    0x3b    0x32&#xA;0xaaaaaaac12a8: 0x35    0x35    0x3b    0x32    0x35    0x35    0x3b    0x32&#xA;0xaaaaaaac12b0: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Comparez avec les données ci-dessus :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) x/24xb $x0&#xA;0xaaaaaaac12a0: 0x1b    0x5b    0x33    0x38    0x3b    0x32    0x3b    0x30&#xA;0xaaaaaaac12a8: 0x38    0x30    0x3b    0x30    0x38    0x30    0x3b    0x30&#xA;0xaaaaaaac12b0: 0x38    0x30    0x6d    0x50    0x1b    0x5b    0x30    0x6d&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;0xaaaaaaac12a7&lt;/code&gt; est le premier octet qui diffère. Nous pouvons placer un watchpoint dessus :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) watch *(char *)0xaaaaaaac12a7&#xA;Hardware watchpoint 3: *(char *)0xaaaaaaac12a7&#xA;(gdb) continue&#xA;Continuing.&#xA;&#xA;Hardware watchpoint 3: *(char *)0xaaaaaaac12a7&#xA;&#xA;Old value = 50 &amp;#39;2&amp;#39;&#xA;New value = 48 &amp;#39;0&amp;#39;&#xA;0x0000aaaaaaaa128c in display ()&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Une nouvelle fonction à explorer apparaît. Ouvrez-la dans iaito.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://rebel1725.codeberg.page/blog/pic_20260527_003_2825852626928846418.png&#34;&#xA;&#x9;width=&#34;1129&#34;&#xA;&#x9;height=&#34;2426&#34;&#xA;&#x9;loading=&#34;lazy&#34;&#xA;&#x9;&#xA;&#x9;&#x9;alt=&#34;le graphe de la fonction initialize\_framebuffer&#34;&#xA;&#x9;&#xA;&#x9;&#xA;&#x9;&#x9;class=&#34;gallery-image&#34; &#xA;&#x9;&#x9;data-flex-grow=&#34;46&#34;&#xA;&#x9;&#x9;data-flex-basis=&#34;111px&#34;&#xA;&#x9;&#xA;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Nous pouvons voir que la modification des données a lieu à &lt;code&gt;0x00001288&lt;/code&gt;, dans une instruction &lt;code&gt;stp&lt;/code&gt;. L’instruction &lt;code&gt;str&lt;/code&gt; à &lt;code&gt;0x0000128c&lt;/code&gt; est également intéressante ; inspectons la mémoire ici :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) x/24xb 0xaaaaaaac12a0&#xA;0xaaaaaaac12a0: 0x1b    0x5b    0x33    0x38    0x3b    0x32    0x3b    0x30&#xA;0xaaaaaaac12a8: 0x38    0x30    0x3b    0x30    0x38    0x30    0x3b    0x30&#xA;0xaaaaaaac12b0: 0x35    0x35    0x6d    0x20    0x1b    0x5b    0x30    0x6d&#xA;(gdb) si&#xA;0x0000aaaaaaaa1290 in display ()&#xA;(gdb) x/24xb 0xaaaaaaac12a0&#xA;0xaaaaaaac12a0: 0x1b    0x5b    0x33    0x38    0x3b    0x32    0x3b    0x30&#xA;0xaaaaaaac12a8: 0x38    0x30    0x3b    0x30    0x38    0x30    0x3b    0x30&#xA;0xaaaaaaac12b0: 0x38    0x30    0x6d    0x50    0x1b    0x5b    0x30    0x6d&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Le bloc de 8 octets à partir de &lt;code&gt;0xaaaaaaac12b0&lt;/code&gt; a été modifié par l’instruction &lt;code&gt;str&lt;/code&gt;. Le registre raconte l’histoire :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) info registers x2&#xA;x2             0xaaaaaaac12a0      187649984565920&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous n’avons pas besoin de nous attarder sur &lt;code&gt;x2&lt;/code&gt;. Concentrons-nous sur &lt;code&gt;x4&lt;/code&gt;, &lt;code&gt;x5&lt;/code&gt; et &lt;code&gt;x1&lt;/code&gt;. À &lt;code&gt;0x00001268&lt;/code&gt; et &lt;code&gt;0x00001270&lt;/code&gt;, nous voyons un registre très important, &lt;code&gt;x25&lt;/code&gt;. Il contient l’adresse de la mémoire qui contient les données écrites dans la mémoire pointée par &lt;code&gt;x2&lt;/code&gt;. Inspectons cette mémoire :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) x/24xb $x25&#xA;0xfffffffff270: 0x1b    0x5b    0x33    0x38    0x3b    0x32    0x3b    0x30&#xA;0xfffffffff278: 0x38    0x30    0x3b    0x30    0x38    0x30    0x3b    0x30&#xA;0xfffffffff280: 0x38    0x30    0x6d    0x50    0x1b    0x5b    0x30    0x6d&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;À &lt;code&gt;0x00001238&lt;/code&gt;, l’adresse contenue dans &lt;code&gt;x25&lt;/code&gt; est copiée dans &lt;code&gt;x0&lt;/code&gt;. Ensuite, plusieurs données sont copiées dans les registres suivants. Puis un appel à &lt;code&gt;snprintf&lt;/code&gt; est effectué. &lt;code&gt;snprintf&lt;/code&gt; écrit une sortie formatée dans un tableau de caractères :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;int snprintf(char *str, size_t size, const char *format, ...);&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Il écrit donc une chaîne formatée dans la mémoire pointée par &lt;code&gt;x25&lt;/code&gt;. Redémarrons GDB et inspectons la mémoire pointée par &lt;code&gt;x2&lt;/code&gt; :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) break *0xaaaaaaaa1258&#xA;Breakpoint 1 at 0xaaaaaaaa1258&#xA;(gdb) run&#xA;Starting program: /home/user/challenge ./example.cimg&#xA;[Thread debugging using libthread_db library &amp;#34;/lib/aarch64-linux-gnu/libthread_db.so.1].&#xA;&#xA;Breakpoint 1, 0x0000aaaaaaaa1258 in display ()&#xA;(gdb) x/s $x2&#xA;0xaaaaaaaa1510: &amp;#34;\033[38;2;%03d;%03d;%03dm%c\033[0m&amp;#34;&#xA;(gdb) x/29xb $x2&#xA;0xaaaaaaaa1510: 0x1b    0x5b    0x33    0x38    0x3b    0x32    0x3b    0x25&#xA;0xaaaaaaaa1518: 0x30    0x33    0x64    0x3b    0x25    0x30    0x33    0x64&#xA;0xaaaaaaaa1520: 0x3b    0x25    0x30    0x33    0x64    0x6d    0x25    0x63&#xA;0xaaaaaaaa1528: 0x1b    0x5b    0x30    0x6d    0x00&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;C’est la chaîne de format. Si vous n’êtes pas à l’aise avec la chaîne renvoyée par &lt;code&gt;x/s&lt;/code&gt;, vous pouvez utiliser Python pour afficher la chaîne octet par octet :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print(b&amp;#34;\x1b\x5b\x33\x38\x3b\x32\x3b\x25\x30\x33\x64\x3b\x25\x30\x33\x64\x3\&#xA;b\x25\x30\x33\x64\x6d\x25\x63\x1b\x5b\x30\x6d\x00&amp;#34;)&#xA;b&amp;#39;\x1b[38;2;%03d;%03d;%03dm%c\x1b[0m\x00&amp;#39;&#xA;&amp;gt;&amp;gt;&amp;gt; blob = b&amp;#39;\x1b[38;2;%03d;%03d;%03dm%c\x1b[0m\x00&amp;#39;&#xA;&amp;gt;&amp;gt;&amp;gt; for i1 in range(len(blob)):&#xA;...     blob[i1:i1+1]&#xA;...     &#xA;b&amp;#39;\x1b&amp;#39;&#xA;b&amp;#39;[&amp;#39;&#xA;b&amp;#39;3&amp;#39;&#xA;b&amp;#39;8&amp;#39;&#xA;b&amp;#39;;&amp;#39;&#xA;b&amp;#39;2&amp;#39;&#xA;b&amp;#39;;&amp;#39;&#xA;b&amp;#39;%&amp;#39;&#xA;b&amp;#39;0&amp;#39;&#xA;b&amp;#39;3&amp;#39;&#xA;b&amp;#39;d&amp;#39;&#xA;b&amp;#39;;&amp;#39;&#xA;b&amp;#39;%&amp;#39;&#xA;b&amp;#39;0&amp;#39;&#xA;b&amp;#39;3&amp;#39;&#xA;b&amp;#39;d&amp;#39;&#xA;b&amp;#39;;&amp;#39;&#xA;b&amp;#39;%&amp;#39;&#xA;b&amp;#39;0&amp;#39;&#xA;b&amp;#39;3&amp;#39;&#xA;b&amp;#39;d&amp;#39;&#xA;b&amp;#39;m&amp;#39;&#xA;b&amp;#39;%&amp;#39;&#xA;b&amp;#39;c&amp;#39;&#xA;b&amp;#39;\x1b&amp;#39;&#xA;b&amp;#39;[&amp;#39;&#xA;b&amp;#39;0&amp;#39;&#xA;b&amp;#39;m&amp;#39;&#xA;b&amp;#39;\x00&amp;#39;&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cette chaîne de format possède quatre espaces réservés. Les trois premiers sont &lt;code&gt;%03d&lt;/code&gt;, qui formatent un entier en décimal avec au moins trois chiffres (par exemple, 7 devient &lt;code&gt;007&lt;/code&gt;, et 15 devient &lt;code&gt;015&lt;/code&gt;). Le dernier est &lt;code&gt;%c&lt;/code&gt;, qui ne correspond qu’à un seul caractère.&lt;/p&gt;&#xA;&lt;p&gt;Nous avons maintenant le motif d’octets suivant :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;0x1b    0x5b    0x33    0x38    0x3b    0x32    0x3b    [N1]&#xA;[N1]    [N1]    0x3b    [N2]    [N2]    [N2]    0x3b    [N3]&#xA;[N3]    [N3]    0x6d    [CH]    0x1b    0x5b    0x30    0x6d&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nous pouvons maintenant inspecter ce qui remplit les espaces réservés :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) info registers x3 x4 x5 x6&#xA;x3             0x50                80&#xA;x4             0x50                80&#xA;x5             0x50                80&#xA;x6             0x50                80&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Tous valent &lt;code&gt;0x50&lt;/code&gt;, ce qui semble correspondre aux données que nous utilisons dans l’exemple de cIMG. Recréons maintenant le cIMG pour clarifier cela :&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; with open(&amp;#34;example.cimg&amp;#34;, &amp;#34;wb&amp;#34;) as file:&#xA;...     file.write(b&amp;#34;cIMG\x02\0\x0a\x0a\x12\x34\x56\x78&amp;#34;)&#xA;...     file.write(b&amp;#34;\x50&amp;#34;*(10*10*4-4))&#xA;...     &#xA;12&#xA;396&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(gdb) break *0xaaaaaaaa1258&#xA;Breakpoint 1 at 0xaaaaaaaa1258&#xA;(gdb) run&#xA;Starting program: /home/user/challenge ./example.cimg&#xA;[Thread debugging using libthread_db library &amp;#34;/lib/aarch64-linux-gnu/libthread_db.so.1].&#xA;&#xA;Breakpoint 1, 0x0000aaaaaaaa1258 in display ()&#xA;(gdb) info registers x3 x4 x5 x6&#xA;x3             0x12                18&#xA;x4             0x34                52&#xA;x5             0x56                86&#xA;x6             0x78                120&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ainsi, les N1, N2 et N3 du motif hexadécimal ci-dessus correspondent respectivement à R, G et B, et CH est simplement le caractère que nous cherchons à remplir.&lt;/p&gt;&#xA;&lt;p&gt;Nous pouvons maintenant revenir à GDB, placer un point d’arrêt avant chaque &lt;code&gt;memcmp&lt;/code&gt;, exécuter &lt;code&gt;x/24xb $x1&lt;/code&gt; pour découvrir les framebuffers attendus, puis utiliser ces framebuffers pour retrouver les données cIMG attendues. Il ne reste plus qu’à remplir les données à l’aide d’un éditeur hexadécimal.&lt;/p&gt;&#xA;&lt;h2 id=&#34;vérification-de-la-taille&#34;&gt;Vérification de la taille&#xA;&lt;/h2&gt;&lt;p&gt;Cependant, après avoir rempli les données attendues, l’exécutable ne nous donne toujours pas le drapeau. Après avoir utilisé GDB pour inspecter la mémoire, nous pouvons constater que les &lt;code&gt;memcmp&lt;/code&gt; renvoient bien zéro comme prévu. Il doit donc exister d’autres conditions qui ne sont pas satisfaites.&lt;/p&gt;&#xA;&lt;p&gt;Retournez dans iaito et remontez depuis le premier &lt;code&gt;memcmp&lt;/code&gt;. Nous pouvons voir un &lt;code&gt;cmp&lt;/code&gt; à &lt;code&gt;0x00000d60&lt;/code&gt; qui compare &lt;code&gt;var_40h&lt;/code&gt; avec 4. À &lt;code&gt;0x00001348&lt;/code&gt; dans &lt;code&gt;initialize_framebuffer&lt;/code&gt;, nous pouvons trouver un &lt;code&gt;str&lt;/code&gt; qui stocke le produit de la largeur et de la hauteur.&lt;/p&gt;&#xA;&lt;p&gt;Le &lt;code&gt;cmp&lt;/code&gt; à &lt;code&gt;0x00000d60&lt;/code&gt; détermine alors la valeur de &lt;code&gt;w0&lt;/code&gt;. Si &lt;code&gt;var_40h&lt;/code&gt; vaut 4, &lt;code&gt;w0&lt;/code&gt; devient 1 ; sinon, il devient 0.&lt;/p&gt;&#xA;&lt;p&gt;À &lt;code&gt;0x00000d78&lt;/code&gt;, &lt;code&gt;w0&lt;/code&gt; est comparé à 0, ce qui affecte le comportement de l’instruction &lt;code&gt;ccmp&lt;/code&gt; à &lt;code&gt;0x00000d84&lt;/code&gt;. Le contenu de &lt;code&gt;[x22, 0x13]&lt;/code&gt; est chargé dans le registre &lt;code&gt;w0&lt;/code&gt;, et &lt;code&gt;[x1, 0x13]&lt;/code&gt; est chargé dans &lt;code&gt;w2&lt;/code&gt;. D’après &lt;code&gt;memcmp&lt;/code&gt;, nous pouvons facilement déduire que &lt;code&gt;x22&lt;/code&gt; est l’adresse réelle du framebuffer, et que &lt;code&gt;x1&lt;/code&gt; est l’adresse du framebuffer attendu. Puisque nous avons déjà fait en sorte que les données soient identiques à celles attendues, et que l’offset 19 est un caractère ASCII, &lt;code&gt;w0&lt;/code&gt; et &lt;code&gt;w2&lt;/code&gt; devraient être identiques et non nuls.&lt;/p&gt;&#xA;&lt;p&gt;Nous pouvons en conclure que si &lt;code&gt;var_40h&lt;/code&gt; vaut 4, &lt;code&gt;w2&lt;/code&gt; sera comparé à &lt;code&gt;w0&lt;/code&gt;, ce qui fixera &lt;code&gt;w19&lt;/code&gt; à 1. Sinon, &lt;code&gt;w2&lt;/code&gt; sera comparé à 0, ce qui mettra &lt;code&gt;w19&lt;/code&gt; à zéro.&lt;/p&gt;&#xA;&lt;p&gt;Après le premier &lt;code&gt;memcmp&lt;/code&gt;, &lt;code&gt;w19&lt;/code&gt; sera comparé à 0 puisque &lt;code&gt;w0&lt;/code&gt; vaut zéro à &lt;code&gt;0x00000e7c&lt;/code&gt;. Ensuite, &lt;code&gt;cset&lt;/code&gt; fixera &lt;code&gt;w19&lt;/code&gt; à 1 si différent, sinon à 0.&lt;/p&gt;&#xA;&lt;p&gt;Modifiez maintenant le cIMG à l’aide d’un éditeur hexadécimal, en changeant la hauteur et la largeur pour des valeurs dont le produit vaut 4. Par exemple, nous pouvons utiliser &lt;code&gt;0202&lt;/code&gt;. L’exécutable devrait maintenant nous donner le drapeau.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&#xA;&lt;/h2&gt;&lt;p&gt;La procédure ci-dessus comprend :&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;une analyse statique avec radare2 et iaito ;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;une analyse dynamique avec GDB comprenant :&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;l’altération du flot de contrôle ;&lt;/li&gt;&#xA;&lt;li&gt;l’inspection de la mémoire ;&lt;/li&gt;&#xA;&lt;li&gt;l’inspection des entiers.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;C’est une procédure très classique en rétro-ingénierie.&lt;/p&gt;&#xA;&lt;p&gt;Au passage, il existe peut-être d’autres approches pour rétroconcevoir cet exécutable. Cependant, quelle que soit l’approche utilisée, elle implique généralement à la fois une analyse statique et une analyse dynamique.&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
