yoshikingのがんばる日記

あたまよくないけどがんばります

CyBRICS CTF Quals 2019 Writeup

CyBRICS CTFが7月20~21日に開催されていたので、zer0ptsとして参加しました. 結果は69位で、解いた問題は3つでした.

チームメンバーのWriteup

st98: CyBRICS CTF Quals 2019 の write-up - st98 の日記帳

ptr-yudai: CyBRICS CTF 2019 Writeup - CTFするぞ

[Rev 10pts] Oldman Reverse

以下のアセンブリファイルが渡されます.

.MCALL  .TTYOUT,.EXIT
START:
    mov   #MSG r1 
    mov #0d r2
    mov #32d r3
loop:       
    mov   #MSG r1 
    add r2 r1
    movb    (r1) r0
    .TTYOUT
    sub #1d r3
    cmp #0 r3
    beq     DONE
    add #33d r2
    swab r2
    clrb r2
    swab r2    
    br      loop      
DONE: 
    .EXIT

MSG:
    .ascii "cp33AI9~p78f8h1UcspOtKMQbxSKdq~^0yANxbnN)d}k&6eUNr66UK7Hsk_uFSb5#9b&PjV5_8phe7C#CLc#<QSr0sb6{%NC8G|ra!YJyaG_~RfV3sw_&SW~}((_1>rh0dMzi><i6)wPgxiCzJJVd8CsGkT^p>_KXGxv1cIs1q(QwpnONOU9PtP35JJ5<hlsThB{uCs4knEJxGgzpI&u)1d{4<098KpXrLko{Tn{gY<|EjH_ez{z)j)_3t(|13Y}"
.end START

r3はループ回数に使われてそうで、r1, r2はMSGをごちゃごちゃしてるな~という認識です. 33をr2に足しているので、1文字目、34文字目、67文字目、....とMSGを参照してそうです. あとは、文字列の長さを伸ばしてあげて、pythonでやってあげます.

>>> msg = "cp33AI9~p78f8h1UcspOtKMQbxSKdq~^0yANxbnN)d}k&6eUNr66UK7Hsk_uFSb5#9b&PjV5_8phe7C#CLc#<QSr0sb6{%NC8G|ra!YJyaG_~RfV3sw_&SW~}((_1>rh0dMzi><i6)wPgxiCzJJVd8CsGkT^p>_KXGxv1cIs1q(QwpnONOU9PtP35JJ5<hlsThB{uCs4knEJxGgzpI&u)1d{4<098KpXrLko{Tn{gY<|EjH_ez{z)j)_3t(|13Y}"
>>> (msg*5)[::33]
'cybrics{pdp_gpg_crc_dtd_bkb_php}09|z1Cn'

フラグはcybrics{pdp_gpg_crc_dtd_bkb_php}でした.

[Cyber 10pts] Zakukozh

This image containing flag is encrypted with affine cipher. Scrape it

イメージファイルがアフィン暗号で暗号化されているみたいです. 軽くアフィン暗号について説明すると、


Enc(x) = (ax + b) \bmod{p}

\begin{eqnarray}
Dec(x) &=& a^{-1}(x - b) \bmod{p}
\end{eqnarray}

のような、暗号化、復号が行われます.a, b, pがパラメータとなり、これを見つけると復号できます. アフィン暗号は既知の平文があると、そこからパラメータを推測できるので、イメージファイルのマジックナンバーから推測します. イメージファイルといっても、いくつかあるのですが、暗号化データを見る感じではpngっぽいです.

マジックナンバーに0x00の部分があるので、そこを見るとbが0x59であることがわかります. また、暗号化データの最大値からpも推測でき、pが256であることがわかります. 残るパラメータはaのみです. aはbとqがわかっているので、適当に小さめな値から求めることができます. ここでは、マジックナンバーの0x0aに注目したとすると、暗号化データでは0xefになっていました. そのため、


\begin{eqnarray}
239 &=& (10a + 89) \bmod{256} \\
150 &=& 10a \\
a &=& 15
\end{eqnarray}

となり、aがわかります(modは超えていないだろうという推測で無視しています...). あとは、復号するだけです.

from Crypto.Util.number import inverse

with open("./zakukozh.bin", "rb") as f:
    data = f.read()

a = 15
b = 89
q = 256
inv_a = inverse(a, q)

m = bytearray([])
for c in data:
    m.append(inv_a * (c - b) % q)

with open('./flag.png', 'wb') as f:
    f.write(m)

flag.pngを表示すると、フラグが書いてました. cybrics{W311_C0M3_2_CY13R1C5}

[Forensic 10pts] Tone

youtubeに電話を掛けるときのボタン音が投稿されていました. はじめは、気合で読もうとしたのですが、4,7が低音、2,5,8が中音、3,6,9が高音までしか分からなくて、細かい音の違いが分からなくて泣いていました. そこで、ptr-yudaiがスペクトル解析をしてくれました. スペクトル解析すると、おおよそ正しい数字がわかるので、あとは文字にあてはめます(おおよそなので単語になってなさそうなところをエスパー).

cybrics{secrettonalflag}

録音して波形を見る、という考えになる前に泣いてしまったのが負け

さいごに

はやく夏休みなんねーかな