読者です 読者をやめる 読者になる 読者になる

AlexCTF Writeup

CTF writeup

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

CR1: Ultracoded (Cryotography 50)

ONE, ZEROのスペース区切りの文字列。0,1に置き換え、2進数のASCIIコードとして文字に変換する。さらにBase64文字列になるので、デコードする。

with open('zero_one', 'r') as f:
    data = f.read()

data = data.replace('\n', '').split(' ')

b_data = ''
for i in range(len(data)):
    if data[i] == 'ZERO':
        b_data += '0'
    else:
        b_data += '1'

b64_data = ''
for i in range(0, len(b_data), 8):
    code = int(b_data[i:i+8], 2)
    b64_data += chr(code)

print b64_data.decode('base64')

すると、モールス信号が出てきた。

.- .-.. . -..- -.-. - ..-. - .... .---- ..... --- .---- ... --- ..... ..- .--. ...-- .-. --- ..... . -.-. .-. ...-- - --- - -..- -

Onlineツールで復号する。

ALEXCTFTH15O1SO5UP3RO5ECR3TOTXT

"O"を"_"に変換する。

ALEXCTFTH15_1S_5UP3R_5ECR3T_TXT

{ }を付ける。

ALEXCTF{TH15_1S_5UP3R_5ECR3T_TXT}

CR3: What is this encryption (Cryotography 150)

eが非常に大きいRSA暗号の復号問題。Wiener's Attackの一部を流用し、復号する。

def egcd(a, b):
    x,y, u,v = 0,1, 1,0
    while a != 0:
        q, r = b//a, b%a
        m, n = x-u*q, y-v*q
        b,a, x,y, u,v = a,r, u,v, m,n
        gcd = b
    return gcd, x, y

def decrypt(p, q, e, c):
    n = p * q
    phi = (p - 1) * (q - 1)
    gcd, a, b = egcd(e, phi)
    d = a
    pt = pow(c, d, n)
    return hex(pt)[2:-1].decode('hex')

p = 0xa6055ec186de51800ddd6fcbf0192384ff42d707a55f57af4fcfb0d1dc7bd97055e8275cd4b78ec63c5d592f567c66393a061324aa2e6a8d8fc2a910cbee1ed9
q = 0xfa0f9463ea0a93b929c099320d31c277e0b0dbc65b189ed76124f5a1218f5d91fd0102a4c8de11f28be5e4d0ae91ab319f4537e97ed74bc663e972a4a9119307
e = 0x6d1fdab4ce3217b3fc32c9ed480a31d067fd57d93a9ab52b472dc393ab7852fbcb11abbebfd6aaae8032db1316dc22d3f7c3d631e24df13ef23d3b381a1c3e04abcc745d402ee3a031ac2718fae63b240837b4f657f29ca4702da9af22a3a019d68904a969ddb01bcf941df70af042f4fae5cbeb9c2151b324f387e525094c41
c = 0x7fe1a4f743675d1987d25d38111fae0f78bbea6852cba5beda47db76d119a3efe24cb04b9449f53becd43b0b46e269826a983f832abb53b7a7e24a43ad15378344ed5c20f51e268186d24c76050c1e73647523bd5f91d9b6ad3e86bbf9126588b1dee21e6997372e36c3e74284734748891829665086e0dc523ed23c386bb520

plaintext = decrypt(p, q, e, c)
print plaintext
ALEXCTF{RS4_I5_E55ENT1AL_T0_D0_BY_H4ND}

CR4: Poor RSA (Cryotography 200)

公開鍵と暗号化データをBASE64エンコードしたファイルが与えられている。
flag.b64をBASE64デコードしたファイルをflag.encとする。
公開鍵の内容を見てみる。

$ openssl rsa -pubin -text < key.pub
Public-Key: (399 bit)
Modulus:
    52:a9:9e:24:9e:e7:cf:3c:0c:bf:96:3a:00:96:61:
    77:2b:c9:cd:f6:e1:e3:fb:fc:6e:44:a0:7a:5e:0f:
    89:44:57:a9:f8:1c:3a:e1:32:ac:56:83:d3:5b:28:
    ba:5c:32:42:43
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
ME0wDQYJKoZIhvcNAQEBBQADPAAwOQIyUqmeJJ7nzzwMv5Y6AJZhdyvJzfbh4/v8
bkSgel4PiURXqfgcOuEyrFaD01soulwyQkMCAwEAAQ==
-----END PUBLIC KEY-----

次のnの値をfactordbで素因数分解する。

n = 0x52a99e249ee7cf3c0cbf963a009661772bc9cdf6e1e3fbfc6e44a07a5e0f894457a9f81c3ae132ac5683d35b28ba5c324243
(= 833810193564967701912362955539789451139872863794534923259743419423089229206473091408403560311191545764221310666338878019)

この結果は以下のp, qの値となる。

p = 863653476616376575308866344984576466644942572246900013156919
q = 965445304326998194798282228842484732438457170595999523426901

この結果から秘密鍵を作成する。

$ rsatool.py -f PEM -o key.pri -p 863653476616376575308866344984576466644942572246900013156919 -q 965445304326998194798282228842484732438457170595999523426901
Using (p, q) to initialise RSA instance

n =
52a99e249ee7cf3c0cbf963a009661772bc9cdf6e1e3fbfc6e44a07a5e0f894457a9f81c3ae132ac
5683d35b28ba5c324243

e = 65537 (0x10001)

d =
33ad09ca06f50f9e90b1acae71f390d6b92f1d6d3b6614ff871181c4df08da4c5f5012457a643094
05eaecd6341e43027931

p =
899683060c76b9c0de581a69e0ea9d91bed1071beb1d924a37

q =
99cde74aedee87adffdd684cbc478e759870b4f20692f65255

Saving PEM as key.pri

秘密鍵を使って、暗号データを復号する。

$ openssl rsautl -decrypt -inkey key.pri < flag.enc
ALEXCTF{SMALL_PRIMES_ARE_BAD}
ALEXCTF{SMALL_PRIMES_ARE_BAD}

SC1: Math bot (Scripting 100)

計算問題を解いていくだけ。

#!/usr/bin/env python
import socket
import re

pattern = 'Question  (.+) :\n(.+)'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('195.154.53.62', 1337))

for i in range(1000):
    data = s.recv(1024)
    print data
    m = re.search(pattern, data)
    formula = m.group(2)
    formula = formula.replace('=', '')
    ans = str(eval(formula)) + '\n'
    print ans
    s.sendall(ans)

data = s.recv(1024)
print data

500回正解すると、フラグが表示された。

ALEXCTF{1_4M_l33t_b0t}

SC2: Cutie cat (Scripting 150)

画像のステガノグラフィの問題。いろいろ試したみたが、なかなかうまくいかなかった。PythonのSteganographyライブラリを使ったら、簡単にフラグを抽出できた。

from steganography.steganography import Steganography

secret_text = Steganography.decode('cat_with_secrets.png')
print secret_text
ALEXCTF{CATS_HIDE_SECRETS_DONT_THEY}

TR1: Hello there (Trivia 10)

freenodeで#alexctfに入る。

    :
19:14 *topic : Alexandria University student held capture the flag event ctf.oddcoder.com ALEXCTF{W3_w15h_y0u_g00d_luck}
ALEXCTF{W3_w15h_y0u_g00d_luck}

TR3: CA (Trivia 20)

AlexctfのHTTPS証明書の発行CAを答える問題。
証明書の発行者を見る。
f:id:satou-y:20170214194426p:plain

letsencrypt