読者です 読者をやめる 読者になる 読者になる

Twitterに書ききれないこと

イベントや技術的なことを記したい・・・

SECCON2016 大阪大会参加してきた・・・(だめ)

SECCON2016 大阪大会に参加してきた。
集まれバイナリアンとか書いてあって不安だった。

結果はたぶん8位
自分は全然だめだった・・・
自動化まで完成させて点を取ってくれたチームメイトに感謝。

しかし面白い形式のCTFだったので楽しめた。
せっかくなのでもっと解ければよかった。

以下問題と反省

(追記) チームメイトの記事

SECCON2016 大阪大会(アツマレバイナリアン)ひとり反省会 - ヾノ*>ㅅ<)ノシ帳

問題

問題数は多いが形式は4つ。

とりあえずバックドアを探す簡単なやつをみた。 バイナリを読むと特定のバイナリ列をある値で一文字ずつxorしてその値と一致するればsecretを読み込んで出力していることがわかった。 このロジックはバイナリが変更されても変わらず、バイナリ列とxorのキーが変更されるだけだった。

angrで書くとこんな感じ f:id:pinksawtooth:20161002220814p:plain こいつの出力をbase64してバイナリに渡すとフラグが出る。

ほんとうは競技中angr使えてません・・・手動でやった。

(追記) せっかくだからangrに必要なアドレスの取得まで自動化までしてみようということで書いたスクリプトと簡単な説明。

サーバとの接続,バイナリのダウンロードは岩村さんがサンプルとしてくれてたのでそれを利用する。

いくつかのバイナリを解析するとこんな感じのフラグ出力の前後で命令列が共通していることがわかる。

  40015b:       75 ed                   jne    0x40014a
  40015d:       e8 1e 00 00 00          call   0x400180
  400162:       6a 00                   push   0x0
  400164:       e8 b8 00 00 00          call   0x400221

call 0x400180ではsecretをopen,read,writeしている 。 小さいバイナリなのでpush 0x0の"6a 00"で該当箇所を絞り、さらにjneの直後で現れるという条件を足すとangrに必要なアドレスを求めることができた。 テストケースは手元にあった10個くらいなのでほんとうに全部いけるかわからない。

import commands, angr, base64


bin_file = "bin_213a7d9cd94ce0a17e8a821875f3046f.elf"
cmd = "objdump -d  -Mintel %s | grep -B 2  -A 1 '6a 00' | grep 'jne' -A 1 | awk 'NR==2' | awk -F: '{print $1}'" % bin_file
#print cmd

def main():
    str = commands.getoutput(cmd)
    addr = str.strip()
    #print addr
    p = angr.Project(bin_file, load_options={'auto_load_libs': False})
    ex = p.surveyors.Explorer(find=(int(addr,16)))
    ex.run()

    return ex.found[0].state.posix.dumps(0).strip('\0\n')

if __name__ == '__main__':
    print base64.b64encode(main())

反省

”実行ファイルを解析するのはもう普通!これからの時代は、いかに速く解析できるかだ!!” とHPにあったとおり,今回の競技はいかにはやく自動化するかが勝負を分けた。

手動解析でロジックを特定したが,自動化に手間取ってしまったため出遅れたかなと思う。 とくに自分自身をインポートするという頭付いてないことしてて競技中に動かなかった・・・ひどいミスをしてangrを使えなかったのが無限につらい・・・