株式会社Ninjastars 技術系ブログ

「本質的安全を提供し、デジタル社会を進化させる!!!」

CTFから学ぶ! Harekaze CTF 2018 15 Puzzle

株式会社Ninjastars
セキュリティエンジニア:一瀬健二郎

今回は2018年に開かれたHarekaze CTF 2018のReversingの問題「15 Puzzle」について記載します。
この問題を通して.NET製アプリケーションがどのような構造を持っているか解析してみたいと思います。
解析ツールとしてCheat Engineとdnspyを利用します。
またCheat Engineについてはツールの詳細な使い方は省略します。

製作者のst98様のwriteup
Harekaze CTF 2018 で出題した問題 (Obfuscated Password Checker, Sokosoko Secure Uploader, 15 Puzzle, Logger) の解説 - st98 の日記帳

問題について

dnspyでデコンパイル->改変->再コンパイルを行い実行すると、実行プログラムのILのバイト列を元にフラグを生成しているため文字化けして正しい答えが現れません。
C#ソースコードを解析し正しい改変を行い解くのが正攻法であると思われますが、別の解き方をしてみます。

解析

プログラムを起動し何度かパネルのボタンをクリックします。
Cheat Engineでアタッチし、Memory View->View->Enumrate DLL's and Symbols
これはプロセスにロードされた全モジュールと全シンボルを列挙してくれる機能であり、以下のような結果となります。

f:id:Ninjastars:20190521144119p:plain
全モジュール+全シンボル情報の列挙

Form1::IsPuzzleSolvedの項目をダブルクリックしてみましょう。
するとILからアセンブリに変換された、実際に内部で動作しているプログラムを見ることが出来ます。

f:id:Ninjastars:20190521142615p:plain
アセンブリに変換されたIL

isPuzzleSolvedなので戻り値が必ず1になるように関数を改竄します。

mov eax,1
ret

パネルをクリックするとScoreが1ずつ増えていくことが分かります。
またILを直接改竄しているわけではないので、CRCによるチェックとも無関係です。
通常の解法と同じでパネルを1000回クリックすればフラグが現れます。
このように状況によってはdnspyでデコンパイル->改変->再コンパイルをする必要はなく、動的に生成されたアセンブリを直接改竄する場合の方が早いことがあります。

今回は関数名から改竄すべき処理がすぐわかりましたが、関数名が難読化等されている場合のアプローチを考えてみましょう。

解析2

private int[] panels = new int[16];

dnspyのデコンパイル結果からpanelsはint型の配列であるので、16進バイト列でメモリ検索してみます。
左上から右に行く順番でデータが配置されてると予想して、下のような画像の場合数値はリトルエンディアンなので以下のバイト列で検索します。
バイト列:03 00 00 00 0f 00 00 00 ** ** ** ** 09 00 00 00(10進:3 15 * 9)
数字がない場合の数値は予想できないので、ワイルドカード*を利用して検索します。
下記の画像のように1つ検索が見つかりますが、この数値がパネルの情報を保持しているアドレスとなります。
※今回はint型配列であると分かっている前提ですが、仮にpanels変数自体も難読化され分からなくてもプログラミングのセオリー的なことからある程度データ構造の予想をすることはできます。

f:id:Ninjastars:20190521190244p:plain
メモリ上に展開されたパネルの情報

ここからのアプローチは下のように考えてみます。

1.クリック時に各パネルが正しい位置にあるか判定する処理が存在するだろうと予想する。
2.パネル情報を保持しているメモリアドレスにハードウェアブレークポイントを設置する(参照、書き込みを検知)。
3.パネルの数値の比較判定条件を常にtrueにする。または元の処理を探り改竄する。
etc

左上のパネルに該当するアドレスにブレークポイントを設置しパネルをクリックしてみます。
下記のような処理がヒットしたので一番上の命令のアドレスに逆アセンブル画面を移動させます。

f:id:Ninjastars:20190521190622p:plain
ハードウェアブレークポイントで検知した処理

mov eax,[ecx+esi*4+08]
lea edx,[esi+01]
cmp eax,edx
je 007C20A5

上記を

cmp eax,edx=>cmp eax,eax

に書き換えます。

実際にパネルをクリックすると常にScoreが+1されていくことが分かりました。
このように断片的な情報からデバッガなどを利用して解析していくアプローチは様々な場面で有効です。
また逆に対策する側としても関数名さえ分からなければ解析できない等と安易に考えることは危険です。

注意事項

本レポートに記載されている内容を許可されていないソフトウェアで行うと、場合によっては犯罪行為となる可能性があります。そのため、記事の内容を試す際には許可されたソフトウェアに対してのみ実施するようにしてください。

本レポートについて
お問い合せ
E-mail:ichise@ninjastars-net.com

株式会社Ninjastarsエンジニア
一瀬健二郎