Arab Security Cyber Wargames 2022 Qualifications Writeup

この大会は2022/8/5 22:00(JST)~2022/8/6 22:00(JST)に開催されました。
今回もチームで参戦。結果は700点で733チーム中125位でした。
自分で解けた問題をWriteupとして書いておきます。

Weird Fs (forensics 300)

Autospyで開くと、Flag.zipがあることがわかる。エクスポートして確認すると、パスワードがかかっているので、クラックして展開する。

$ fcrackzip -u -D -p dict/rockyou.txt Flag.zip 


PASSWORD FOUND!!!!: pw == juelma
$ unzip -P juelma Flag.zip
Archive:  Flag.zip
 extracting: Flag.txt
$ cat Flag.txt
ASCWG{M4C_4N6_1$_Co0l}
ASCWG{M4C_4N6_1$_Co0l}

Rsa In The Wild (crypto 100)

RSA暗号。確認してみたところ、JohnとY4mm1のnの公約数、SaraとGaryのnの公約数は1でないため、素因数分解できる。あとは通常通り復号する。

#!/usr/bin/env python3
import json
from Crypto.Util.number import *

with open('output.json', 'r') as f:
    json_data = json.load(f)

users =['John', 'Sara', 'Y4mm1', 'Gary']
ns = []
cs = []
for i in range(4):
    ns.append(json_data[i][users[i]]['key'])
    cs.append(json_data[i][users[i]]['msg'])

assert GCD(ns[0], ns[2]) > 1
assert GCD(ns[1], ns[3]) > 1

e = 0x10001

p0 = GCD(ns[0], ns[2])
p1 = GCD(ns[1], ns[3])
ps = [p0, p1, p0, p1]

for i in range(4):
    q = ns[i] // ps[i]
    assert ps[i] * q == ns[i]
    assert isPrime(ps[i])
    assert isPrime(q)
    phi = (ps[i] - 1) * (q - 1)
    d = inverse(e, phi)
    m = pow(cs[i], d, ns[i])
    assert pow(m, e, ns[i]) == cs[i]
    msg = long_to_bytes(m)
    print(msg)

実行結果は以下の通り。

b'\x0cX\x08\x0b\xc4)\xcd\xcd\x8f<\xb0]\x87\x03\xcd\xf0\x0e\xac\xbd9\x079\x86$\'ej\xdfl\xa2\xf7\xa8)\x15\xe3\xef3\x9e\xd9\x89\xd9&\x99"\x03[\x83\x12\xb8\x0b\xa9WEm\x9a\x80\'\x9bHB\x03\x12\xb6?\xf5$\xec\x10\xdc\xa8P\x8f\x88\x06\xad"\xe6\xe1\xa5\xb0*\xac\xd3\xf4\x9c\x03\xf9\xd1\xc3\xd6[X\xc2\xb4T\xe0<\xbc\x8cF.5?\x11\x14<\xe8\x9dN\xbd9\xc9\xe0\xf9b\xbd\xbc\x05\x0e\xa1\x9b\xc7~\x94\xcb\xd7\xa2\x04'
b"Hello, friend! It's me again. I can cipher things with my mind! ASCWG{7h3_c0mM0n_9re4t_P0W3r_0f_6r0k3N_R$A}"
b'a{\x8c\xcb=\xe8\xe5$z\xb2\x08\xa50fz\xc6\x96\x9e\xc8@RP\x18\x01V\x85N\x80\xa7A\x03\xfa\xbbhxw\xa3\xbc\x9d\x85\xcb\x85{"\xa5\xf8-\xf7\xb8\x96\xbc\xcc\x04\xb0\xfa{u:\xa5h\xc2j\xba\x96\x02\x81\xa4\x10\x0c7p\\\xf2\xbc\xa5u\xc5\xf9r\xac/\xe4U\xe3\xcc\xcb\xb7\xe8\xa3\xedO\x91\x89\x15\x9e\x11G9\xff\xea>\xb3\x94\x11\xc4\x9b\xa4eC\x93\x12\xe5[\x15u\xae5\xbb\xe2&\xca!\xf5\xf2\xa3KM'
b"\x17\xfe&\x9c.\\e\xb6\x91\xdc7\xcf\xf0UA\x10(\x915}4\x05\x1d\xf23\x17\x0co\x1d\xa5\xccO\t\x89\x98\x12\xe4\x06\xaa\xc2B\xbe#v9\xa5[m\x96\x91\xfe\xef\x1f{\xf3\xd8\x06\x9c\x05\x18zW\x01\xda(\xac3\x8f\xa1\x02\x92F\x96\xe0\xf9\x8c+\xb0\xb2\x9be\x0e1\x97\xd6\xec%\xf8\x16\xf6\xf0\xb3Y\xcb\xeb\xc4\xc8\xa4Y\x0bWy\xff\xc4IDw\\\xa7\x9b\xf5P\xb4\xd9\xdaM\xca\xb4\x9b\x8a\x95'\r\x08\xa9\xe1n%"
ASCWG{7h3_c0mM0n_9re4t_P0W3r_0f_6r0k3N_R$A}

Osp (crypto 300)

kをブルートフォースで暗号化数値から引き算し、32~126でブルートフォースで割り切れ、割った数が素数のものを探す。

#!/usr/bin/env python3
from Crypto.Util.number import *

with open('output.txt', 'r') as f:
    cs = f.read().splitlines()

for c in cs:
    for k in range(256):
        v = int(c) - k
        for code in range(32, 127):
            if v % code == 0:
                p = v // code
                if isPrime(p) and p.bit_length() == 256:
                    print(cs.index(c), chr(code))

実行結果は以下の通り。

0 N
0 A★
1 S★
1 t
2 A
2 C★
3 W★
3 D
4 G★
4 ?
5 {★
6 W★
6 D
6 c
7 h★
8 4★
8 /
9 +
9 5
9 B
9 7★
10 _★
10 F
10 N
11 1★
11 @
11 =
12 f★
13 _★
13 F
13 N
14 1★
14 @
14 =
15 +
15 5
15 B
15 7★
15 H
16 '★
17 s★
17 a
18 _★
18 F
18 N
19 N★
20 0★
20 E
21 +
21 5
21 B
21 7★
22 r
22 _★
23 @★
23 \
24 r
24 _★
25 `
25 P★
25 h
26 r★
26 T
26 ^
27 1★
27 @
27 =
28 K
28 M★
28 Y
28 m
29 3★
29 2
30 !★
31 6
31 -★
32 f★
33 0★
33 E
34 f★
35 f★
36 M
36 a★
37 3★
38 6★
38 A
39 D
39 5★
40 7★
40 H
40 *
41 e★
42 }★

候補は複数出るので、フラグとして正しそうな文字を組み合わせる。

ASCWG{Wh47_1f_17's_N07_@_Pr1M3!-f0ffa3657e}