tkbctf2 Write-up

tkbctf2にチームsuperflipとして参加した。メンバーは私1人。950点で、個人1位、チーム2位。

私が解いた問題の解法。

weasel (Challenge 1) crypt 150

ブラウザで見ると1行だけど、ソースコードではちゃんと改行されている。ADFGVX暗号。

0 x r 8 d q
j 7 6 z m c
p f h b a 5
1 t w l 3 k
v u e y 2 n
s 9 4 o i g
−・・− ・・−・ −・・ −・・ ・・−・ −・・− ・・・− −−・ ・・−・ −−・ ・・・− −・・− −・・− ・・・− −−・ −・・ ・・・− −・・ −・・ −−・ −・・− −・・− −−・ −・・−

鍵は問題のタイトルかつ、Wikipediaの例の「weasel」。

#coding: utf-8

K = "weasll"
T = [
    "0xr8dq",
    "j76zmc",
    "pfhba5",
    "1twl3k",
    "vuey2n",
    "s94oig",
]
C = u"−・・− ・・−・ −・・ −・・ ・・−・ −・・− ・・・− −−・ ・・−・ −−・ ・・・− −・・− −・・− ・・・− −−・ −・・ ・・・− −・・ −・・ −−・ −・・− −・・− −−・ −・・−"

K = [K[i] for i in range(len(K)) if K[i] not in K[:i]]
c = 0
for i in range(128):
    if chr(i) in K:
        K[K.index(chr(i))] = c
        c += 1

C = [{
    u"・−":     "A",
    u"−・・":   "D",
    u"・・−・": "F",
    u"−−・":   "G",
    u"・・・−": "V",
    u"−・・−": "X",
}[c] for c in C.split()]
CT = []
c = len(C)
while c>0:
    CT += [[""]*min(len(K),c)]
    c -= len(K)
for i in range(len(K)):
    x = K.index(i)
    y = 0
    while y<len(CT) and x<len(CT[y]):
        CT[y][x] = C.pop(0)
        y += 1
C = "".join("".join(c) for c in CT)

P = ""
for i in range(0,len(C),2):
    P += T["ADFGVX".index(C[i])]["ADFGVX".index(C[i+1])]
print P
konecomofmof

The Net (Challenge 2) Trivia 100

問題文は最初は、

You know what.

だけだった。後から点数が下がるとともにヒントが追加された。元は100点だったけど、50点になってから解いた(´・ω・`)

The Net」は映画の名前。画面の右下に「π」が出てくるシーンがあるらしい。コンテストのトップページの右下にもπがあって、class="debuginfo"だった。CSSファイルを見てみると、

.debuginfo .icon
{
    color:#cacaca;
    font:1.5em serif;
    padding:0 2px;
        /* Yes, you have found the answer for the Trivia. The flag is "SandraBullock" */
        /* This challenge is brought to you by @x86_64. */
}
SandraBullock

Do it (Challenge 3) Forensics 200

Do it(やるだけ)問題なのに、解けなかった。

830MBバイトのpcapファイルが渡される。大部分がLinuxイメージのダウンロードなので、その部分を消してWiresharkで開いた。スペックの良いPCならそのまま開けるらしい。Yahoo!で検索したり、Yahoo!メッセンジャーをダウンロードしてzipファイルを送ったりしている。zipファイルは「hello」で開けるけど、フェイク。ユーザーBadManInTsukubaのプロフィール画像が答え。WiresharkのFile→Export→Objects→HTTPでまとめて画像を取り出せる。

BADCAB1E (たぶん)

SkillAnalyzer (Challenge 4) Binary 350

実行すると、Beatmaniaの譜面のようなものが表示される。

>96d4e828f611bdd4e3d2bc45bb9e8a40d59763bb
You're the DJ of this gig!
========
  -
  - - -

 -   - -
   -  -
    -  -
      -
 - -   -
    -

   -
 -

   -

--   - -
========

↓のように打ち込むと、

S157

3

1
3

4
137
6
47
36
157

246
2
You're the 7th dan player!

と表示される。プログラムを解析して何も見つからないと思ったら、↑がそのまま答えだった。解析なんて要らなかったんだ……(´Д`; )

You're the 7th dan player!

Police (Challenge 5) Web 400

XSSする問題。↓inputに細工した文字列を入れて、giveMeTheFlag()を呼び出せばクリア。ただし、この処理の実行中に呼び出してもダメという制約がある。validate(input)は、inputが文字列(/^"[^"]*"$|^'[^']*'$/)、数字(/^\d+(\.\d+)?$/)、正規表現(/^\/[^\/]*\/$/)、もしくはこれらを要素に持つオブジェクト(/^\{.*\}$/で、{}の対応が取れている)かどうかをチェックしている。

return (validate(input) ? Function("return " + input)() : "not Literal");

↓を入力したら通った。返値codeを10と比較している箇所があって、その時にcode.valueOf()が呼び出される。

{valueOf:/*/,a:"*/giveMeTheFlag/*",b:/*/}

\を使う解法もあるらしい。

hatsuneMiku39