CSAW CTF Qualification Round 2016 Writeup

この大会は2016/9/17 7:00(JST)~2016/9/19 7:00(JST)に開催されました。
今回もチームで参戦。結果は1301点で1274チーム中118位でした。
自分で解けた問題をWriteupとして書いておきます。

Coinslot (Misc 25)

提示された金額をできるだけ大きいコインで支払っていくようにする。

#!/usr/bin/env python

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('misc.chal.csaw.io', 8000))

for i in range(10000):
    data = s.recv(256)
    print data
    if i == 0:
        sum = float(data.split('\n')[0][1:]) * 100
    else:
        sum = float(data.split('\n')[1][1:]) * 100
    sum = int(str(sum).split('.')[0])

    b10000 = int(sum / 1000000)
    sum = sum % 1000000
    ans = str(b10000)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    b5000 = int(sum / 500000)
    sum = sum % 500000
    ans = str(b5000)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    b1000 = int(sum / 100000)
    sum = sum % 100000
    ans = str(b1000)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    b500 = int(sum / 50000)
    sum = sum % 50000
    ans = str(b500)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    b100 = int(sum / 10000)
    sum = sum % 10000
    ans = str(b100)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    b50 = int(sum / 5000)
    sum = sum % 5000
    ans = str(b50)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    b20 = int(sum / 2000)
    sum = sum % 2000
    ans = str(b20)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    b10 = int(sum / 1000)
    sum = sum % 1000
    ans = str(b10)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    b5 = int(sum / 500)
    sum = sum % 500
    ans = str(b5)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    b1 = int(sum / 100)
    sum = sum % 100
    ans = str(b1)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    c50 = int(sum / 50)
    sum = sum % 50
    ans = str(c50)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    c25 = int(sum / 25)
    sum = sum % 25
    ans = str(c25)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    c10 = int(sum / 10)
    sum = sum % 10
    ans = str(c10)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    c5 = int(sum / 5)
    sum = sum % 5
    ans = str(c5)
    print ans
    s.sendall(ans + '\n')

    data = s.recv(256)
    print data

    c1 = int(sum / 1)
    sum = sum % 1
    ans = str(c1)
    print ans
    s.sendall(ans + '\n')

    print 'Round %d' % (i + 1)

400ラウンドしたら、フラグが表示された。

flag{started-from-the-bottom-now-my-whole-team-fucking-here}

Notesy 2.0 (Crypto 1)

問題にフラグが書いてあった。

abcdefghijklmnopqrstuvwxyz

Sleeping Guard (Crypto 50)

ncで接続すると、Base64データらしき長いデータが返ってくる。このデータをdataファイルに保存する。
与えられたコードはKEYについてどんな処理をしているか書かれていないが、PNGファイルの先頭12バイトは決まっていることとKEYとXORをしているのではないかと予想してコードを書いてみる。

import base64

png_head = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
    0x00, 0x00, 0x00, 0x0d]

with open('data', 'rb') as f:
    data = f.read()

data = base64.b64decode(data)

key = []
for i in range(12):
    key.append(png_head[i] ^ ord(data[i:i+1]))

flag = ''
for i in range(len(data)):
    code = ord(data[i:i+1]) ^ key[i % 12]
    flag += chr(code)

with open('flag.png', 'wb') as f:
    f.write(flag)

実行すると、画像にフラグが書かれている。
f:id:satou-y:20160920220726p:plain

flag{l4zy_H4CK3rs_d0nt_g3T_MAg1C_FlaG5}

Watchword (Forensics 250)

添付されていたmp4ファイルに対してforemostを使う。

$ foremost powpow.mp4 
Processing: powpow.mp4
|*|

するとpngファイルが抽出できた。抽出したファイル名をoreo.pngに変える。
f:id:satou-y:20160920221106p:plain

stepicのURLがヒントに出ていたので、stepicを使って画像を抽出する。

$ stepic -d -i oreo.png -o out.png

抽出したファイルはjpg形式のため、out.pngからout.jpgに変更する。
f:id:satou-y:20160920221442j:plain

powpow.mp4のプロパティのタイトルにこう書いてある。

aHR0cDovL3N0ZWdoaWRlLnNvdXJjZWZvcmdlLm5ldC8=

Base64デコードすると、以下のURLになる。
http://steghide.sourceforge.net/

今度はsteghideを使う。パスフレーズはpassword。

$ steghide info out.jpg
"out.jpg":
  format: jpeg
  capacity: 1.7 KB
Try to get information about embedded data ? (y/n) y
Enter passphrase: 
  embedded file "base64.txt":
    size: 83.0 Byte
    encrypted: rijndael-128, cbc
    compressed: yes

$ steghide extract -sf out.jpg

すると、base64.txtが抽出できた。

ここで第2のヒント「Python3のbase64モジュールを使う」という情報から、Base85で復号する。

>c:\python35\python
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64
>>> e = 'W^7?+dsk&3VRB_4W^-?2X=QYIEFgDfAYpQ4AZBT9VQg%9AZBu9Wh@|fWgua4Wgup0ZeeU}c_3kTVQXa}eE'
>>> d = base64.b85decode(e)
>>> d
b'flag{We are fsociety, we are finally free, we are finally awake!}'
>>>
flag{We are fsociety, we are finally free, we are finally awake!}