(runme.xの解析)
サーバからダウンロードできる runme.x では,同様の特殊命令が利用されて パスワードのデコードが行われています.
特殊命令の仕様がわかれば,スクリプトなどでデコード結果を計算できます.
このようにしてパスワードが得られれば,そのパスワードを以下のようにして
サーバにコミットして,防御ポイントが得られます.
$ echo "<パスワード> <チームフラグ>" | nc <サーバのアドレス> 9999このためいかにrunme.xを解析してパスワードを復元するか, もしくはrunme.xを実行してパスワードを得るか, というのが競技になります.
まずは runme.x を解析してみましょう.
$ file runme.x runme.x: ELF 32-bit LSB executable, Analog Devices Blackfin, version 1 (SYSV), statically linked, strippedBlackfinの実行ファイルのようです.
なのでこの runme.x を今までやったように頑張って解析して, 実行したときの結果がわかればいいわけです.
なお競技時のままだと runme.x はstripされていてデバッグ情報が
落ちていて,解析の敷居が高いです.
サーバの /home/user/exec-sim/make.sh の以下の部分を削除して,
stripされないようにしておくといいかと思います.
/home/user/tools/cross-gcc494/bin/${arch}-strip ${arch}.x
さて,このrunme.xですが,冒頭で説明した runme.x の実行環境があれば,
以下のようにして実行できます.
(これは特殊命令の対応がされた実行環境です.もちろん競技者はこの環境を持ちません)
$ /home/user/tools/cross-gcc494/bin/bfin-elf-run --environment user runme.x PASSWORD:XXXXXXXXXXXXXXXX $このパスワードをサーバにコミットします.
$ echo "XXXXXXXXXXXXXXXX teamflag" | nc 127.0.0.1 9999 Valid password.「Valid password」と言われれば成功です.
成功した場合,サーバのインフォメーションページからリンクされている
flag.txtというページに,「teamflag」と掲載されるはずです.
競技では,これでチームフラグをコミットすれば,そのチームに防御ポイントが入ります.
もちろん競技者はこの実行環境を持ちませんが,runme.xからうまくパスワードが 取得できれば,こんなふうにして防御ポイントが取得できます.
チームフラグのコミットは短時間に繰り返しはできません.
またrunme.xは5分おきに更新されます.
runme.xが更新されたら,新たなrunme.xを実行して最新のパスワードを取得します.
(最新のパスワードでないと,コミットできません)
最初のうちは runme.x の内容は,パスワードのデコード元のデータと
乱数命令の設定パラメータとシードが異なるだけで,
プログラム自体に変化はありません.
実際には乱数命令によって得られた乱数を,デコード元のデータにxorで
掛け合わせているだけです.
なので,乱数アルゴリズムが推定できれば,静的解析によってパスワードを 取得することは,難しくはありません.
しかしそのようにしてパスワードの取得とチームフラグのコミットを
繰り返し行っていると,runme.xの内容が徐々に変わってきます.
具体的には,decrypt()の内容が微妙に変わってきます.
もっと詳しく言うと,乱数に 0x55 を xor してからデコードする場合が
出てきます.
runme.xを逆アセンブルして,確認してみてください.
ただし必ず0x55が掛け合わせてあるというわけではなく,
そうでない,元と同じ場合もあります.
このため静的解析で0x55の対応ができなかった場合には,
「runme.xが運良く元と同じプログラムだった場合にはパスワードがわかるが,
そうでない場合(0x55がxorされる場合)にはパスワードがわからない」
という状態になります.
つまり運によってパスワードがわかったりわからなかったりするように なるわけです. (もちろん0x55の対応ができれば,その場合にもパスワードは取得できます)
で,引続きチームフラグのコミットを続けると,今度はたまに そもそも bfin-elf-run では実行できないrunme.xが出てきます.
※ コミットが面倒だったら,サーバの /home/user/tmp/count.txt に
コミットの成功数がカウントされているので,これを手動で増やしてください.
count.txtの値に応じてrunme.xの変移が大きくなります.
詳しくは exec-sim の make.sh と,そこから呼び出されるスクリプトを参照
※ 標準ではrunme.xは5分で更新されます.速めたい場合には,/home/user/tmp/interval.txt を調整してください
アーキテクチャを調べてみます.
$ file runme.x msp430-elf.x: ELF 32-bit LSB executable, TI msp430, version 1 (embedded), statically linked, not strippedMSP430というアーキテクチャが出てきています.
その先は,runme.xが以下のように変化してきます.