teppay’s log

技術ブログです。

DEF CON Quals 2018 Writeup

はじめに

  • 常設なCTF(おもにLSE CTF)はちょいちょい解いていましたが,久しぶりのイベント型?CTF参加です
  • いままでSECCONオンライン予選にしか出たことがありませんでしたが,これからはチームも組めそうなのでじゃんじゃん挑戦していければと思っています.
  • 今回も今までどおりぼっち参戦です
  • 他の用事もあったので,warmup1問しか解けず,後追いでwarmupをもう1問ときました.つまり,大会終了後にwarmupを終えました...

解けた問題

You Already Know(warmup) - 101pt

Stop overthinking it, you already know the answer here.

You already have the flag.

Seriously, if you can read this, then you have the flag.

「これを読んでいるということは,もうFlagをゲットしているよ」と言われた.
これ系の問題はだれかのWriteupで見たことがあったし,warmupなので簡単だろうということで,Chromeの開発者ビュー?のNetworkタブでレスポンスを見てみたらコメントにFlagがあった

ELF Crumble(warmup) - 102pt

We prepared this beautiful binary that just printed for you the welcome flag, but it fell on the ground and broke into pieces.

Luckily no instruction was broken, so I am sure you can just glue it back together…

Flag format is non-standard, there are no brackets.

「Welcome Flagがprintしただけの美しいバイナリを用意したけど,壊れちゃったからくっつけてなおしてね」と言われた.
与えられたtgzファイルを解凍すると,以下のファイルが出てきた.

$ ll
-rwxr-xr-x@ 1 teppay  staff   7.3K  5  2 05:37 broken
-rw-r--r--@ 1 teppay  staff    79B  5  2 05:42 fragment_1.dat
-rw-r--r--@ 1 teppay  staff    48B  5  2 05:46 fragment_2.dat
-rw-r--r--@ 1 teppay  staff   175B  5  2 05:47 fragment_3.dat
-rw-r--r--@ 1 teppay  staff    42B  5  2 05:48 fragment_4.dat
-rw-r--r--@ 1 teppay  staff   128B  5  2 05:56 fragment_5.dat
-rw-r--r--@ 1 teppay  staff    22B  5  2 05:56 fragment_6.dat
-rw-r--r--@ 1 teppay  staff   283B  5  2 06:00 fragment_7.dat
-rw-r--r--@ 1 teppay  staff    30B  5  2 06:00 fragment_8.dat

$ file *
broken:         ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=4cd47d8a237a3139d1884b3ef52f6ed387c75772, not stripped
fragment_1.dat: data
fragment_2.dat: data
fragment_3.dat: data
fragment_4.dat: data
fragment_5.dat: data
fragment_6.dat: data
fragment_7.dat: data
fragment_8.dat: data

唯一のELFファイルであるbrokenstringsコマンドに食わせてみると,

$ strings broken
[snip]
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[snip]

この様に807バイトのXが連続した文字列が見つかり,これは明らかにあやしい.
問題文とbroken以外のファイル名に共通しているflagment(断片)という単語から,このXで埋められた部分にflagment-n.datたちが入ることで,バイナリが完成するのではと思い,flagment-n.datのファイルサイズを足してみたら,ビンゴだった.

$ expr 79 + 48 + 175 + 42 + 128 + 22 + 283 + 30
807

つまり,このflagment_n.batを正しい順番に並べ替えて,Xで埋められた部分にはめればいいというわけだと思う.

※※恥ずかしげもなく長ったらしくWriteupしていますが,この問題はwarmup問題です

objdumpしてbrokenの中身を見てみると,

  • f1
  • f2
  • f3
  • recover_flag
  • main

の5つの関数がXで塗りつぶされている. そのままobjdumpの出力を使って,それぞれの関数のサイズを調べてみると,

  • f1 316Byte (0x5ad~0x6e8)
  • f2 69Bytes (0x6e9~0x72d)
  • f3 116Bytes (0x72e~0x7a1)
  • recover_flag 58Bytes(0x7a2~0x7db)
  • main 248Bytes(0x7dc~0x8d3)

関数の個数とサイズを見て,関数とfragment_n.datのファイルたちは 1対1には対応していないだろうということで,次にfragment_n.datファイルを見ていくことにした.

objdumpできるかと思ったらさすがひらけず,IDAで開いてみたらディスアセンブルできた.(たまにデータと認識されている部分があったので,'C'を押してコードと認識し直してもらいながら)
アセンブラを読んで関数のつながりのようなものを見ていければ良いのかもしれないが,自分はまだ関数のはじめとおわりを認識するのがやっとなので,以下のようにfragment_n.datの中の構造を書き出してみた.

fragment_1.dat
  • 関数の後半(3Bytes)|関数(69Bytes)|関数の前半(5Bytes)
fragment_2.dat
  • 関数の後半(11Bytes)|関数の前半(26Bytes)
fragment_3.dat
  • 関数の中間部分(175Bytes)
fragment_4.dat
  • 関数の後半(42Bytes)
fragment_5.dat
  • 関数の後半(109Bytes)|関数の前半(17Bytes)
fragment_6.dat
  • 関数の中間部分(20Bytes)
fragment_7.dat
  • 関数の中間部分(281Bytes)
fragment_8.dat
  • 関数の始まり(29Bytes)

おそらくバイナリの最後の命令のバイト数がわからなくて若干のずれが生じてしまっているが,関数のサイズと照らし合わせるとfragment_{8,7,1,5,6,2,3,4}.datの順番でならべるとピッタリはまる(はず)

そこでひとまずこれらを並べてくっつけた,pieceというバイナリを作った.

$ cat fragment_8.dat fragment_7.dat fragment_1.dat fragment_5.dat fragment_6.dat fragment_2.dat fragment_3.dat fragment_4.dat > piece

ということで,あとはこれをbrokenに埋め込むだけ...やりかたがわからない

もっとスマートな方法を使いたかったが,わからなかったのでバイナリエディタでコピペして,願いもこめてnotbrokenという名前で保存した.

$ ./notbroken

と実行したら,それらしい出力があったので解けたみたい