初めまして。みむらです。
チームわさむすめ でリーダーとして全力で旗をふったり、雑務をやったり、
気持ちの上では全員にお茶をくんで運んだりと、
そんな仕事をやっている(つもりです)
まぁ冗談はこの辺にして。
まずは先日行われました SECCON CTF 2013 の WEB 予選で出題されました
Binary 100 の問題である “Enjoy the Game” について解説いたします。
起動しますと、次のような画面が表示されます。
このゲームはキーボードの十字キーで動くことができ、
ゴールに向かい、フラグを入手することが問題の内容となります。
実際に大会で触った方は分かるかと思いますが、
実はゴールには行けないようにマップが構成されており、
そのままでは行くことが出来ません。
そこで、いくつかデータを変更して様子を観察してみます。
data フォルダ内にメタセコイアのテキスト形式での 3D データが入っています。
これは同じフォルダにあるテクスチャの画像から容易に想像できるように、
ゲーム内の壁を表現した 3D データとなっています。
テキスト形式ですのでメモ帳かなにかで見てみますと、
中に Object と書かれた部分が見つかります。
そのうちの vertex (頂点座標)の部分に注目します。
値が3つずつ並んでいて、それぞれ X, Y, Z というように記録されています。
メタセコイアの mqo ファイルは 右手系 Y-up 座標系で表現しますので、
描画した際の高さを表現する部分は真ん中の Y 座標となります。
ここで、 Y 座標をすべて 0 に置換してプログラムを起動してみることにします。
明るさをかなり上げてありますが、このようにマップが大変見やすくなります。
またここで、くるりと回ってみますと、
このようにゴールの場所が見えます。
ですが、もちろんここへは本来であれば壁がある場所ですので
行くことは出来ません。
そこで、プログラムを書き換えて壁の当り判定を無視するようにします。
というわけで、 IDA Pro でプログラムを眺めます。
そうしますと、 0x1400016C7 あたりにそれらしいコードが見つかります。
(このあたりは動的解析をすると簡単に見つかります)
ここでは、
movzx eax, byte ptr [rcx+r9] ; 通路情報が入った配列から該当箇所の情報を取得 cmp al,1 ; 通路どうかを判定 jz short loc_1400016CF ; 通路であれば 0x1400016CF へ飛ぶ
という処理が書かれています。
ですので、”通路であれば” ではなく、
常にジャンプするように書き換えを行います。
スペースキーを押してこの表示に切り替えた後
d キーを押して該当箇所を含めた前後の箇所をバイト表示にして、この情報を元に
バイナリエディタで検索して該当箇所を求めます。
今回の場合は 0xAC9 が該当箇所となります。
元のデータは “74 04” となっており、これは “jz 0x1001006” を表しています。
これを “EB 04” に書き換え、 “jmp 0x1001006” に書き換えます。
書き換えますと次のように書き換わり、
常にジャンプすることが分かるかと思います。
あとはこの状態で、答えの箇所まで・・と行きたいところではあるのですが、
このゲームはまっすぐゴールに向かってもフラグが出ないように作成されています。
そのため、あたかも壁がある場合の動きで、最寄りの場所まで移動し、
ゴールの場所に移動することでフラグが出ます。
私が解いた際には、何度やってもフラグが出ず、
最終的にいくつか出てきた文字列からチームメイトが想像してフラグを求めました。
答え:“3D_dUnGEoN”