この大会は2021/9/12 17:00(JST)~2021/9/13 17:00(JST)に開催されました。
今回もチームで参戦。結果は1097点で232チーム中29位でした。
自分で解けた問題をWriteupとして書いておきます。
Sanity Check (Misc)
問題にフラグが書いてあった。
COMPFEST13{Welcome_to_CTF_COMPFEST_13}
Promotional Video (Misc)
字幕にフラグが表示されるが早くで読めない。http://video.google.com/timedtext?type=list&v=047T5AZpOiIにアクセスして字幕情報を見る。
<transcript_list docid="15244354765009271330"> <track id="0" name="" lang_code="en" lang_original="English" lang_translated="English" lang_default="true"/> </transcript_list>
http://video.google.com/timedtext?hl=en&lang=en&name=&v=047T5AZpOiIにアクセスする。
<transcript> <text start="0" dur="5">Don't forget to follow our social media and visit our website (link in description)</text> <text start="5" dur="0.001">C</text> <text start="5.502" dur="0.001">O</text> <text start="6.307" dur="0.001">M</text> <text start="6.407" dur="0.001">P</text> <text start="7.507" dur="0.001">F</text> <text start="7.607" dur="0.001">E</text> <text start="7.707" dur="0.001">S</text> <text start="8.807" dur="0.001">T</text> <text start="9.907" dur="0.001">1</text> <text start="10.007" dur="0.001">3</text> <text start="10.107" dur="0.001">{</text> <text start="10.207" dur="0.001">c</text> <text start="10.307" dur="0.001">4</text> <text start="10.407" dur="0.001">p</text> <text start="10.507" dur="0.001">t</text> <text start="11.607" dur="0.001">U</text> <text start="11.707" dur="0.001">r</text> <text start="11.807" dur="0.001">3</text> <text start="11.907" dur="0.001">_</text> <text start="12.007" dur="0.001">T</text> <text start="12.107" dur="0.001">h</text> <text start="12.207" dur="0.001">3</text> <text start="12.307" dur="0.001">_</text> <text start="12.407" dur="0.001">F</text> <text start="12.507" dur="0.001">l</text> <text start="12.607" dur="0.001">4</text> <text start="12.707" dur="0.001">g</text> <text start="12.807" dur="0.001">_</text> <text start="12.907" dur="0.001">c</text> <text start="13.007" dur="0.001">b</text> <text start="13.107" dur="0.001">1</text> <text start="13.207" dur="0.001">2</text> <text start="13.307" dur="0.001">1</text> <text start="13.407" dur="0.001">7</text> <text start="13.507" dur="0.001">b</text> <text start="13.607" dur="0.001">c</text> <text start="13.707" dur="0.001">c</text> <text start="13.807" dur="0.001">d</text> <text start="13.907" dur="0.001">}</text> </transcript>
COMPFEST13{c4ptUr3_Th3_Fl4g_cb1217bccd}
Snab? Yes, Snab (Cryptography)
sはp + qの2乗なので、sの平方根をとれば、p + q (= p_q とする) がわかる。また以下の式より、phiもわかる。
phi = (p - 1) * (q - 1) = n - (p + q) + 1 = n - p_q + 1
さらにGCD(pow(s, 3) - a, b) = rと推測できる。以上により復号する。復号結果は以下の通り。
#Snab says good job! But you're not done yet flag = findme halfa = ''.join([flag[i] for i in range (0, len(flag), 2)]) halfb = ''.join([flag[i] for i in range (1, len(flag), 2)] p = bytes_to_long(bytes(halfa, encoding = 'utf-8')) q = bytes_to_long(bytes(halfb, encoding = 'utf-8')) r = 0 while (not(isPrime(p) and isPrime(q))): p += 1 q += 1 r += 1
p, qの値からそれぞれrだけ引けば、元のp, qがわかりhalfa, halfbを求められる。あとは交互に構成していけば、フラグになる。qを求めるには以下のことを使う。
b = (s - q * (2 * p + q)) * r = (s - 2 * n - q**2) * r ↓ q**2 = s - 2 * n - (b // r)
from Crypto.Util.number import * import gmpy with open('output.txt', 'r') as f: params = f.read().splitlines() e = int(params[0]) s = int(params[1]) n = int(params[2]) a = int(params[3]) b = int(params[4]) c_list = eval(params[5]) p_q = int(gmpy.root(s, 2)[0]) assert pow(p_q, 2) == s phi = n - p_q + 1 d = inverse(e, phi) r = GCD(pow(s, 3) - a, b) m_list = [] for c in c_list: mr = pow(c, d, n) m_list.append(mr // r) for m in m_list: msg = long_to_bytes(m).rstrip() print msg print q = int(gmpy.root(s - 2 * n - (b // r), 2)[0]) p = n // q assert p * q == n p = p - r q = q - r halfa = long_to_bytes(p) halfb = long_to_bytes(q) flag = '' for i in range(len(halfa)): flag += halfa[i] flag += halfb[i] print flag
実行結果は以下の通り。
#Snab says good job! But you're not done yet flag = findme halfa = ''.join([flag[i] for i in range (0, len(flag), 2)]) halfb = ''.join([flag[i] for i in range (1, len(flag), 2)] p = bytes_to_long(bytes(halfa, encoding = 'utf-8')) q = bytes_to_long(bytes(halfb, encoding = 'utf-8')) r = 0 while (not(isPrime(p) and isPrime(q))): p += 1 q += 1 r += 1 Cool! You did it! {y0U_d1DnT_3xpEcT_t0_FinD_pQ_4s_a_fl4g_DiD_y0u_7e1877a801}
COMPFEST13{y0U_d1DnT_3xpEcT_t0_FinD_pQ_4s_a_fl4g_DiD_y0u_7e1877a801}