seccon beginners ctf4b 2020 writeup

成績

P01TERGEIST 1479ポイントで65位でした 5問しか解いてないですが、久々にCTFしたので記録を残します。

Writeup

Spy

ソースを見ると/と/challengeにアクセスできる。 存在するアカウントを選択すればいいので、提供されているemployees.txtを一つずつ 入力してアクセス速度が違うものを選択する。

R&B

先頭の文字を見てrot13とbase64のデコードを繰り返すだけ

emoemoencode

絵文字のunicodeを調べて後ろから2桁の数字を見るとフラグのasciiコード ぽかったのでchr()で変換するだけ

yakisoba

入力によってCorrectとWrongになる問題はとりあえずangrにかけてみることにしている。 以下のコードで普通に通った。

import angr

project = angr.Project('./yakisoba', load_options={'auto_load_libs':False})
simgr = project.factory.simgr()
simgr.explore(find=lambda s: b'Correct!' in s.posix.dumps(1), avoid=lambda s: b'Wrong!' in s.posix.dumps(1))

try:
    found = simgr.found[0]
    print(found.posix.dumps(0))
except IndexError:
    print("Not found")

Noisy equations

coeffsが44個の数字のリストが44個集まったリスト。 これに乱数のノイズを乗せて長さ44のflagをかけ合わせたanswersがある。

coeffsをA, answersをBという行列で表すとB = AF(Fはflagを表す44x1の行列)になる。 よってAの逆行列を求めてFを計算した。 四捨五入を行うときにすっかり忘れていたpython3のround()の仕様に少し迷った。

import numpy as np

# coeffsとansersの取得は省略

A = np.array(coeffs,dtype='float64')
B = np.array(answers,dtype='float64')
inv_A = np.linalg.inv(A)
F = np.dot(inv_A, B)

f = F.tolist()
print(f)
round = lambda x:int((x*2+1)/2)

for s in f:
    num = int(round(s))
    print(chr(num), end="")

しかしこのコードだと

 cuf4b{q4nd0m_534d`24^n4c2554rz^f0s]53cvr16y}

のように完全なフラグではないのでguessする。 「random_seed_is_necessary_for_security」 を思いつくまで30分くらいかかった