株式会社Ninjastars 技術研究部

「もっと楽しく安全なゲームの世界を創る」

Ghidra Tutorial + CTF・脆弱性診断 超入門 Reversing④

株式会社Ninastars
取締役:齊藤和輝

好評となっているReversing編ではCTFや脆弱性診断においてのリバーシング技術の基本をお教えします。
今回の記事ではどういった思考でアセンブリを読んでいくのかということを詳細に書いていきます。
またGhidraのチュートリアルとしても利用できるようにしています。
前回私が書いた記事で述べたことは省略する場合があります。
あらかじめ記事を読んでおくことを推奨します。

参考問題集

今回はeagle0wl氏のcrackmeシリーズのcrkme06という問題を使用します。
リンク先からeagle0wl's crackme VOL.01 ver1.02をクリックしてダウンロードしてください。

www.mysys.org

参考サイト

アセンブリ言語の基本知識が掲載されている。
programmer.main.jp

使用ツール

Ghidra

NSA(米国国家安全保障局)が公開した高機能なバイナリ解析ツール。
ninjastars.hatenablog.com

crkme06

crkme04と同様の筋道で解析していきましょう。
ステップ1.静的解析ツール「Ghidra」を使用し、crkme06の逆アセンブルを行う。
ステップ2.正解と不正解を判定する際に必ず必要な関数や我々の目に見える情報の中からキーワードとなる文字列を予想しながら検索する。
ステップ3.ステップ2で検索した結果の前後から比較用オペコードを探しレジスタの流れを理解する。
ステップ4.これ以降はプログラムによって様々な道筋が変わるので考えないことにする.....

ステップ1
Ghidraを起動し、crkme06.exeのファイルをCodeBrowser画面にドラッグ&ドロップして逆アセンブルをしてもらいます。
前回と同様の画面になると思います。

f:id:Ninjastars:20190329143619p:plain
Ghidraによる逆アセンブル

ステップ2
今回は正解したときに「正解です!」と表示されるウインドウを起動している関数を検索していきたいと思います。
前回は文字列を全て列挙して該当するであろう関数名を探すという方法でしたが、今回はImportされている関数を追ってくれるGhidraの機能を用いて検索していきましょう。
CodeBrowserの上部ツールバーでWindow->Symbol TreeでSymbol Treeウインドウを起動してくれます。
Symbol TreeウインドウにてImports->USER32.DLLで今回使用されている関数を列挙してくれます。
ここで注目するのがMessageBoxAです。
MessageBoxはその名の通りメッセージボックスを表示してくれる関数です。しかしながら、今回では非常に重要な手がかりになります。
クリックすると関数を格納している箇所に飛んでくれます。
この関数が使われている箇所に飛んでいきましょう。
参照となっている箇所はXREFで分かります。
XREF[1]: MessageBoxA:00401298
という表記が参照しているアドレスの位置です。
別の場所に飛ばされましたね。しかし、まだ参照している箇所があるので更に飛んでいきましょう。
今回は2箇所あるのですがどちらでも構いません。
これで実際に関数を呼び出して処理をしている命令群に飛んでくれました。

f:id:Ninjastars:20190329145801p:plain
MessageBoxがCALLされているアドレス

ステップ3
このままだと命令群の全体図が見づらいので前回同様フローチャートとして図式化しましょう。
CodeBrowserの上部ツールアイコンの中から"Display Function Graph"をダブルクリックすると以下の画像のようにフローチャートとして図式化してくれます。

f:id:Ninjastars:20190329150328p:plain
フローチャートを表示
アドレス0040126aでCALLされているMessageBoxの周囲は多くのCMP命令が使われています。
f:id:Ninjastars:20190329154318p:plain
MessageBox周辺の命令群
直前ではCMP EBX,0x0がありEBXを比較しています。
なのでこれからはEBXを追っていくことにします。

ステップ4
EBXの中身が0x0になればいいのでまずはどこでEBXの値を初期化しているのか探してみましょう。
よく使われる命令文としてXOR EBX,EBXがあります。
これはMOV EBX.0x0よりもCPUレベルで処理が早いので様々なところで使われます。
アドレス004011f9に初めて出てきました。
つまり004011f9から00401256までの間でEBXに対して何かしらの処理をして分岐していることがわかりました。
画像を見ると直前のMOV EBX,0x1に分岐を飛ばすと正解の処理に分岐しないことがわかります。
EDXの値が0でないときにこの分岐に飛ばされます。
もう少し遡っていきましょう。
注目するのはDo Loopです。ここでは繰り返し同じ処理をしています。どのような処理をしているのかを見ていきましょう。

f:id:Ninjastars:20190329161216p:plain
Do Loopの中身を見ていきましょう。
ループ処理を抜けるにはECXの値が0xa以上になっていればよいです。
ではECXを追っていきましょう。
ECXがカウンタの働きをしているのでDo Loopに入る前ECXの値がどのようになっているかを調べます。
アドレス0040120fにてMOV ECX,0x2となっているのでカウンタの値が0x2から始まっていることが分かります。
またその後の命令CMP AX,0x4f45となっています。AXはEAXレジスタの一部分です。
EAXは下の図のような構造になっています。
f:id:Ninjastars:20190329164822p:plain
EAXの構造
AXが0x4f45と一致していないとEBXの値が変わってしまうのでAXは0x4f45と決まります。
カウンタが0x2から始まっていることを考えると最初の2文字が0x4f45と一致すると考えられます。
次の命令からDo Loopの処理に入ります。
MOVZX EAX,byte ptr[ECX+ESI*0x1]の命令を見ていきましょう。
この命令ではECXつまりカウンタによってアドレスを変更しているので1文字ずつずらしてEAXに入れていることがわかります。
CMP AL,0x30
JC LAB_00401236
CMP AL,0x39
JA LAB_00401236
と連なっている部分はALの値が0x30以上0x39以下の場合MOV EBX,0x1に分岐しないのでALの値は0x30以上0x39以下にしないといけません。
またその後の命令
CMP ECX,0x7
ではECXが7以上である時
SUB AL,0x30
ADD EDX,EAX
の処理に分岐しています。
つまり7文字目以降の文字が判定に使われているということです。
ここまでで出てきた情報を一度整理しましょう。
1.最初の2文字は0x4f45と一致する。
2.3文字目から10文字目まではすべて0x30以上0x39以下である。
3.2の内判定処理に使われているのは7文字目から10文字目だけである。
4.EDXの値は0x0でないといけない。つまり、3での文字は全て0x30でないといけない。

これらをまとめると答えの文字列は
EOxxxxx000(xは任意の数字)という形になることがわかります。
それではcrkme06.exeを起動して打ち込んでみましょう!
f:id:Ninjastars:20190308162046p:plain
正解しました!

イベント告知

2019年4月16日(火)19:00-22:00
株式会社Ninjastars主催、初のセキュリティイベント
Defense against Game Hack with Ghidraを開催します!
Ghidraについての使い方やリバースエンジニアリング手法をハンズオン形式で体験することができるプログラムも用意しています!
皆様、ぜひご参加ください!
申し込みフォームはこちら↓
t.co

f:id:Ninjastars:20190329203020j:plain