SECCON 2017 Online CTF Writeup #seccon

スキルも文章力もない奴が何偉そうに言ってんの?(自分です)と思ったので書く。

とあるチームに参加して4問解いた。Submitしたのは上の3問で計500点。

Vigenere3d (Crypto 100)

ヴィジュネル暗号の3次元版。
2つ目の鍵を使ってヴィジュネル暗号の表を3次元方向に拡張している。

ヴィジュネル暗号の強さは鍵の長さ(=周期)に依存している。
Vigenere3dは、鍵を2つ用いているため、周期は2つの鍵の長さの最小公倍数となる。
問題のプログラムでは2つの鍵が同じ長さになっているため、拡張した意味がまったくない…

さて、暗号プロセスを見てみると、平文1文字に対して、2つの鍵のsにおけるインデックスの和で暗号文が決まることがわかる。
t[x]のデータを表にしてみるとわかりやすい。以下は平文が’S’の場合。

この問題では、2つ目の鍵は1つ目の鍵を逆順にしたものにしている。
このため、1つ目の鍵と2つ目の鍵のインデックスの和、というのは、後ろ半分の8文字目からは1~7文字目の順番を逆にしたものとなり、前半分の7文字分だけ鍵(のインデックスの和)がわかれば全部わかることになる。
7文字分は平文と暗号文の両方がわかっているため、これだけで鍵が全部導出できる。
平文1文字分ずつ上記の表を出して暗号文との対応から鍵を求めていくと、vigenere3d.pyの入力として与える鍵(の一例)は

AAAAAAA_aZ2PK_

であることがわかる。
あとは復号プログラムを作って暗号文と鍵を与えてやればいい。

import sys

def _l(idx, s):
return s[idx:] + s[:idx]

def main(c, k1, k2):
s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
t = [[_l((i+j) % len(s), s) for j in range(len(s))] for i in range(len(s))]
i1 = 0
i2 = 0
p = ""
for a in c:
for i in range(len(s)):
if t[i][s.find(k1[i1])][s.find(k2[i2])] == a:
p += s[i]
break
i1 = (i1 + 1) % len(k1)
i2 = (i2 + 1) % len(k2)
return p

print main(sys.argv[1], sys.argv[2], sys.argv[2][::-1])
Flag: SECCON{Welc0me_to_SECCON_CTF_2017}

Run me! (Programming 100)

与えられたソースコードを見ると、11011番目のフィボナッチ数の頭32桁がフラグの模様。
あとは下の通り。

Flag: SECCON{65076140832331717667772761541872}

Powerful Shell (Binary 300)

難読化(?)されたPowershellスクリプトを解析する(Binary…?)
要所要所で変数に保持したPowershellプログラムを実行する部分があるので、代わりにWrite-Hostで標準出力に出すなどしてやれば見ることができる。

1段目。
文字を延々と生成して変数$ECCONに追加している。
最後の”Write-Progress -Completed”の後に実行しているので変数$ECCONを出力してやればよい。

2段目。
キーボードを叩いて秘密のメロディを演奏させる。演奏されたメロディが正しいと次の段階に進む。
環境等チェックしているところはコメントアウトしつつ、Powershell ISEでデバッグ実行するのが楽、
“Play the secret melody.”と標準出力に出しているところまで進むと$keytoneにキーと鳴らす音の周波数の対応が入っている。
正解のメロディは少し後の$secret変数に周波数の列として納められているので$keytoneの内容と見比べて正解のキー列を得る。
ソースを追っていくと入力したキー列は$fに文字列の形で入っているため、正解のキー列で文字列を作っておく。

$f = "hhjhhjhjkjhjhf"

この$fは後でXORデコードの鍵として使われる。
下の方の$text以降に上記の$fの値を設定する一行を加え、最後のiexをWrite-Hostに書き換えれば実行されるコードを取得できる。

3段目。
最後はPowershellでの記号プログラミング。
記号のみで任意のPowerShellコードを実行 – JPerl advent calendar 2010 Sym Trackに書かれているのとまったく同じやりかたで記号化している。
(上記リンクはサーバにアクセスできなかったため、Web Archiveにリンクしている)
やり方を見て解読していけばいい。

Flag: SECCON{P0wEr$H311}

Simon and Speck Block Ciphers (Crypto 100)

アルゴリズム、平文、暗号文、鍵の一部が与えられており、鍵がフラグになっている。
鍵のうちわからない部分はたった4文字なので、Brute forceすればよい。
ググるとGitHubに実装があったのでこれを使った。

from simon import SimonCipher

def str2long(s):
l = 0
for i in range(len(s)):
l = l * 256 + ord(s[i])
return l

plain = 0x6d564d37426e6e71
cipher = 0xbb5d12ba422834b5

chars = [ chr(i) for i in range(33, 127) ]
solved = False
for c1 in chars:
for c2 in chars:
print "c1 = %c, c2 = %c" % (c1, c2)
for c3 in chars:
for c4 in chars:
k = "SECCON{%c%c%c%c}" % (c1, c2, c3, c4)
s = SimonCipher(str2long(k), key_size = 96, block_size = 64)
if s.encrypt(plain) == cipher:
print "Key = %s" % k
solved = True
break
if solved:
break
if solved:
break
if solved:
break
Flag: SECCON{6Pz0}

以上。
久しぶりのCTFで楽しかったが、セキュリティの知識が必要とされる問題を解けていないことがわかる。
実働時間も短かった(まあこれはしょうがない)
Pwn系を解けなかったしそのスキルがあるとは思えないので精進したい。

コメントを残す

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

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください