teppay’s log

技術ブログです。

SECCON 2017 Online CTF Writeup

はじめに

  • SECCON 2017 Online CTFにぼっち参戦しました。
  • 解けた問題は、
    • Vegenere3d
    • Run me!
    • putchar music
    • SHA-1 is dead
    • Log search
    • Thank you for playing!
      の6問で600点でした。
  • これまでずっと書いてみたかったWriteupを初めて書いてみます。お見苦しかったらごめんなさい。

Writeup

Vigenere3d

----- Vigenere3d.py
import sys
def _l(idx, s):
    return s[idx:] + s[:idx]
def main(p, 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
    c = ""
    for a in p:
        c += t[s.find(a)][s.find(k1[i1])][s.find(k2[i2])]
        i1 = (i1 + 1) % len(k1)
        i2 = (i2 + 1) % len(k2)
    return c
print main(sys.argv[1], sys.argv[2], sys.argv[2][::-1])
-----
$ python Vigenere3d.py SECCON{**************************} **************
POR4dnyTLHBfwbxAAZhe}}ocZR3Cxcftw9

去年はふつーのVigenereが出ましたが(数少ない解けた問題だったので覚えてる)、今年はVigenere3dということで3DのVigenere cipherが出ました。Vigenereは簡単に言えば、1文字ずつシフトする数を変えたシーザー暗号ですが、3Dになってもそれは変わりません。なので、ズレ幅を計算してあげればkeyがわからなくても解けました。
去年は、keyのわからない部分の候補を減らしてその後はブルートフォースした気がしますが、今回はスマートに解けた気がします。

s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz_{}"
pref = 'SECCON{'
key = []
c =    'POR4dnyTLHBfwbxAAZhe}}ocZR3Cxcftw9'

for i in range(len(pref)):
    key.append(len(s) + s.find(c[i]) - s.find(pref[i]) % len(s))

key = key + key[::-1] 

i = 0
flag = ''
for a in c:
    flag += s[(len(s) + s.find(a) - key[i]) % len(s)]
    i = (i + 1) % len(key)

print(flag)
SECCON{Welc0me_to_SECCON_CTF_2017}

Run me!

Run me!
-----  RunMe.py
import sys
sys.setrecursionlimit(99999)
def f(n):
    return n if n < 2 else f(n-2) + f(n-1)
print "SECCON{" + str(f(11011))[:32] + "}"
-----

Run me と言われていますがそのままRunしたら明らかに時間がかかるので、とりあえずメモ化してみたら一瞬でした。

from functools import lru_cache
import sys

sys.setrecursionlimit(99999)

@lru_cache(maxsize=15000)
def f(n):
    return n if n < 2 else f(n-2) + f(n-1)
print("SECCON{" + str(f(11011))[:32] + "}")
SECCON{65076140832331717667772761541872}

qiita.com

putchar Music

putchar music
This one line of C program works on Linux Desktop. What is this movie's title? 
Please answer the flag as SECCON{MOVIES_TITLE}, replace all alphabets with capital letters, and spaces with underscores.

main(t,i,j){unsigned char p[]="###<f_YM\204g_YM\204g_Y_H #<f_YM\204g_YM\204g_Y_H #+-?[WKAMYJ/7 #+-?[WKgH #+-?[WKAMYJ/7hk\206\203tk\\YJAfkkk";for(i=0;t=1;i=(i+1)%(sizeof(p)-1)){double x=pow(1.05946309435931,p[i]/6+13);for(j=1+p[i]%6;t++%(8192/j);)putchar(t>>5|(int)(t*x));}}

これは実行しないで、タイミング的にあれかなと思って試しに入れてみたら通りました。ごめんなさい笑

SECCON{STAR_WARS}

SHA-1 is dead

この問題は今年のはじめにGoogleが発表したSHA-1脆弱性?、SHAtteredについての問題でした。 SHA-1が同じだけど、違うファイルを作れって話です。

SHA-1 is dead
http://sha1.pwn.seccon.jp/
Upload two files satisfy following conditions:

1. file1 != file2
2. SHA1(file1) == SHA1(file2)
3. SHA256(file1) <> SHA256(file2)
4. 2017KiB < sizeof(file1) < 2018KiB
5. 2017KiB < sizeof(file2) < 2018KiB
* 1KiB = 1024 bytes

Googleが発表した際のサイトですでにSHA-1が衝突したPDFがダウンロードできますが、それではファイルサイズの条件に合致しません。そこで最初は1から新しくSHA-1が衝突したファイルを作るのかと思って調べていたら以下のスライドに行き着きました。

www.slideshare.net

例の脆弱性は、SHA-1の性質上、衝突した2つのファイルそれぞれの後ろに同じものをくっつけても、SHA-1は衝突したままになるというものだったそうです。(くわしくはスライドを。。) なので、例の公開されたPDFの後ろに、ファイルサイズが 2017KiB < sizeof(file) < 2018KiBになるようにゴミをくっつけてやりました。

target_size = 2017 #kB

def main():
    with open('shattered-1.pdf', 'rb') as fin1:
        b1 = fin1.read()
        origin_size = int(len(b1)/1024)

    add = b'\xff' * ((target_size - origin_size) * 1024)
    b1 += add


    with open('shattered-2.pdf', 'rb') as fin2:
        b2 = fin2.read()

    b2 += add

    with open('new1.pdf', 'wb') as fout1:
        fout1.write(b1)

    with open('new2.pdf', 'wb') as fout2:
        fout2.write(b2)

if __name__ == '__main__':
    main()

あとはこれで出来たファイルを提出すれFLAGゲットできました。 ファイルをいくつも開いたり閉じたりする時、どうすればきれいにかけるんだろ。

これはなぜ解けたのかわかりませんでした。
Logのなかに見えたflagっぽいURLにアクセスしたらflagもらえました。

Thank you for playing!

Thank you for playing!
SECCON{We have done all the challenges. Enjoy last 12 hours. Thank you!}

これは入力するだけでした。

まとめ

  • 去年に引き続き、今年もぼっち参戦でした。
  • わいわいチームでやりたいなとも思いますが、まだ100点問題しか解けないのでちょうどいいかなと思っています。
  • 来年は200点以上の問題も解けたらいいなと思います。