CpawCTFでも割とやっかいなのがリバースエンジニアリング問題だと思っている。
何よりもまず敷居が高すぎる。日本の総人口の99%以上はアセンブラなんて聞いたことすらない。
ということで、リバースエンジニアリングの入門問題、CpawCTF Q21 reversing easy!についてゆっくり解説記事を書いてみる。
初挑戦の人向けにハマリポイントも解説していきたいので、この問題に挑戦する環境はLinuxMint(64bit)ということでいく。ただ、多少の基礎素養は必要なので悪しからず。
具体的には、こちらの本を読んだことがある人であればOKだと思う。
CpawCTFとは?
CTFの初心者向け問題がたくさんある常設サイト。
いつでもだれでも登録すればCTFを始められるうえ、問題もイージーなものから順番に解いていくスタイルなので、初歩から学ぶことができる。私もここから始めました。
Q21 問題の内容
rev100という名前のファイルが渡される。
問題は、「フラグを出力する関数を書き忘れたが、なんとかフラグを出力してくれ」というもの。
問題を解いていく
ファイルの特徴の確認
まずは実行ファイルをダウンロード。
とりあえずファイルの種類を知りたいのでfileコマンドを打ってみる。

fileコマンドの結果、「ELF 32bit」などと表示されている。
これはつまり、ELF形式のファイルで32bitOSで動くということ。
ちなみにELF形式というのはLinux用の実行ファイルのことで、Windowsでいうところのexeファイルみたいなもの。
そして、fileコマンドの前に「ls -l」というコマンドを打っているが、これはそのファイルへの権限をチェックしている。
読み取り権限がr、書き込み権限がw、実行権限がxで表現されるので、このファイルに関しては実行権限が全然ないことがわかる。
そこで、実行権限を付与することにする。

これで実行できるようになった。
さぁ実行するぞ!

( ゚Д゚)ハァ?
となるが、それもそのとおり。
最初にfileコマンドを実行したときに、32bitと表示されていたのを思い出す。
この記事の初めの方に書いてあるとおり、実行時のOSは64bitなのでそのままでは32bitは動かない。
だから、32bitのファイルも動くようにいろいろ追加しないといけない。
$sudo apt install gcc-multilib
$sudo apt install g++-multilib
これだけでOK。さぁ実行しよう!

( ^ω^)・・・
まぁ入門問題とはいってもこれだけじゃだめよね。
お次はStringsして文字列を抽出してみる。

いろいろ出てくるが、真ん中あたりにcpawという文字が見えるのでそのあたりにflagがあるのかなと思うがよくわからない。
IDAを使ってみる
IDAとはなにか
一言でいうと「世界最強のリバースエンジニアリングツール」
実行ファイルを逆アセンブリしてアセンブリ言語にしたり、そこからさらにデコンパイルして元のソースコードを復元できる。
また、デバッガの機能もあるので、ぐりぐりと実行ファイルをいじって動きを確かめることもできる。
IDAのダウンロードとインストール
まずは公式サイトにアクセス。
そもそもIDAは、中古車が買えるくらいの超高級ツールだが、機能制限されたフリー版もある。
今回はフリー版をダウンロードする。(一応同じく無料で使えるデモ版もあるが登録手続きがいる)
IDA Freeware for Linuxというボタンがあるのでクリックしてダウンロード。
そして、ダウンロードしたファイルを実行する。(実行権限がないときは権限付与を忘れずに)

するとこんな画面が表示される。

やっと会えたね!
この女性はサイバーセキュリティ業界で最も有名な歴史上の人物なのでその名を覚えても損はない。
彼女はマントノン侯爵夫人!
中学・高校の世界史の授業では絶対に習っていないレア人物なので、知らない人も多いはず。
ひとことで言うと、フランスの黄金時代の王様ルイ14世の奥さん。バリバリの超貴族。
この人がなぜイメージガール?になったのかというと、ツール制作者が無料素材を漁っていたところたまたま目についたからだとか。
つまり特にこれといった理由もなくイメージガールにされたらしい。
「マントノン侯爵夫人についてもっともっと詳しく知りたいよぉー」という稀有な方はWikipediaをどうぞ。

話を戻してIDAのインストールへ。
ライセンス同意の画面やインストールフォルダの画面が表示されていくのでポチポチ押していく。

このまま進めばインストールが始まりデスクトップにアイコンができる。
これでインストールは完了。
IDAでデバッグしてみる
デスクトップのアイコンからIDAを起動する。
まずはNewをクリック。

すると、ディスアセンブルするファイルを選んでくださいというような画面になるので、cpawCTFの課題ファイルを選んで開く。

すると、IDAがファイルを解析してオススメ設定を表示してくれるのでとりあえずOK。

すると逆アセンブリされたコードとかいろいろ表示される。

次にオプションを設定する。
ツールバーのOptions→Generalから、
Line Presixes(graph)
Stack Pointer
にチェックを入れる。少し見やすくなる。
そして逆アセンブリされたコードの中のmain関数を見ていくと、call _printfという部分が見つかる。
この辺りをよーく見てみると・・・

yakiniku!
おっと・・・普通のディスアセンブラなら自力で計算しないといけないところ、IDAが気を利かせて不思議な文字列を表示してくれている。
yakiniku!ってどういうことかな?かな?
とりあえずデバッグしてみよう。
.textフィールドの、0804852C番地でブレイクポイントを作ってみる。クリックしてF2キーがショートカットだ。
ブレイクポイントを作るとその場所が赤くなるので、続けて実行する。F9が実行ボタンのショートカット。
するとこんな画面になるはず。

カンタンに画面の説明をすると
- 左上がアセンブリのコード
- 右上がレジスタのデータ
- 左下はメモリのデータをダンプした画面
- 右下はスタックのデータ
となる。
このprintf関数の少し前を見てみると、espレジスタの数値に4Ahとか20hとか24hなどをプラスしたところにいろいろなデータを保存していることがわかる。
このときのESPとEBPのデータを見てみると

ふむふむ。
FFADA9C8からFFADA970の間がこの時に有効化されていたスタック領域ということがわかる。
問題文は「出力関数を忘れていた」なので、(しらじらしくも)スタック領域にこそFLAGがあるに違いないと考え、今度はスタックを見に行く。

この手のスタックでは、上に書いてあるもの(つまり、番号が小さいもの)ほど後から入れられている。
つまり、先に出されるということ。(スタックのプッシュとかポップを基本情報の教科書で習いましたよね)
このスタック情報をゆっくりとASCIIに変換していくと、
- FFADA984番地=7D→ }
- FFADA990番地=79→ y
- FFADA994番地=61→ a
- FFADA998番地=6B→ k
- FFADA99C番地=69→ i
- FFADA9A0番地=6E→ n
- FFADA9A4番地=69→ i
- FFADA9A8番地=6B→ k
- FFADA9AC番地=75→ u
- FFADA9B0番地=21→ !
- FFADA9B4番地=70630000→ cp
- FFADA9B8番地=007B7761→ aw{
というふうになる。
cとpは逆じゃね?と思うのも当然。
だが、今どきのコンピュータの低レイヤーはリトルエンディアンで数字を扱っているので、70630000は人間の認識的には、00006370になる。難しければ以下サイトを読むとすっとわかるはず。
このprintf関数がcpaw{}を出力しているかはわかっていないが、とりあえずそれらしい文字列がスタックに積まれていることがわかった。
ということでこいつをうまいこと成形して回答を送信すれば問題クリアとなる。
まとめ
一番簡単なリバースエンジニアリング問題でも、こんなに難しいんだなぁと驚き。
今回はスタックを見ることで答えを探したけど、アセンブリを見るだけで解くこともできるはず。
もちろん逆コンパイルを駆使することもできるだろう。
CTFのリバースエンジニアリング問題は夢いっぱいだね。
コメント