SECCON 2014 オンライン予選に参加した&writeup

2014年7月27日 / 未分類

7/19(土) 9:00-21:00に開催されたSECCON CTFオンライン予選に参加しました。
うちのチームは練習問題含めて8問解いて1000点獲得。
一週間遅れですが、解けなかったものも含めてWriteup書いた。


練習問題

指定されたテキスト開けば書いてある。

FLAG{seccon2014}

一度答えを入れて送信したところエラーになり、iPhoneでやってた人に先を越されたorz


Network 100 このパケットを解析せよ

指定されたpcapファイルを開くとFTPの通信が見えたのでこれを抽出する。

net100-1

すると、RETRコマンドでflag.txtをダウンロードしていることがわかる。
FTPではコントロール通信とデータ通信が別の接続で行われるため、「RETR flag.txt」の後に発生している通信を見てみる。

net100-2

これがflag.txtの中身だが、どう見てもBase64エンコードされているのでデコードしてやると

tkito@ubuntu:~$ echo RkxBR3tGN1AgMTUgTjA3IDUzQ1VSM30= | base64 -d; echo
FLAG{F7P 15 N07 53CUR3}

このようにFLAGを取得できる。

余談だが、先日Base64エンコードされたテキストを見て「これは一目でBase64ってわかるよね」と言ったら変態扱いされた。納得いかない。


Network 300 ソーシャルハック?

指定されたアドレスに行くと今流行りのLINE乗っ取り的なチャット画面が出てくる。
中身はJavaScriptで動いていて、ソースを見たところ、こちらの発言がパターンにマッチするとそれに応じた返答(「いくら?」に対して「5000円」など)を返してくる。
パターンにマッチしなかった場合にはサーバに問い合わせて返ってきた内容を発言する。
しかしこれ以上進まなくて終了。

正しい解法は他の人が書いてるので割愛。


Crypto 100 decode me

指定されたファイルを開くと、化けている。
化けてないところを見ると、

FRPPBA 2014
ebg13/47

とある。
これはrot13でエンコードされており、元に戻すと

SECCON 2014
rot13/47

となる。
rot13はともかく、47がわからなかったので、rot47でぐぐったところ、日本語でrot13のようなことをするためのものらしい。
化けてるところ見るとできてないようだけど。
nkfに実装されていることがわかったので、nkfでデコードすると

tkito@ubuntu:~$ nkf -r encoded.txt
SECCON 2014 に参加のみなさまこんにちは。
rot13/47 に気付くとは流石です。
nkfコマンドで簡単にデコードできることにも気付きましたか?
というわけで、おめでとうございます!
フラグは半角英数文字に変換してから入力してください。
FLAG{Have fun SECCON2014}

となり、FLAGを取得できる。


Crypto 300 Decrypt it!

与えられたzipファイルを展開すると、crypt.zipとflag.zipが得られる。
flag.zipにはパスワードがかかっており、crypt.zipにはかかっていない。
crypt.zipを展開すると、cryptというファイルが得られる。
flag.zipには暗号化されているがファイル一覧は取得できるので見てみると、

tkito@ubuntu:~$ unzip -l flag.zip
Archive:  flag.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
    13956  2014-07-15 14:34   crypt
  1088958  2014-07-15 14:35   flag.bin
       89  2014-07-15 14:50   readme.txt
---------                     -------
  1103003                     3 files

crypt.zipに入っていたものと同じ名前同じサイズのファイルがあることがわかる。
平文ファイルが手に入っているので、pkcrackを使えば暗号化を解くことができる。
…はずなのだが、キーが見つからないと言われてしまい挫折。


Forensic 100 879,394bytes
Forensic 300

どちらもチームのフォレンジックマンにお任せした。
見事正解してくれました。


Binary 100 x86アセンブラを読もう

そのまま読んでも何とかなるかも知れないが、頭のCPUエミュレータが正常に動作する保証はなかったため、nopたくさん仕込んであるexeファイルに埋め込んでIDAでデバッグ実行し、01361040に相当するところにSet IPしてデバッグした。
表示されるのは0136105Bでpushしているeaxの値なのでそこまで進めてeaxの値を見ると0xFFFFFFFE。
signedとして解釈すると-2でunsignedとして解釈すると4294967294になるが、どちらを入れてもダメ。

よくわからないので1命令ずつ追っていたところ、0136104Bで0xFFがpushされた際、スタック上の値が0xFFFFFFFFになっていることに気づいた。
FFを4バイトに拡張したらまあそうなるなというところなのだが、スタックの値をいじって0x000000FFとして実行してみたところ、xxxxxx(正確な値忘れた)という値が得られ、これが正解であった。
0136104Bの命令、push FFじゃなくてpush 00FFであるべきだったのでは…


Binary 300 ダンプを追え!

何のダンプかすらわからないまま終了。


Programming 100 重ねてみよう

与えられたファイルはアニメーションGIFファイル。
開いてみると、夜空に星がまたたきます。キレイダナー。
重ねてみようとのことなので、全フレームを分割して、各ピクセルについて全フレームのORを取った画像を出力すると、こんな画像に。

prg100-1

どう見てもQRコードなのでスマホで読み込もうとするも読み込めない。
よく見ると普通のQRコードと白黒が反転している。
というわけで白黒反転させた。

prg100-2

スマホで読むと読み込めて、フラグが出てくる。
最終的なプログラムは下記。

import Image

im = Image.open("afterimage.gif")
im_merged = im.copy()

# merge
try:
    while True:
        im.seek(im.tell() + 1)
        for x in range(0, im.size[0]):
            for y in range(0, im.size[1]):
                if im.getpixel((x, y)) == 1:
                    im_merged.putpixel((x, y), 1)

except EOFError:
    pass

# invert
for x in range(0, im_merged.size[0]):
    for y in range(0, im_merged.size[1]):
        if im_merged.getpixel((x, y)) == 0:
            im_merged.putpixel((x, y), 1)
else:
    im_merged.putpixel((x, y), 0)

im_merged.save("merged.gif")

Programming 300 あみだくじ

プログラミングデキル人におまかせ。
いろいろあって時間内には解けず。

これ、他の人のWrite up見てると問題はランダムではなく固定らしいので、Brute-forceで頑張れば解けるんじゃなかろうか。
現実的な時間で終わるかどうかはわからない。


Web 100 箱庭SQLiチャレンジ

SQLiの箱庭が出てきました。
普通のCTFだと、Web系の問題は主催者運営のサイトが用意されていてそこでいろいろやるんだが、開催期間が終了するとサイトも閉じられてしまい、後からチャレンジできないのが問題であった。
その点この箱庭だと開催期間終了後も解くことができるのですごいありがたい。
今後もこの方針で突き進んでいただきたいです。
この思い、開発者に届け。
何かメモリダンプしたらフラグが見えたみたいな話がありましたがそれはさておき…

さてSQLiです。
お約束のデータを入れます。

' or 1=1;--

web100-1

IDが0-4まで出ているが、これが全ての模様。
続いてselect文のカラム数の確認。

' union select 1,1,1,1,1;--

web100-2

これ以外はエラーとなった。カラム数は5とわかる。
続いてテーブル、カラムの構造の取得。

' union select 1,1,1,1,sql from sqlite_master;--

web100-3

DBはSQLiteのようである。2つSQLが出力されて、1つはID等が入ったテーブル、もう1つはあからさまに怪しいflagというカラムを持つSECCONテーブル。
ではフラグ取得のためSECCONテーブルの中身を見る。

' union select 1,1,1,1,flag from SECCON;--

web100-4

というわけでフラグをゲット。


Web 300 箱庭XSSリターンズ

1ステージ進むたびに前のステージで使った単語(アルファベットと数字からなる文字列)がNGワードに加わるという鬼畜仕様。
3ステージクリアしたところでネタのストックが切れた。
まだまだXSS力は足りない。
なお、真面目にやらずとも解ける裏ワザがあったようで…


Unknown 100 詰将棋?

解けなかった。
チームメンバが結構な時間トライしていたが結局正解できず。
十三手詰と言われているが十一手で詰むパターンが発見されたり、何が正解なのかよくわからない問題であった。


Unknown 300 Print it!

バイナリがノーヒントで与えられる。
見てみると、先頭80バイトが文字列と0で、その次からデータ本体が格納されているように見える。
データ本体部分も解析してみて、頭4バイトがチャンク数、以降その数だけ50バイトのチャンクが続く、というところまでわかった。
チャンクの中身も12バイトの0があった後に4バイトのデータが9個続き、最後に2バイトの0がくる、ということがわかったが、それ以上は何もわからず終了。

CTF期間終了後にIRCでヒントを出している人がいたので、それに従ってぐぐると、STLという3Dデータのフォーマットであることがわかった。
Print it!のPrintは3D Printの意味だったのか、とか、make the keyのmakeは物理的に作るという意味だったのか、とか思ったりした。
STLを読み込めるツールで読むと、以下のようなオブジェクトが出てくる。

unk300

フラグは見ての通り。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

ERROR: si-captcha.php plugin: GD image support not detected in PHP!

Contact your web host and ask them to enable GD image support for PHP.

ERROR: si-captcha.php plugin: imagepng function not detected in PHP!

Contact your web host and ask them to enable imagepng for PHP.

TOPへ戻る