TMUCTF 2021 Writeup

この大会は2021/9/8 19:30(JST)~2021/9/10 13:30(JST)に開催されました。
今回もチームで参戦。結果は2805点で496チーム中41位でした。
自分で解けた問題をWriteupとして書いておきます。

Welcome (Welcome)

Slackに入り、#generalチャネルのメッセージを見ると、Slackbotがひたすらフラグを送信している。

TMUCTF{W3lc0m3_70_7muc7f_2021_7h15_15_4_U}

Warmup (Welcome)

2つの画像の色が異なる場合は黒、同じ場合は白にして画像にしてみると、フラグが現れた。

from PIL import Image

img1 = Image.open('ciphered_message.png').convert('RGB')
img2 = Image.open('secret.png').convert('RGB')
w, h = img1.size

output_img = Image.new('RGB', (w, h), (255, 255, 255))

for y in range(h):
    for x in range(w):
        r1, g1, b1 = img1.getpixel((x, y))
        r2, g2, b2 = img2.getpixel((x, y))
        if r1 == r2 and g1 == g2 and b1 == b2:
            output_img.putpixel((x, y), (0, 0, 0))
        else:
            output_img.putpixel((x, y), (255, 255, 255))

output_img.save('flag.png')

f:id:satou-y:20210914215528p:plain

TMUCTF{W3_h0p3_y0u_3nj0y_7h15_c0mp371710n_4nd_7h4nk_y0u!}

Warmup (Pwn)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  char local_58 [76];
  int local_c;
  
  setbuf(stdout,(char *)0x0);
  setbuf(stdin,(char *)0x0);
  setbuf(stderr,(char *)0x0);
  tmulogo();
  puts("Welcome to TMUCTF 2021! Let us know your name: ");
  local_c = 0;
  gets(local_58);
  puts("Thanks!\n");
  if (local_c != 0) {
    system("cat flag.txt");
  }
  return 0;
}

BOFで長い文字列を指定すればよい。80バイト入力してみる。

$ nc 194.5.207.56 7000
=================================================================
=     ____ _    _    ____ ____ ____   ____ ____ ____    __      =
=     |_ _\|\/\ || \ | __\|_ _\|  _\  |   \|   ||   \  / |      =
=       || |   \||_|\| \__  || | _\   '-'_/| \ |'-'_/ /_ |      =
=       |/ |/v\/|___/|___/  |/ |/     |___]|___||___]   \|      =
=                                                               =
=================================================================
Welcome to TMUCTF 2021! Let us know your name: 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Thanks!

TMUCTF{n0w_y0u_4r3_w4rm3d_up}
TMUCTF{n0w_y0u_4r3_w4rm3d_up}

UnBIOSed (Reversing)

$ python pyinstxtractor.py Unbiosed.exe
[*] Processing Unbiosed.exe
[*] Pyinstaller version: 2.1+
[*] Python version: 37
[*] Length of package: 18531925 bytes
[*] Found 44 files in CArchive
[*] Beginning extraction...please standby
[!] Warning: The script is running in a different python version than the one used to build the executable
    Run this script in Python37 to prevent extraction errors(if any) during unmarshalling
[!] Unmarshalling FAILED. Cannot extract PYZ-00.pyz. Extracting remaining files.
[*] Successfully extracted pyinstaller archive: Unbiosed.exe

You can now use a python decompiler on the pyc files within the extracted directory

Unbiosed.exe_extracted\Unbiosedを編集し、ヘッダを付けpycにする。ヘッダは以下を16バイト付けた。

3e 0d 0d 0a 00 00 00 00 00 00 00 00 00 00 00 00

pycをデコンパイルする。

$ uncompyle6 Unbiosed.pyc 
# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3390)
# Decompiled from: Python 3.6.9 (default, Jan 26 2021, 15:33:00) 
# [GCC 8.4.0]
# Embedded file name: Unbiosed.py
import numpy as np, random
a = np.empty([10, 10])
b = np.empty([10, 10])
c = np.dot(a, b)
if random.uniform(0, 5) <= 2:
    print('The Bios is Corrupted!')
    exit()
d = input('Please Enter the Recovery Key:')
e = list(d)
g = 0
h = [84, 77, 85, 67, 84, 70, 123, 77, 52, 121, 95, 52, 108, 108, 95, 89, 48, 117, 114, 95, 68, 51, 99, 49, 53, 49, 48, 110, 53, 95, 98, 51, 95, 85, 110, 98, 49, 48, 53, 51, 100, 33, 125]
for f in range(len(h)):
    if ord(e[f]) != h[f]:
        g = g + 1

if g > 0:
    print('Your Bios Data Cannot be Recovered with This Key.')
    exit()
print("Congratulations! You Have The Flag, But I'll Print it Out Again For You:")
print(d)
# okay decompiling Unbiosed.pyc

hのコードを文字にすればよい。

h = [84, 77, 85, 67, 84, 70, 123, 77, 52, 121, 95, 52, 108, 108, 95, 89, 48, 117, 114, 95, 68, 51, 99, 49, 53, 49, 48, 110, 53, 95, 98, 51, 95, 85, 110, 98, 49, 48, 53, 51, 100, 33, 125]
flag = ''.join([chr(c) for c in h])
print flag
TMUCTF{M4y_4ll_Y0ur_D3c1510n5_b3_Unb1053d!}

Login (Web)

http://185.235.41.189/robots.txtにアクセスすると、コードが書かれている。

if (isset($_GET["password"])) {
    if (hash("md5", $_GET["password"]) == $_GET["password"]) {
        echo "<h1>Here is the flag:</h1>" . $flag;
    } else {
        echo "Try harder!";
    }
}

md5が0e[数字]になる0eから始まる文字列を指定すればよい。調べると例えば0e215962017が該当するらしいので、入力するとフラグが表示された。

TMUCTF{D0_y0u_kn0w_7h3_d1ff3r3nc3_b37w33n_L0053_c0mp4r150n_4nd_57r1c7_c0mp4r150n_1n_PHP!?}

Tri (Crypto)

問題の暗号は以下の通り。

kqiaprcvsbmwynzjghxudftleo+
dk+hjpegrhomfgjozzshxqcojnkcozsrfgbnjviubevbuxrrpzdfkjmd+vrwiegqh+ocydjoinlpehrgdnjcvbdacsodjelhvxjmsfzqedvfdbulsoxctne+cagjiovlwlphergkw

いろいろ調べてみたら、Trifid cipherというのがある。https://cryptii.com/pipes/trifid-cipherでデコードしてみる。GROUP SIZEが3の時に以下のように復号できる。

didyouforgetthatthreeismyfavoritenumberlibrxmxpsryhuwkhihqfhvsurshuoblsurplvhwrjlyhbrxwkhiodjolsvdbwvjwwfdvflkudhodvqhhwqlqwdvvfhuzlulvkr
        ↓
did you forget that three is my favorite number librxmxpsryhuwkhihqfhvsurshuoblsurplvhwrjlyhbrxwkhiodjolsvdbwvjwwfdvflkudhodvqhhwqlqwdvvfhuzlulvkr

以下の部分をシーザー暗号としてシフトする。

librxmxpsryhuwkhihqfhvsurshuoblsurplvhwrjlyhbrxwkhiodjolsvdbwvjwwfdvflkudhodvqhhwqlqwdvvfhuzlulvkr

https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号する。

Rotation 3:
ifyoujumpoverthefencesproperlyipromisetogiveyoutheflaglipsaytsgttcascihraelasneetnintasscerwirisho
        ↓
if you jump over the fences properly i promise to give you the flag lipsaytsgttcascihraelasneetnintasscerwirisho

今度はRail Fence Cipherっぽい。https://www.geocachingtoolbox.com/index.php?lang=en&page=railFenceCipherで復号する。
レール数:3、オフセット:3で復号できた。

classicciphersarealwaysinterestingisntthatso
TMUCTF{classicciphersarealwaysinterestingisntthatso}

Common Factor (Crypto)

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

・e = 65537
・primes: 5個の2048bit素数
・n: primesの要素の積
・nを出力
・x1 = primes[1] ** 2
・x2 = primes[2] ** 2
・x3 = primes[1] * primes[2]
・y1 = x1 * primes[2] + x2 * primes[1]
・y2 = x2 * (primes[3] + 1) - 1
・y3 = x3 * (primes[3] + 1) - 1
・x2 + x3 + y1を出力
・y2 + y3を出力
・pow(flag, e, n)を出力

式を変形してみる。

x2 + x3 + y1 = primes[2] ** 2 + primes[1] * primes[2]
               + primes[1] ** 2 * primes[2] + primes[2] ** 2 * primes[1]
             = primes[2] ** 2 * (primes[1] + 1) + primes[1] * primes[2] * (primes[1] + 1)
             = primes[2] * (primes[1] + primes[2]) * (primes[1] + 1)
y2 + y3 = x2 * (primes[3] + 1) - 1 + x3 * (primes[3] + 1) - 1
        = primes[2] ** 2 * (primes[3] + 1) + primes[1] * primes[2] * (primes[3] + 1) - 2
        = primes[2] * (primes[1] + primes[2]) * (primes[3] + 1) - 2

y2 + y3 + 2 と n のGCDはprimes[2]。次に1つ目の式からprimes[1]がわかる。さらに2つ目の式からprimes[3]がわかる。

pow(flag, e, n) = c
→pow(flag, e, primes[1]*primes[2]*primes[3]) = c % primes[1]*primes[2]*primes[3]

modulusをprimes[1]*primes[2]*primes[3]にして、復号する。

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

e = 65537

with open('output.txt', 'r') as f:
    n = int(f.readline().rstrip())
    k1 = int(f.readline().rstrip())
    k2 = int(f.readline().rstrip())
    c = int(f.readline().rstrip())

p2 = GCD(k1, n)

p1 = symbols('p1')
eq = Eq(p2 * (p1 + p2) * (p1 + 1), k1)
ps = solve(eq)
for p in ps:
    if p > 0:
        p1 = p
        break

p3 = symbols('p3')
eq = Eq(p2 * (p1 + p2) * (p3 + 1) - 2, k2)
ps = solve(eq)
p3 = ps[0]

phi = (p1 - 1) * (p2 - 1) * (p3 - 1)
d = inverse(e, phi)
m = pow(c % (p1 * p2 * p3), d, (p1 * p2 * p3))
flag = long_to_bytes(m)
print flag
TMUCTF{Y35!!!__M4Y_N0t_4lW4y5_N33d_4ll_p21M3_f4c70R5}

435! (Crypto)

keyと暗号の一部がマスクされている。ブロックごとに考える。

平文
CBC (Cipher Bloc
ker Chaining) is
 an advanced for
m of block ciphe
r encryptionHHHH
HHHHHHPPPPPPPPPP

暗号
9**********b4381646*****01******
**************8b9***0485********
**********************0**ab3a*cc
5e**********18a********5383e7f**
************1b3*******9f43fd6634
1f3ef3fab2bbfc838b9ef71867c3bcbb

暗号の最後のブロックとパディングがわかっているので、条件を満たすkeyをブルートフォースで求める。あとは後ろのブロックから順に復号していき、ivを求める。これがフラグになる。

#!/usr/bin/python3
import itertools
import binascii
import hashlib
from Crypto.Cipher import AES
from Crypto.Util.strxor import strxor

def pad(message):
    padding = bytes((key_len - len(message) % key_len) * chr(key_len - len(message) % key_len), encoding='utf-8')
    return message + padding

chars = ''
for code in range(32, 127):
    chars += chr(code)

ct5 = binascii.unhexlify('1f3ef3fab2bbfc838b9ef71867c3bcbb')
ct4_tail = binascii.unhexlify('9f43fd6634')

for c in itertools.product(chars, repeat=3):
    key = (c[0] + 'XhN2' + c[1] +'8d%8Slp3' + c[2] + 'v').encode()
    key_len = len(key)
    h = hashlib.sha256(key).hexdigest()
    hidden = binascii.unhexlify(h)[:10]
    message = b'CBC (Cipher Blocker Chaining) is an advanced form of block cipher encryption' + hidden
    pt5 = pad(message)[-16:]
    aes = AES.new(key, AES.MODE_ECB)
    pt = aes.decrypt(ct5)
    if strxor(pt[-5:], b'\x0a' * 5) == ct4_tail:
        break

print('[+] key =', key)

h = hashlib.sha256(key).hexdigest()
hidden = binascii.unhexlify(h)[:10]
message = b'CBC (Cipher Blocker Chaining) is an advanced form of block cipher encryption' + hidden
message = pad(message)
pts = [message[i:i+16] for i in range(0, len(message), 16)]

ct = ct5
for i in range(5, -1, -1):
    aes = AES.new(key, AES.MODE_ECB)
    pt = aes.decrypt(ct)
    ct = strxor(pt, pts[i])
    print('[+] ct_part =', binascii.hexlify(ct))

flag = 'TMUCTF{%s}' % ct.decode()
print('[*] flag =', flag)

実行結果は以下の通り。

[+] key = b'0XhN2!8d%8Slp3Ov'
[+] ct_part = b'9c1a9d16795c1b334d6ec49f43fd6634'
[+] ct_part = b'5e5969dcdb9b18ac33993785383e7f32'
[+] ct_part = b'959349e93481869c836d900dcab3a6cc'
[+] ct_part = b'8bc67a00c0e5198b9d0304858953eb83'
[+] ct_part = b'9f4ac903118b43816462b35101a7b6fe'
[+] ct_part = b'5930555f4433437259503733445f3137'
[*] flag = TMUCTF{Y0U_D3CrYP73D_17}
TMUCTF{Y0U_D3CrYP73D_17}

Strangely (Crypto)

https://wiremask.eu/tools/xor-cracker/でクラックする。key「f3 d9 01 ae 93 bb 25」でrarファイルにようになったが、keyの7バイト目がことなるようなので、調整する。

with open('file', 'rb') as f:
    enc = f.read()

rar_head = 'Rar!\x1a\x07\x00'

key = []
for i in range(len(rar_head)):
    key.append(ord(enc[i]) ^ ord(rar_head[i]))

dec = ''
for i in range(len(enc)):
    dec += chr(ord(enc[i]) ^ key[i%len(key)])

with open('flag.rar', 'wb') as f:
    f.write(dec)

rarファイルの情報を見る。

$ 7z l -slt flag.rar

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=ja_JP.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz (A0655),ASM,AES-NI)

Scanning the drive for archives:
1 file, 1559 bytes (2 KiB)

Listing archive: flag.rar

--
Path = flag.rar
Type = Rar
Physical Size = 1559
Solid = -
Blocks = 23
Multivolume = -
Volumes = 1

----------
Path = 5.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:29:40
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = D4F15C54
Host OS = Win32
Method = m3:17
Version = 29

Path = 6.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:29:51
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 6224C494
Host OS = Win32
Method = m3:17
Version = 29

Path = 7.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:30:03
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = B79C496B
Host OS = Win32
Method = m3:17
Version = 29

Path = 8.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:30:17
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 0DEB7416
Host OS = Win32
Method = m3:17
Version = 29

Path = 9.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:30:31
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = B1441D53
Host OS = Win32
Method = m3:17
Version = 29

Path = 10.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:30:41
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = A55CEB27
Host OS = Win32
Method = m3:17
Version = 29

Path = 11.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:30:56
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 05C3ACC9
Host OS = Win32
Method = m3:17
Version = 29

Path = 12.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:31:09
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 3DA99B67
Host OS = Win32
Method = m3:17
Version = 29

Path = 13.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:31:21
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 3F4D936A
Host OS = Win32
Method = m3:17
Version = 29

Path = 14.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:31:35
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 138AA87B
Host OS = Win32
Method = m3:17
Version = 29

Path = 15.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:31:45
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = A538E0A1
Host OS = Win32
Method = m3:17
Version = 29

Path = 16.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:31:55
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = B9DF8C6B
Host OS = Win32
Method = m3:17
Version = 29

Path = 17.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:32:05
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 01CE8D5D
Host OS = Win32
Method = m3:17
Version = 29

Path = 18.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:32:16
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 814B8BED
Host OS = Win32
Method = m3:17
Version = 29

Path = 19.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:32:28
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 717F3F79
Host OS = Win32
Method = m3:17
Version = 29

Path = 20.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:32:40
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 5C011BC9
Host OS = Win32
Method = m3:17
Version = 29

Path = 21.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:32:50
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = A48DBAA5
Host OS = Win32
Method = m3:17
Version = 29

Path = 22.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-20 10:20:48
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = E64AF817
Host OS = Win32
Method = m3:17
Version = 29

Path = 23.txt
Folder = -
Size = 1
Packed Size = 16
Modified = 2021-01-20 10:20:59
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = FCB6E20C
Host OS = Win32
Method = m3:17
Version = 29

Path = 1.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:28:43
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 3570E041
Host OS = Win32
Method = m3:17
Version = 29

Path = 2.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:28:57
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 654AB3A9
Host OS = Win32
Method = m3:17
Version = 29

Path = 3.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:29:09
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 5B22215B
Host OS = Win32
Method = m3:17
Version = 29

Path = 4.txt
Folder = -
Size = 4
Packed Size = 16
Modified = 2021-01-19 13:29:27
Created = 
Accessed = 
Attributes = A
Encrypted = +
Solid = -
Commented = -
Split Before = -
Split After = -
CRC = 0E0D89E9
Host OS = Win32
Method = m3:17
Version = 29

1.txt~22.txtまでのsizeは4、23.txtのsizeは1なので、総当たりでCRCが一致する文字列を見つける。

import binascii
import itertools

crcs = [0x3570E041, 0x654AB3A9, 0x5B22215B, 0x0E0D89E9, 0xD4F15C54, 0x6224C494,
    0xB79C496B, 0x0DEB7416, 0xB1441D53, 0xA55CEB27, 0x05C3ACC9, 0x3DA99B67,
    0x3F4D936A, 0x138AA87B, 0xA538E0A1, 0xB9DF8C6B, 0x01CE8D5D, 0x814B8BED,
    0x717F3F79, 0x5C011BC9, 0xA48DBAA5, 0xE64AF817, 0xFCB6E20C]

chars = ''
for c in range(32, 127):
    chars += chr(c)

flag = ''
for i in range(len(crcs)):
    found = False
    if i == 22:
        r = 1
    else:
        r = 4
    for c in itertools.product(chars, repeat=r):
        text = ''.join(c)
        if (binascii.crc32(text) & 0xffffffff) == crcs[i]:
            found = True
            flag += text
            print '[+] flag =', flag
            break
    if found == False:
        print 'Error'
        break

print '[*] flag =', flag

実行結果は以下の通り。

[+] flag = TMUC
[+] flag = TMUCTF{7
[+] flag = TMUCTF{7h3r3
[+] flag = TMUCTF{7h3r3_w45
[+] flag = TMUCTF{7h3r3_w45_n0_
[+] flag = TMUCTF{7h3r3_w45_n0_n33d
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru7
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju57_h
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju57_h4v3_
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju57_h4v3_70_c
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju57_h4v3_70_c4lcu
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju57_h4v3_70_c4lcul473
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju57_h4v3_70_c4lcul473_cRc
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju57_h4v3_70_c4lcul473_cRc5_:)
[+] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju57_h4v3_70_c4lcul473_cRc5_:)}
[*] flag = TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju57_h4v3_70_c4lcul473_cRc5_:)}
TMUCTF{7h3r3_w45_n0_n33d_70_bru73_f0rc3_7h3_P455W0rD!_Y0u_ju57_h4v3_70_c4lcul473_cRc5_:)}

Broken RSA (Crypto)

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

・pads = [b'\x04', b'\x02', b'\x00', b'\x01', b'\x03']
・i, j: 0~4の組み合わせ
 ・pads[0] + b'TMUCTF' + pads[4]
 ・pads[1] + b'TMUCTF' + pads[3]
 ・pads[2] + b'TMUCTF' + pads[2]
 ・pads[3] + b'TMUCTF' + pads[1]
 ・pads[4] + b'TMUCTF' + pads[0]
 ・pads[0] * 2 + b'TMUCTF' + pads[4] * 2
 ・pads[1] * 2 + b'TMUCTF' + pads[3] * 2
 ・pads[2] * 2 + b'TMUCTF' + pads[2] * 2
 ・pads[3] * 2 + b'TMUCTF' + pads[1] * 2
 ・pads[4] * 2 + b'TMUCTF' + pads[0] * 2
     :
 ・それぞれのpow(bytes_to_long(msg), e, n)を出力
・最後にpow(bytes_to_long(secret_msg), e, n)を出力

以下を比べてみる。

・pads[2] + b'TMUCTF' + pads[2]
 = b'TMUCTF\x00'
・pads[2] * 2 + b'TMUCTF' + pads[2] * 2
 = b'TMUCTF\x00\x00'
・pads[2] * 3 + b'TMUCTF' + pads[2] * 3
 = b'TMUCTF\x00\x00\x00'

1つ目の数の256倍が2つ目の数になり、2つ目の数の256倍が3つ目の数になる。このことから暗号化データは以下のようになることを使って、nを導き出す。

(A * 256**e) % n = B
(B * 256**e) % n = C

(A * 256**e - B) と (B * 256**256 - C)のGCDがnと考えられる。算出すると、nは以下の値になる。

n = 178687641710030174725391391875667596365020728306319047485522635263856928788792264392747544630866502200298051103123255099970617381333101830066744705357923051686594736448334538740566230676008114657220351133399973716405404704654132288956810705849964560317000445171090246556869619036945752872429931964062189095563138744809626920021187533539499744999940892826446388022339663656502481337983590571794320931540723276842297611798866462197198435976264905955663723006770230633947206618763194442570290448812114549218867835561537767658934219897738952522114759281325723662384407818238388836452701782722266368637081847540663426878964206423537416368928558513511910356279139696064536450514293833309698627046383863195702404780871841847505106126552260648896877439999464328457911073105705457119731432752925110957852530172829266128412160058897537830972644942192992462097998221061279622581673295977766215387020119500286919736797464640883769066399346357647673531235429835830770457120931424234362943301312350110319595495619381

これを素因数分解する。

$ python -m primefac 178687641710030174725391391875667596365020728306319047485522635263856928788792264392747544630866502200298051103123255099970617381333101830066744705357923051686594736448334538740566230676008114657220351133399973716405404704654132288956810705849964560317000445171090246556869619036945752872429931964062189095563138744809626920021187533539499744999940892826446388022339663656502481337983590571794320931540723276842297611798866462197198435976264905955663723006770230633947206618763194442570290448812114549218867835561537767658934219897738952522114759281325723662384407818238388836452701782722266368637081847540663426878964206423537416368928558513511910356279139696064536450514293833309698627046383863195702404780871841847505106126552260648896877439999464328457911073105705457119731432752925110957852530172829266128412160058897537830972644942192992462097998221061279622581673295977766215387020119500286919736797464640883769066399346357647673531235429835830770457120931424234362943301312350110319595495619381
178687641710030174725391391875667596365020728306319047485522635263856928788792264392747544630866502200298051103123255099970617381333101830066744705357923051686594736448334538740566230676008114657220351133399973716405404704654132288956810705849964560317000445171090246556869619036945752872429931964062189095563138744809626920021187533539499744999940892826446388022339663656502481337983590571794320931540723276842297611798866462197198435976264905955663723006770230633947206618763194442570290448812114549218867835561537767658934219897738952522114759281325723662384407818238388836452701782722266368637081847540663426878964206423537416368928558513511910356279139696064536450514293833309698627046383863195702404780871841847505106126552260648896877439999464328457911073105705457119731432752925110957852530172829266128412160058897537830972644942192992462097998221061279622581673295977766215387020119500286919736797464640883769066399346357647673531235429835830770457120931424234362943301312350110319595495619381: 10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087 17168409475383972628504778240855911978985929543286350892069246008372473042523567037011013249871547777584631416739758322856251015798698301831765580955300650407835153601378654173742292554894502681735405620391535895647045866153891745460976487617315465562496499358894287054034024692381191210822762212034588017308516989613261306910988892855362427544142343518767108593353834256519607664876369541892324877459094093260657539475432861721224124049660249386714464357030183841589410520002623236416489710292432265593266725745973870777993186048812530526551997744644388584507538634448903227467825441758880828727826547230875410498763

素因数分解できたので、それを使ってsecret_msgを復号する。

from Crypto.Util.number import *

e = 65537

with open('output.txt', 'r') as f:
    encs = map(int, f.read().split('\n'))

diff = []
for i in range(4):
    diff.append(encs[i*5+2] * 256**e - encs[(i+1)*5+2])

n = diff[0]
for i in range(1, 4):
    n = GCD(n, diff[i])

p = 10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087
q = 17168409475383972628504778240855911978985929543286350892069246008372473042523567037011013249871547777584631416739758322856251015798698301831765580955300650407835153601378654173742292554894502681735405620391535895647045866153891745460976487617315465562496499358894287054034024692381191210822762212034588017308516989613261306910988892855362427544142343518767108593353834256519607664876369541892324877459094093260657539475432861721224124049660249386714464357030183841589410520002623236416489710292432265593266725745973870777993186048812530526551997744644388584507538634448903227467825441758880828727826547230875410498763
assert n == p * q

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(encs[25], d, n)
flag = long_to_bytes(m)
print flag

復号結果は以下の通り。

Public key cryptography. RSA was first publicly described in 1977 by Ron Rivest, Adi Shamir and Leonard Adleman of the Massachusetts Institute of Technology. TMUCTF{Ju57_4n07h3r_R54_ch4ll3n63!_C0u1d_y0u_50lv3_17?!?}
TMUCTF{Ju57_4n07h3r_R54_ch4ll3n63!_C0u1d_y0u_50lv3_17?!?}