<?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 Rebel Zhang のブログ</title>
        <link>https://rebel1725.codeberg.page/blog/ja/tags/gdb/</link>
        <description>Recent content in GDB on Rebel Zhang のブログ</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>ja-JP</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/ja/tags/gdb/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>GDB と Iaito/Radare2 を使ったリバースエンジニアリングの例</title>
            <link>https://rebel1725.codeberg.page/blog/ja/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/ja/post/a-reverse-engineering-example-with-gdb-and-iaito-radare2/</guid>
            <description>&lt;p&gt;ここ数週間、私はリバースエンジニアリングを学んでおり、最初の体験を共有するために&lt;a class=&#34;link&#34; href=&#34;../a-brief-introduction-into-reverse-engineering/&#34; &gt;ブログ記事を書きました&lt;/a&gt;。最近はもう少し踏み込み、静的解析と動的解析を組み合わせて CTF 問題を解いていますが、これはリバースエンジニアリングをもう少し詳しく説明するのにとても良い例だと感じました。&lt;/p&gt;&#xA;&lt;p&gt;以前は GDB を使った動的解析について記事を書くつもりでした。しかし、この問題も GDB を説明するのに非常に良い例だと気づきました。そして、この問題を解くために、もう一つのツールである &lt;strong&gt;iaito&lt;/strong&gt; も使います。これは radare2 のグラフィカルフロントエンドです。&lt;/p&gt;&#xA;&lt;h2 id=&#34;問題&#34;&gt;問題&#xA;&lt;/h2&gt;&lt;p&gt;cIMG は、端末上で異なる色の文字から成る画像を表現するための、一種の画像フォーマットです。これは次の要素で構成されています。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;マジックナンバー、つまり &lt;code&gt;cIMG&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;バージョン番号&lt;/li&gt;&#xA;&lt;li&gt;幅と高さ&lt;/li&gt;&#xA;&lt;li&gt;データ。各ピクセルは R, G, B と ASCII 文字を含みます&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;この問題は、ある実行ファイルに cIMG を渡し、cIMG が特定の条件を満たしている場合にだけ flag を得る、というものです。&lt;/p&gt;&#xA;&lt;h2 id=&#34;ソースコード&#34;&gt;ソースコード&#xA;&lt;/h2&gt;&lt;p&gt;この問題の&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;はこちらから入手できます。このソースコードは BSD 2-Clause ライセンスのようです。&lt;/p&gt;&#xA;&lt;p&gt;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;Python を開き、例として 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;問題のバイナリを使って、この例の 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;このファイルは表示はしますが、flag はくれません。&lt;/p&gt;&#xA;&lt;h2 id=&#34;静的解析&#34;&gt;静的解析&#xA;&lt;/h2&gt;&lt;p&gt;flag を &lt;em&gt;与える&lt;/em&gt; cIMG ファイルを作る必要があります。まずは静的解析から始めましょう。&lt;/p&gt;&#xA;&lt;p&gt;iaito でファイルを開きます。&lt;code&gt;aaa&lt;/code&gt; 解析を実行し、&lt;code&gt;main&lt;/code&gt; 関数のグラフを開きます。次のようになります。&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;the graph of the main function&#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;&lt;code&gt;0x00000cac&lt;/code&gt; でファイルヘッダの読み込み、&lt;code&gt;0x00000cc4&lt;/code&gt; でマジックナンバーのチェック、&lt;code&gt;0x00000cd0&lt;/code&gt; でバージョンチェック、&lt;code&gt;0x00000ce0&lt;/code&gt; で幅と高さの読み込みが確認できます。その後、&lt;code&gt;malloc&lt;/code&gt; で画像データ用のメモリを確保し、そのメモリにデータを読み込みます。&lt;/p&gt;&#xA;&lt;p&gt;マジックナンバーは &lt;code&gt;cIMG&lt;/code&gt; で、16 進数では &lt;code&gt;63 49 4d 47&lt;/code&gt; です。バージョンは 32 ビットの little-endian 整数であり、幅と高さはいずれも 8 ビット整数です。&lt;/p&gt;&#xA;&lt;h2 id=&#34;flag-条件&#34;&gt;flag 条件&#xA;&lt;/h2&gt;&lt;p&gt;関数の末尾を見てみましょう。明らかに &lt;code&gt;sym.win&lt;/code&gt; が flag を与える関数です。これは &lt;code&gt;0x00000e8c&lt;/code&gt; で呼び出されており、この実行は &lt;code&gt;0x00000e58&lt;/code&gt; のチェックの後に行われます。このチェックでは &lt;code&gt;w19&lt;/code&gt; が 0 であってはなりません。&lt;/p&gt;&#xA;&lt;h2 id=&#34;制御フローの改ざん&#34;&gt;制御フローの改ざん&#xA;&lt;/h2&gt;&lt;p&gt;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;&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 0xc44&#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;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;GDB のデータアドレスには &lt;code&gt;0xaaaaaaaa0000&lt;/code&gt; のオフセットがあることが分かります。&lt;/p&gt;&#xA;&lt;p&gt;flag 条件のチェックの直前にブレークポイントを置いて、続行します。&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;レジスタ &lt;code&gt;w19&lt;/code&gt; の内容を変更して続行します。&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;すると実行ファイルは flag を与えてくれます。これで終わりです。よい一日を :-p&lt;/p&gt;&#xA;&lt;p&gt;冗談です。もし本当にこのように問題を終わらせてしまったら、リバースエンジニアリングの楽しさが失われてしまいます。さらに深く見ていきましょう。&lt;/p&gt;&#xA;&lt;h2 id=&#34;データチェック&#34;&gt;データチェック&#xA;&lt;/h2&gt;&lt;p&gt;iaito に戻ります。グラフ内で &lt;code&gt;w19&lt;/code&gt; をクリックします。すると、そのレジスタがグラフ中のすべての命令で強調表示されます。手がかりを探すために、グラフを巻き戻していきます。&lt;/p&gt;&#xA;&lt;p&gt;グラフの中に &lt;code&gt;sym.imp.memcmp&lt;/code&gt; の呼び出しがいくつか見つかります。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;memcmp&lt;/code&gt; は &lt;code&gt;&amp;lt;string.h&amp;gt;&lt;/code&gt; で宣言される C 標準ライブラリの関数で、2 つのメモリブロックをバイト単位で比較します。&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; と &lt;code&gt;ptr2&lt;/code&gt; はそれぞれ 2 つのブロックを指し、&lt;code&gt;n&lt;/code&gt; は比較するバイト数を指定します。2 つのブロックが同一なら、関数は &lt;code&gt;0&lt;/code&gt; を返し、それ以外なら 0 以外の値を返します。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;memcmp&lt;/code&gt; の呼び出しは 4 回あります。各呼び出しの後には &lt;code&gt;cmp w0, 0&lt;/code&gt; があります。最初の呼び出しを除いては、&lt;code&gt;cmp&lt;/code&gt; の後に &lt;code&gt;cset w0, eq&lt;/code&gt; と &lt;code&gt;and w19, w19, w0&lt;/code&gt; もあります。ここから、&lt;code&gt;memcmp&lt;/code&gt; が差分を見つけると &lt;code&gt;w0&lt;/code&gt; が 0 になるため、&lt;code&gt;w19&lt;/code&gt; はクリアされると考えられます。したがって、4 組のメモリブロックを同じにする必要があると推測できます。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;x0&lt;/code&gt; と &lt;code&gt;x1&lt;/code&gt; が比較対象の 2 つのアドレスです。&lt;code&gt;x2&lt;/code&gt; にはサイズが入っており、&lt;code&gt;mov x2, 0x18&lt;/code&gt; から 24 バイトであることが分かります。&lt;/p&gt;&#xA;&lt;p&gt;もう一度 GDB を開き、最初の &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;随机的字节。我看不出它们是什么意思。&lt;/p&gt;&#xA;&lt;p&gt;回到 iaito。第一块内存是从 &lt;code&gt;x22&lt;/code&gt; 读取的，而 &lt;code&gt;x22&lt;/code&gt; 又从 &lt;code&gt;var_48h&lt;/code&gt; 这个地址中读取。&lt;code&gt;afv&lt;/code&gt; 告诉我们它距离 &lt;code&gt;sp&lt;/code&gt; 的偏移是 &lt;code&gt;0x48&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;GDB を再起動し、&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;スタックポインタの値を確認し、ウォッチポイントを設定します。&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;続行します。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-(gdb)&#34; data-lang=&#34;(gdb)&#34;&gt;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;このアドレスを iaito で見つけます。&lt;code&gt;0x00000c58&lt;/code&gt;、つまり &lt;code&gt;0x00000c5c&lt;/code&gt; の 1 つ前の命令で、&lt;code&gt;var_48h&lt;/code&gt; が &lt;code&gt;str&lt;/code&gt; によってクリアされていることが分かります。&lt;/p&gt;&#xA;&lt;p&gt;さらに進めて、この変数がどこで設定されるのかを見ていきます。&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;まだ見ていない新しい関数 &lt;code&gt;initialize_framebuffer&lt;/code&gt; が現れました。&lt;/p&gt;&#xA;&lt;p&gt;iaito でその関数へ移動します。&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;the graph of the initialize\_framebuffer function&#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;&lt;code&gt;0x00001354&lt;/code&gt; の命令で、&lt;code&gt;malloc&lt;/code&gt; によって割り当てられたメモリアドレスが変数に保存されていることが分かります。ただし、それは &lt;code&gt;[x22, 0x10]&lt;/code&gt; として表現されています。&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;。まさに &lt;code&gt;var_48h&lt;/code&gt; のアドレスです。&lt;/p&gt;&#xA;&lt;p&gt;さらに、&lt;code&gt;malloc&lt;/code&gt; に渡されるサイズも興味深いです。これは、オフセット 6 と 7 の値を掛け合わせ、その結果に &lt;code&gt;w1&lt;/code&gt;、つまり &lt;code&gt;0x18&lt;/code&gt;（24）を掛け、最後に &lt;code&gt;x0&lt;/code&gt;、つまり 1 を足して計算されています。&lt;/p&gt;&#xA;&lt;p&gt;そのオフセットの値も見てみましょう。&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;どちらも 10 です。私たちが指定した画像の幅と高さのようです。ハードウェアウォッチポイントを使って確認してみましょう。AArch64 ではアラインメントが必要なので、&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;GNU C Library によるトリガを飛ばします。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-Hardware&#34; data-lang=&#34;Hardware&#34;&gt;&#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;ここで、メモリが &lt;code&gt;0x00000c54&lt;/code&gt; でクリアされているのが分かります。&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-(gdb)&#34; data-lang=&#34;(gdb)&#34;&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;&lt;code&gt;stp xzr, xzr, [buf]&lt;/code&gt; が見えます。上の &lt;code&gt;afv&lt;/code&gt; から、&lt;code&gt;buf&lt;/code&gt; はスタックポインタから &lt;code&gt;0x38&lt;/code&gt; の位置にあることが分かります。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;0x00000cb8&lt;/code&gt; では、&lt;code&gt;buf&lt;/code&gt; からの &lt;code&gt;ldr&lt;/code&gt; と、その後のマジックナンバーのチェックが見つかります。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;0x00000c9c&lt;/code&gt; では、次のような興味深い箇所があります。&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;これで、これらのオフセットにある 2 つの値が幅と高さであることを確認できました。&lt;/p&gt;&#xA;&lt;p&gt;iaito と GDB の &lt;code&gt;initialize_framebuffer&lt;/code&gt; に戻ります。ウォッチポイントを設定してメモリを調べます。&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;上のデータと比較してみましょう。&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; が最初に異なるバイトです。ここにウォッチポイントを設定できます。&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;新しい関数を調べる必要があります。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;the graph of the initialize\_framebuffer function&#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;データの変化は &lt;code&gt;0x00001288&lt;/code&gt; の &lt;code&gt;stp&lt;/code&gt; 命令で起きていることが分かります。&lt;code&gt;0x0000128c&lt;/code&gt; の &lt;code&gt;str&lt;/code&gt; 命令も興味深いので、ここでのメモリを見てみましょう。&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;&lt;code&gt;0xaaaaaaac12b0&lt;/code&gt; からの 8 バイトのブロックは、&lt;code&gt;str&lt;/code&gt; 命令によって変更されています。レジスタがその物語を示しています。&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;&lt;code&gt;x2&lt;/code&gt; についてはあまり気にしなくてかまいません。&lt;code&gt;x4&lt;/code&gt;、&lt;code&gt;x5&lt;/code&gt;、&lt;code&gt;x1&lt;/code&gt; に注目しましょう。&lt;code&gt;0x00001268&lt;/code&gt; と &lt;code&gt;0x00001270&lt;/code&gt; では、非常に重要なレジスタ &lt;code&gt;x25&lt;/code&gt; が見えます。これは、&lt;code&gt;x2&lt;/code&gt; が指すメモリに書き込まれるデータを含むメモリのアドレスを保持しています。そのメモリを調べてみましょう。&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; では、&lt;code&gt;x25&lt;/code&gt; のアドレスが &lt;code&gt;x0&lt;/code&gt; にコピーされます。その後、次のレジスタへいくつかのデータがコピーされます。そして &lt;code&gt;snprintf&lt;/code&gt; が呼ばれます。&lt;code&gt;snprintf&lt;/code&gt; は、書式付き出力を文字配列に書き込みます。&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;つまり、&lt;code&gt;x25&lt;/code&gt; のメモリに書式付き文字列を書き込んでいるわけです。GDB を再起動し、&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;これが書式文字列です。&lt;code&gt;x/s&lt;/code&gt; の結果に違和感がある場合は、Python を使ってこの文字列を 1 バイトずつ表示できます。&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;この書式文字列には 4 つのプレースホルダがあります。最初の 3 つは &lt;code&gt;%03d&lt;/code&gt; で、整数を少なくとも 3 桁の 10 進数に整形します。たとえば 7 は &lt;code&gt;007&lt;/code&gt;、15 は &lt;code&gt;015&lt;/code&gt; になります。最後の 1 つは &lt;code&gt;%c&lt;/code&gt; で、1 文字だけに対応します。&lt;/p&gt;&#xA;&lt;p&gt;これで次のバイトパターンが分かりました。&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;では、プレースホルダに何が入っているのかを調べましょう。&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;すべて &lt;code&gt;0x50&lt;/code&gt; です。これは例の cIMG で使ったデータのようです。ここを明確にするために、cIMG を再作成してみましょう。&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;したがって、上の 16 進パターンにある N1, N2, N3 はそれぞれ R, G, B に対応し、CH は埋め込みたい文字そのものです。&lt;/p&gt;&#xA;&lt;p&gt;これで GDB に戻り、各 &lt;code&gt;memcmp&lt;/code&gt; の前でブレークし、&lt;code&gt;x/24xb $x1&lt;/code&gt; を実行して期待される framebuffer を調べます。そして、その framebuffer を使って期待される cIMG データを復元します。あとは十六進エディタでそのデータを書き込めばよいです。&lt;/p&gt;&#xA;&lt;h2 id=&#34;サイズのチェック&#34;&gt;サイズのチェック&#xA;&lt;/h2&gt;&lt;p&gt;しかし、期待されるデータを埋めても、実行ファイルはまだ flag を返しません。GDB でメモリを確認すると、&lt;code&gt;memcmp&lt;/code&gt; は期待通り 0 を返していました。したがって、満たされていない別の条件があるはずです。&lt;/p&gt;&#xA;&lt;p&gt;iaito に戻り、最初の &lt;code&gt;memcmp&lt;/code&gt; から後ろへさかのぼります。&lt;code&gt;0x00000d60&lt;/code&gt; に &lt;code&gt;cmp&lt;/code&gt; があり、&lt;code&gt;var_40h&lt;/code&gt; と 4 を比較しています。&lt;code&gt;initialize_framebuffer&lt;/code&gt; の &lt;code&gt;0x00001348&lt;/code&gt; には、幅と高さの積を保存する &lt;code&gt;str&lt;/code&gt; があります。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;0x00000d60&lt;/code&gt; の &lt;code&gt;cmp&lt;/code&gt; が、その後の &lt;code&gt;w0&lt;/code&gt; の値を決めます。&lt;code&gt;var_40h&lt;/code&gt; が 4 なら &lt;code&gt;w0&lt;/code&gt; は 1 になり、それ以外なら 0 になります。&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;0x00000d78&lt;/code&gt; では &lt;code&gt;w0&lt;/code&gt; が 0 と比較され、&lt;code&gt;0x00000d84&lt;/code&gt; の &lt;code&gt;ccmp&lt;/code&gt; 命令の動作に影響します。&lt;code&gt;[x22, 0x13]&lt;/code&gt; の内容が &lt;code&gt;w0&lt;/code&gt; に読み込まれ、&lt;code&gt;[x1, 0x13]&lt;/code&gt; が &lt;code&gt;w2&lt;/code&gt; に読み込まれます。&lt;code&gt;memcmp&lt;/code&gt; から分かるように、&lt;code&gt;x22&lt;/code&gt; は実際の framebuffer のアドレスで、&lt;code&gt;x1&lt;/code&gt; は期待される framebuffer のアドレスです。すでにデータは期待値と一致しており、オフセット 19 は ASCII 文字なので、&lt;code&gt;w0&lt;/code&gt; と &lt;code&gt;w2&lt;/code&gt; は同じであり、かつ 0 ではないはずです。&lt;/p&gt;&#xA;&lt;p&gt;ここから、&lt;code&gt;var_40h&lt;/code&gt; が 4 なら &lt;code&gt;w2&lt;/code&gt; は &lt;code&gt;w0&lt;/code&gt; と比較され、その結果 &lt;code&gt;w19&lt;/code&gt; は 1 に設定される、と結論できます。それ以外の場合、&lt;code&gt;w2&lt;/code&gt; は 0 と比較され、&lt;code&gt;w19&lt;/code&gt; は 0 になります。&lt;/p&gt;&#xA;&lt;p&gt;最初の &lt;code&gt;memcmp&lt;/code&gt; の後では、&lt;code&gt;0x00000e7c&lt;/code&gt; で &lt;code&gt;w0&lt;/code&gt; が 0 なので、&lt;code&gt;w19&lt;/code&gt; は 0 と比較されます。すると &lt;code&gt;cset&lt;/code&gt; によって、等しくなければ &lt;code&gt;w19&lt;/code&gt; は 1、そうでなければ 0 に設定されます。&lt;/p&gt;&#xA;&lt;p&gt;そこで、hex エディタを使って cIMG を修正し、幅と高さを掛け合わせると 4 になる値に変更します。たとえば &lt;code&gt;0202&lt;/code&gt; にできます。これで実行ファイルは flag を返すはずです。&lt;/p&gt;&#xA;&lt;h2 id=&#34;結論&#34;&gt;結論&#xA;&lt;/h2&gt;&lt;p&gt;上で説明した手順には次が含まれます。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;radare2 と iaito を使った静的解析&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;GDB を使った動的解析。内容は次のとおりです。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;制御フローの改ざん&lt;/li&gt;&#xA;&lt;li&gt;メモリの निरी視&lt;/li&gt;&#xA;&lt;li&gt;整数の確認&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;これはリバースエンジニアリングではごく典型的な手順です。&lt;/p&gt;&#xA;&lt;p&gt;ちなみに、この実行ファイルを逆向きに解析する方法は他にもあるかもしれません。しかし、どの方法を使うにしても、たいていは静的解析と動的解析の両方が関わります。&lt;/p&gt;&#xA;</description>
        </item></channel>
</rss>
