KnightCTF 2023 Writeup

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

KnightCTF Discord Server (Basics 25)

Discordに入り、#announcementsチャネルのメッセージを見ると、以下のように書いてある。

01001011 01000011 01010100 01000110 01111011 01110111 00110011 01001100 01100011 00110000 01001101 00110011 01011111 01010100 00110000 01011111 01001011 01101110 01101001 01100111 01101000 01110100 01000011 01010100 01000110 01111101

ASCIIコードの2進数表記と推測できるので、デコードする。

#!/usr/bin/env python3
codes= '01001011 01000011 01010100 01000110 01111011 01110111 00110011 01001100 01100011 00110000 01001101 00110011 01011111 01010100 00110000 01011111 01001011 01101110 01101001 01100111 01101000 01110100 01000011 01010100 01000110 01111101'
codes = codes.split(' ')

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

Dirt (Misc 50)

解凍すると、ディレクトリパスが以下のようになっている。

challenge\}\s\r\3\d\l\0\f\_\3\d\1\5\n\1\_\s\r\3\d\l\0\f\{\F\T\C\K

階層の深いディレクトリ名からつなげると、フラグになる。

KCTF{f0ld3rs_1n51d3_f0ld3rs}

Logger (Misc 100)

アクセスログを日時でソートする。

                :
2023-01-03 15:46:20.382679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /K - 39950
2023-01-03 15:46:20.385679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /C - 6142
2023-01-03 15:46:20.388679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /T - 48333
2023-01-03 15:46:20.391679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /F - 16796
2023-01-03 15:46:20.394679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /{ - 45424
2023-01-03 15:46:20.397679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /w - 57044
2023-01-03 15:46:20.400679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /r - 56376
2023-01-03 15:46:20.403679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /1 - 34061
2023-01-03 15:46:20.406679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /n - 18217
2023-01-03 15:46:20.409679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /k - 13820
2023-01-03 15:46:20.412679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /l - 3610
2023-01-03 15:46:20.415679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /3 - 43593
2023-01-03 15:46:20.418679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /_ - 46224
2023-01-03 15:46:20.421679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /1 - 49001
2023-01-03 15:46:20.424679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /n - 5135
2023-01-03 15:46:20.427679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /_ - 42868
2023-01-03 15:46:20.430679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /7 - 51928
2023-01-03 15:46:20.433679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /1 - 42167
2023-01-03 15:46:20.436679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /m - 9672
2023-01-03 15:46:20.439679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /3 - 13974
2023-01-03 15:46:20.442679 - Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 - GET /} - 5898

ソート後のアクセスログの最後の方のアクセス先の"/"の後の文字を並べると、フラグになった。

KCTF{wr1nkl3_1n_71m3}

GET Me (Web/API 25)

$ curl http://167.99.8.90:9009/
{"success":false,"message":"Sorry ! You can't GET it :P"}

POSTメソッドでアクセスしてみる。

$ curl http://167.99.8.90:9009/ -X POST
{"success":false,"message":"You should send me a url !"}

urlパラメータが必要のようだ。

$ curl http://167.99.8.90:9009/ -d 'url=a'
{"success":false,"message":"Looking for flag ? Visit https:\/\/hackenproof.com\/user\/security"}

https://hackenproof.com/でアカウントを作成して、https://hackenproof.com/user/securityにアクセスすると、フラグが書かれていた。

KCTF{H4ck3nPr00f3d_bY_Kn16h75qu4d}

Hello (Networking 300)

dnsでフィルタリングし、問合せしているドメインの*.knoghtctf.comの*部分を連結するとbase64文字列になりそう。

#!/usr/bin/env python3
from scapy.all import *
from base64 import *

packets = rdpcap('find-me.pcapng')

b64 = ''
for p in packets:
    if not p.haslayer(ICMP) and p.haslayer(DNS) and p[IP].dst == '8.8.8.8':
         b64 += p[DNSQR].qname.decode()[0]

flag = b64decode(b64).decode()
print(flag)

base64デコードした結果、以下になった。

UPBL{o1_mr3a_en0_hk3_i0h}

Vigenere暗号と推測して、https://www.dcode.fr/vigenere-cipherで復号する。KCTFで始まることから、鍵はKNIGHTと推測できる。

KCTF{h1_th3n_wh0_ar3_y0u}

Go Deep! (Forensics 400)

$ binwalk sea.jpg 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01
9247167       0x8D19BF        Zip archive data, at least v2.0 to extract, compressed size: 61520, uncompressed size: 61777, name: deep
9308807       0x8E0A87        End of Zip archive, footer length: 22

jpgの後ろにzipがくっついているので、切り出す。

$ foremost sea.jpg 
Processing: sea.jpg
|foundat=deep4}8���Umj�.���Z�����E[����6Q�i��ڻjT"bo!�V��ޱc���{��x�މ�}�=���9���L�,ܡy��Ջ;T�^���s�.��2R�;w�D�?���x��|~9�p��枽���;e0
<�����㥉ם;t������sg핺����vY�C�a�nӴ��%o܅�M̯���O���GB^��^Z��q྆��eIy�0J���$����e!|���&���/�Cz���i��RhvO�{+�;�
                 [���}@3��~Տ��J

                               ;��S�
                                    ���G����������SI��w�x��{�KG���Zandd��H4��ɵ�o�F��������!������̭���r����?'�����!A�1�;Y�Z������K^�\����<��97װS��4�r�-�����ڞ�������A�x/��m�rkR�[� ��&�X���J��8��
                 &��q�������`3�riA���{/P��&�k|x���s|X_��|��i�����Y�9�̥m<�h ��r�*�E��ha�H
*|

切り出したzipを解凍すると、deepファイルが展開される。deepファイルの先頭10バイトはjpgのヘッダ部になっているが、他はpng形式になっている。バイナリエディタで先頭10バイトを以下のように修正する。

修正前:ff d8 ff e0 00 10 4a 46 49 46
修正後:89 50 4e 47 0d 0a 1a 0a 00 00

pngの高さが異なるようなので、CRCが合うように高さを変える。

#!/usr/bin/env python3
import struct
import binascii

with open('deep.png', 'rb') as f:
    data = f.read()

head = data[:12]
tail = data[29:]

for h in range(265, 1024):
    height = struct.pack('>I', h)
    ihdr = data[12:20] + height + data[24:29]
    crc = struct.pack('!I', binascii.crc32(ihdr))
    if crc == data[29:33]:
        out = head + ihdr + tail
        with open('deep_fix.png', 'wb') as f:
            f.write(out)
        break

最終的に修正した画像の左下にフラグが書いてあった。

KCTF{g0_d33p_d0wn}

Factorie (Cryptography 50)

nを素因数分解するだけの問題。factordbで素因数分解する。

n = 39434538531451803895327 * 55131777675015246472249
KCTF{39434538531451803895327_55131777675015246472249}

Vaulter (Cryptography 100)

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

・byte_data = []
・file_name: 第1引数
・num: 1以上1024以下のランダム整数
・byte_data: file_nameのファイルの内容のバイナリデータ
・bdh: byte_dataの16進数表記
・out = []
・bdhの各文字eachについて以下を実行
 ・outにeachのASCIIコードとnumのXORを追加
 ・concat: outの各数値を文字にし、結合
 ・concatをoutput.encに書き込み

ブルートフォースでXORして16進数になるようにし、復号する。

#!/usr/bin/env python3
import string

def is_hexdigits(s):
    for c in s:
        if c not in string.hexdigits[:16]:
            return False
    return True

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

for num in range(1, 1024):
    try:
        dec = b''
        for i in range(len(enc)):
            dec += bytes([ord(enc[i]) ^ num])
        bdh = dec.decode()
    except:
        continue

    if is_hexdigits(bdh):
        break

with open('flag.docx', 'wb') as f:
    f.write(bytes.fromhex(bdh))

復号したら、docxファイルになるので、開いてみると、一番下にフラグが書いてあった。

KCTF{w3lc0m3_70_3ncryp710n_w0rLD}

I Love Pi (Cryptography 100)

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

・lengths: 10個の未知の要素を持つ配列
・flag: 長さ39のフラグ
・s = 0
・encoded_flag = ""
・lengthsの各要素lについて以下を実行
 ・seg = flag[s:s+l]
 ・segの長さだけ以下を実行
  ・seg: segをbase64エンコード
 ・s += l
 ・encoded_flag += seg
・encoded_flagを出力

base64の切れ目を確認しながら、復号する。

#!/usr/bin/env python3
import base64

dic = {}
for i in range(1, 17):
    s = 'a' * i
    for _ in range(i):
        s = base64.b64encode(s.encode()).decode()
    dic[len(s)] = i

with open('encoded_flag.txt', 'r') as f:
    enc = f.read()

#### guessing ####
base64_lengths = [12, 4, 24, 4, 32, 144, 8, 44, 32, 12]

#### output ####
flag = b''

index = 0
for i in range(len(base64_lengths)):
    l = base64_lengths[i]
    seg = enc[index:index + l]
    for _ in range(dic[l]):
        seg = base64.b64decode(seg)
    flag += seg
    index += l

flag = flag.decode()
print(flag)
KCTF{4_P1_4_D4Y_K33P5_7H3_H4CK3r5_4W4Y}

Jamal (Cryptography 125)

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

・seed(0)
・flag: フラグ
・x: 2以上9999999以下のランダム整数
・p = get_prime(43)
 ・p = 2**42以上2**43以下のランダム整数
 ・pが素数の場合にpを返却
・g = get_prime(43)
・gとpが同じ間以下を実行
 ・g = get_prime(43)
・gがpより大きい場合
 ・g, p = p, g
・y = pow(g, x, p)
・flagの各文字chについて以下を実行
 ・k = 2以上9999以下のランダム整数
 ・c1, c2 = encrypt(ch, g, p, y, k)
 ・c1, c2をflag.encに書き込み
・pをkey.pubに書き込み

seedでランダム値はわかっているので、逆算してフラグを求める。

#!/usr/bin/env python3
from random import randint, seed

def is_prime(n):
    if n == 2 or n == 3:
        return True
    if n % 2 == 0 or n < 2:
        return False
    for i in range(3, int(n**0.5)+1, 2):
        if n % i == 0:
            return False
    return True

def get_prime(n):
    while True:
        p = randint(2**(n-1), 2**n)
        if is_prime(p):
            return p

seed(0)
x = randint(2, 9999999)
p = get_prime(43)
g = get_prime(43)

while g == p:
    g = get_prime(43)

if g > p:
    g, p = p, g

y = pow(g, x, p)

with open('jamal-key.pub', 'r') as f:
    p_file = int(f.read().split(' ')[-1])

assert p_file == p

with open('jamal-flag.enc.txt', 'r') as f:
    lines = f.read().splitlines()

flag = ''
for line in lines:
    c1 = int(line.split(',')[0])
    c2 = int(line.split(',')[1])
    k = randint(2, 9999)
    assert pow(g, k, p) == c1
    ch = (c2 * pow(pow(y, k, p), -1, p)) % p
    flag += chr(ch)
print(flag)
KCTF{h4v3_y0u_h34rd_0f_3l64m4l?}

Encode Mania (Cryptography 150)

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

・flag: フラグ(kctf{************})
・encrypted_flag = flag.encode('utf-8')
・12回以下を繰り返し実行
 ・option: 0以上3以下のランダム整数
 ・encrypted_flag = encrypt(encrypted_flag, option)
  ・optionが0の場合、base64エンコード
  ・optionが1の場合、base32エンコード
  ・optionが2の場合、base16エンコード
  ・optionが3の場合、base85エンコード
・encode_mania.txtにencrypted_flagを書き込み

1回ずつbase64、base32、base16、base85デコードを試して確認しながらデコードする。

#!/usr/bin/env python3
import base64

with open('encode_mania.txt', 'r') as f:
    flag = f.read()

print('[+]', flag)

#### 1st decryption ####
flag = base64.b32decode(flag)
print('[+]', flag.decode())

#### 2nd decryption ####
flag = base64.b16decode(flag)
print('[+]', flag.decode())

#### 3rd decryption ####
flag = base64.b64decode(flag)
print('[+]', flag.decode())

#### 4th decryption ####
flag = base64.b85decode(flag)
print('[+]', flag.decode())

#### 5th decryption ####
flag = base64.b16decode(flag)
print('[+]', flag.decode())

#### 6th decryption ####
flag = base64.b16decode(flag)
print('[+]', flag.decode())

#### 7th decryption ####
flag = base64.b32decode(flag)
print('[+]', flag.decode())

#### 8th decryption ####
flag = base64.b64decode(flag)
print('[+]', flag.decode())

#### 9th decryption ####
flag = base64.b85decode(flag)
print('[+]', flag.decode())

#### 10th decryption ####
flag = base64.b64decode(flag)
print('[+]', flag.decode())

#### 11th decryption ####
flag = base64.b16decode(flag)
print('[+]', flag.decode())

#### 12th decryption ####
flag = base64.b85decode(flag)
print('[+]', flag.decode())

実行結果は以下の通り。

[+] GUZDGMRUIQ3TENJYGMYTOMBUHA2TSMZRGM4TGOBVIE2DKNRUGZATIQRXIEZTSNRRGUZDGMRUIU3DMNRWGQ3TKMRUHA2TSNZZG4ZTERRVHE3EENRUGZATKOBTGM3TQNRZGUZDGMRUIUZTMNCCGMYTMOBUHA2TSMZRGM4TGOBVIE2DKNRUGZATIQRTGEZTSNRRGUZDGMRUIU3DONCEGQ3DOMBUHA2TSNZZG42DMNRVG42TKNRUGZATIQRXIEZTSNSBGUZDGMRUIQ3TENJQGMYTOMBUHA2TSMZRGM4TGOBVHEZTANRUGZATMNJWHE3TINJZGUZDGMRUIU3DMNRWGQ3TKNRUHA2TSNZZG4ZTERRVIE2DKNRUGZATKOBTGM3TQNSCGUZDGMRUIUZTMNCCGMYTOMBUHA2TSMZRGM4TGOBVIE2DKNRUGZATIQRXIEZTSNJZGUZDGMRUIU3DMNRWGQ3TKMRUHA2TSMZRGM4TGOBVHE2TKNRUGZATIQRXIEZTSNRRGUZDGMRUIQ3TENJYGMYTMQZUHA2TSNZZG42DMNRVG42TKNRUGZATIQRTGEZTSNRZGUZDGMRUIQ3TENJQGMZDKNRUHA2TSMZRGM4TGOBVHEZTANRUGZATKOBTGM3TQNSBGUZDGMRUIU3DMNRWGQ3DOMBUHA2TSNZZG42DMNRVHE2TKNRUGZATIQRTGEZTSNRRGUZDGMRUIU3DMNRWGQ3TKMRUHA2TSNZZG4ZTERRVG43EENRUGZATKOBTGM3TQNSDGUZDGMRUIU3DMNRWGQ3DMQZUHA2TSMZRGM4TGOBVHE2TKNRUGZATKOBTGM3TQNRYGUZDGMRUIU3DMNRWGQ3TMNBUHA2TSNZZG42DMNRVHEZTANRUGZATIQRXIEZTSNSBGUZDGMRUIQ3TENJYGMZDIRJUHA2TSNZZG4ZTERRVHEZTANRUGZATIQRXIEZTSNRRGUZDGMRUIU3DMNRWGQ3TIRJUHA2TSMZTGZDDOMRVG42DKNRUGZATKOBTGM3TQNSDGUZDGMRUIQ3TENJQGMZDKMRUHA2TSMZRGM4TGOBVG43EENRUGZATKOBTGM3TQNSDGUZDGMRUIQ3TENJQGMZDIRJUHA2TSNZZG4ZTERRVG42DKNRUGZATMNJWHE3TINKBGUZDGMRUIQ3TENJQGMYTOMBUHA2TSNZZG4ZTERRVIE2DKNRUGZATIQRTGEZTSNSBGUZDGMRUIU3DMNRWGQ3TKMRUHA2TSNZZG42DMNRVHEZTANRUGZATIQRXIEZTSNSCGUZDGMRUIU3DMNRWGQ3TINRUHA2TSMZTGZDDOMRVG42DKNRUGZATIQRXIEZTSNRYGUZDGMRUIU3DMNRWGQ3DMOBUHA2TSNZZG42DMNRVG43EENRUGZATKOBTGM3TQNSCGUZDGMRUIQ3TENJQGMYTOMBUHA2TSMZRGM4TGOBVIE2DKNRUGZATIQRXIEZTSNRZGUZDGMRUIU3DMNRWGQ3DOMBUHA2TSMZRGM4TGOBVHE2TKNRUGZATKOBTGM3TQNRZGUZDGMRUIQ3TENJQGMZDKMRUHA2TSNZZG4ZTERRVHEZTANRUGZATIQRTGEZTSNKBGUZDGMRUIQ3TENJQGMZDIRJUHA2TSNZZG4ZTERRVG43EENRUGZATKOBTGM3TQNSBGUZDGMRUIU3DMNRWGQ3TINRUHA2TSMZRGM4TGOBVHEZTANRUGZATIQRXIEZTSNSCGUZDGMRUIQ3TENJQGMZDIRJUHA2TSNZZG42DMNRVHEZTANRUGZATIQRXIEZTSNRZGUZDGMRUIU3DMNRWGQ3TKNRUHA2TSMZRGM4TGOBVIE2DKNRUGZATKOBTGM3TQNRYGUZDGMRUIQ3TENJQGMYTOMBUHA2TSNZZG42DMNRVG42TKNRUGZATIQRXIEZTSNSBGUZDGMRUIQ3TENJYGMYTMQZUHA2TSMZRGM4TGOBVIE2DKNRUGZATKOBTGM3TQNKBGUZDGMRUIU3DMNRWGQ3TIQJUHA2TSMZRGM4TGOBVG43EENRUGZATKOBTGM3TQNSCGUZDGMRUIQ3TENJYGMYTOMBUHA2TSMZRGM4TGOBVIE2DKNRUGZATIQRXIEZTSNRYGUZDGMRUIU3DMNRWGQ3TKNRUHA2TSNZZG4ZTERRVIE3EENRUGZATKOBTGM3TQNRYGUZDGMRUIQ3TENJQGMYTOMBUHA2TSMZRGM4TGOBVHE3EENRUGZATIQRXIEZTSNSEGUZDGMRUIU3DONCEGQ3DOMBUHA2TSNZZG4ZTERRVHE2TKNRUGZATIQRXIEZTSNSBGUZDGMRUIQ3TENJQGMYTOMBUHA2TSMZRGM4TGOBVHEZTANRUGZATKOBTGM3TQNRYGUZDGMRUIU3DMNRWGQ3TIRJUHA2TSNZZG4ZTERRVIE2DKNRUGZATIQRXIEZTSNSBGUZDGMRUIQ3TENJYGMZDINRUHA2TSMZRGM4TGOBVIE2TKNRUGZATIQRXIEZTSNRRGUZDGMRUIQ3TENJYGMZDIQJUHA2TSNZZG42DMNRVG43EENRUGZATIQRXIEZTSNSCGUZDGMRUIQ3TENJQGMZDKQJUHA2TSMZTGZDDOMRVHE2TKNRUGZATIQRXIEZTSNSEGUZDGMRUIQ3TENJQGMZDIRJUHA2TSMZRGM4TGOBVG42TKNRUGZATIQRTGEZTSNSBGUZDGMRUIQ3TENJQGMYTMQZUHA2TSMZRGM4TGOBVHEZTANRUGZATIQRTGEZTSNRRGUZDGMRUIU3DMNRWGQ3TKMRUHA2TSNZZG4ZTERRVG43EENRUGZATKOBTGM3TQNSCGUZDGMRUIQ3TENJQGMZDIQJUHA2TSMZRGM4TGOBVG43EENRUGZATKOBTGM3TQNRYGUZDGMRUIU3DMNRWGQ3DMQZUHA2TSNZZG42DMNRVHEZTANRUGZATKOBTGM3TQNRRGUZDGMRUIU3DMNRWGQ3TKNRUHA2TSNZZG4ZTERRVHEZTANRUGZATIQRXIEZTSNRRGUZDGMRUIU3DMNRWGQ3TKNRUHA2TSMZRGM4TGOBVHE2TKNRUGZATKOBTGM3TQNSEGUZDGMRUIQ3TENJYGMZDINRUHA2TSNZZG42DMNRVG42TKNRUGZATIQRXIEZTSNRZGUZDGMRUIU3DMNRWGQ3TKMRUHA2TSNZZG42DMNRVG43EENRUGZATIQRTGEZTSNRZGUZDGMRUIQ3TENJYGMYTOMBUHA2TSNZZG4ZTERRVG43EENRUGZATIQRTGEZTSNKBGUZDGMRUIQ3TENJQGMZDIRJUHA2TSNZZG42DMNRVG43EENRUGZATKOBTGM3TQNSDGUZDGMRUIU3DMNRWGQ3TIRJUHA2TSMZTGZDDOMRVG43EENRUGZATMNJWHE3TINKBGUZDGMRUIQ3TENJYGMZDINRUHA2TSNZZG42DMNRVG43EENRUGZATKOBTGM3TQNSCGUZDGMRUIQ3TENJQGMZDINRUHA2TSMZRGM4TGOBVIE2DKNRUGZATIQRTGEZTSNRZGUZDGMRUIUZTMNCCGMYTMQZUHA2TSNZZG4ZTERRVG43EENRUGZATKOBTGM3TQNSFGUZDGMRUIQ3TENJYGMZDIRJUHA2TSNZZG42DMNRVHEZTANRUGZATKOBTGM3TQNSBGUZDGMRUIQ3TENJQGMZDIRJUHA2TSNZZG4ZTERRVG42DKNRUGZATKOBTGM3TQNSBGUZDGMRUIQ3TENJQGMYTMQZUHA2TSMZRGM4TGOBVHE3EENRUGZATIQRXIEZTSNSEGUZDGMRUIQ3TENJYGMYTMQZUHA2TSMZRGM4TGOBVHE3EENRUGZATKOBTGM3TQNSDGUZDGMRUIQ3TENJYGMYTOMBUHA2TSNZZG42DMNRVHE3EENRUGZATIQRTGEZTSNRRGUZDGMRUIQ3TENJQGMYTOMBUHA2TSNZZG42DMNRVG42TKNRUGZATIQRTGEZTSNKBGUZDGMRUIQ3TENJYGMZDIQJUHA2TSNZZG4ZTERRVIE2DKNRUGZATMNJWHE3TINJZGUZDGMRUIUZTMNCCGMYTMQZUHA2TSMZTGZDDOMRVG42TKNRUGZATMNJWHE3TINJZGUZDGMRUIQ3TENJYGMYTOMBUHA2TSMZRGM4TGOBVIE2DKNRUGZATIQRXIEZTSNRRGUZDGMRUIU3DMNRWGQ3TKMRUHA2TSNZZG4ZTERRVHE3EENRUGZATKOBTGM3TQNRRGUZDGMRUIU3DMNRWGQ3TINRUHA2TSMZRGM4TGOBVG42DKNRUGZATIQRXIEZTSNSEGUZDGMRUIU3DONCEGQ3DOMBUHA2TSNZZG4ZTERRVG42TKNRUGZATIQRXIEZTSNSBGUZDGMRUIQ3TENJQGMYTMOBUHA2TSMZRGM4TGOBVHEZTANRUGZATIQRXIEZTSNKBGUZDGMRUIU3DMNRWGQ3TIQJUHA2TSNZZG4ZTERRVIE3EENRUGZATIQRTGEZTSNKBGUZDGMRUIUZTMNCCGMYTMOBUHA2TSNZZG4ZTERRVHE3EENRUGZATMNJWHE3TINRRGUZDGMRUIU3DMNRWGQ3DMQZUHA2TSNZZG42DMNRVG42TKNRUGZATMNJWHE3TINRYGUZDGMRUIQ3TENJQGMZDKNRUHA2TSMZRGM4TGOBVHEZTANRUGZATMNJWIE3TQNRYGUZDGMRUIUZTMNJQGQ3TINRUHA2TSMZTGZDDGOBVHE2TKNRUGZATMNJWIE3TQNRYGUZDGMRUIUZTMNJQGQ3TINRUHA2TSMZTGZDDGOBVHE2TCM2EGNCA====
[+] 52324D7258317048593139385A45646A4B7A396152324E66664752485979732F596B646A5833786952324E364B316848593139385A45646A4B31396152324E674D467048597974665755646A4B7A396A52324D7250317048593139385930646A6569745952324E66664756485979732F5A45646A5833786B52324E364B317048593139385A45646A4B7A395952324E6666475248593139385955646A4B7A396152324D7258316C48597974665755646A4B31396952324D7250325648593139385930646A5833786A52324E6666467048597974665955646A4B31396152324E66664752485979732F576B646A5833786C52324E6666466C48593139385955646A5833786852324E6666476448597974665930646A4B7A396A52324D7258324E485979732F5930646A4B7A396152324E6666474E4859336F725745646A5833786C52324D725032524859313938576B646A5833786C52324D7250324E485979732F5745646A6569745A52324D72503170485979732F5A45646A4B31396A52324E6666475248597974665930646A4B7A396B52324E666647464859336F725745646A4B7A396852324E666646684859797466576B646A5833786B52324D7250317048593139385A45646A4B7A396952324E6666467048593139385955646A5833786952324D72503252485979732F5930646A4B31395A52324D7250324E485979732F576B646A5833786A52324E6666474648593139385930646A4B7A396B52324D7250324E48597974665930646A4B7A396952324E6666475648593139385A45646A5833786852324D7250317048597974665755646A4B7A396A52324D7258316C48593139385A45646A5833785A52324E6666474A4859313938576B646A5833786B52324D7258317048593139385A45646A4B7A396852324E66664756485979732F5A6B646A5833786852324D725031704859313938596B646A4B7A396D52324E674D4670485979732F5955646A4B7A396A52324D7250317048593139385930646A5833786852324E6666474E485979732F5A45646A4B7A396A52324D7258324648593139385A55646A4B7A396152324D7258324A4859797466576B646A4B7A396B52324D7250325A4859336F725955646A4B7A396D52324D7250324E48593139385755646A4B31396A52324D7250316C48593139385930646A4B31396152324E66664752485979732F576B646A5833786B52324D7250324A4859313938576B646A5833786852324E6666466C48597974665930646A5833786152324E66664756485979732F5930646A4B7A396152324E6666475648593139385955646A5833786D52324D7258324648597974665755646A4B7A396952324E666647524859797466576B646A4B31396952324D72583170485979732F576B646A4B31395A52324D7250324E4859797466576B646A5833786C52324E6666474E4859336F72576B646A6569745A52324D725832464859797466576B646A5833786B52324D7250324648593139385A45646A4B31396952324E364B316C485979732F576B646A5833786E52324D7258324E48597974665930646A5833786A52324D7250324E485979732F5745646A5833786A52324D7250316C4859313938596B646A4B7A396D52324D7258316C4859313938596B646A5833786C52324D725831704859797466596B646A4B31396152324D7250317048597974665755646A4B31395A52324D7258324A485979732F5A45646A6569745952324E364B316C4859336F725755646A6569745952324D7258317048593139385A45646A4B7A396152324E66664752485979732F596B646A5833786152324E6666474648593139385745646A4B7A396D52324E674D4670485979732F5755646A4B7A396A52324D7250316848593139385930646A4B7A395A52324E6666474A485979732F5A6B646A4B31395A52324E364B3168485979732F596B646A6569746152324E6666466C48597974665755646A6569746852324D7250325648593139385930646A656A786852324E365047464859336F385955646A656A786852324E365047464859336F3859513D3D
[+] R2MrX1pHY198ZEdjKz9aR2NffGRHYys/YkdjX3xiR2N6K1hHY198ZEdjK19aR2NgMFpHYytfWUdjKz9jR2MrP1pHY198Y0djeitYR2NffGVHYys/ZEdjX3xkR2N6K1pHY198ZEdjKz9YR2NffGRHY198YUdjKz9aR2MrX1lHYytfWUdjK19iR2MrP2VHY198Y0djX3xjR2NffFpHYytfYUdjK19aR2NffGRHYys/WkdjX3xlR2NffFlHY198YUdjX3xhR2NffGdHYytfY0djKz9jR2MrX2NHYys/Y0djKz9aR2NffGNHY3orWEdjX3xlR2MrP2RHY198WkdjX3xlR2MrP2NHYys/WEdjeitZR2MrP1pHYys/ZEdjK19jR2NffGRHYytfY0djKz9kR2NffGFHY3orWEdjKz9hR2NffFhHYytfWkdjX3xkR2MrP1pHY198ZEdjKz9iR2NffFpHY198YUdjX3xiR2MrP2RHYys/Y0djK19ZR2MrP2NHYys/WkdjX3xjR2NffGFHY198Y0djKz9kR2MrP2NHYytfY0djKz9iR2NffGVHY198ZEdjX3xhR2MrP1pHYytfWUdjKz9jR2MrX1lHY198ZEdjX3xZR2NffGJHY198WkdjX3xkR2MrX1pHY198ZEdjKz9hR2NffGVHYys/ZkdjX3xhR2MrP1pHY198YkdjKz9mR2NgMFpHYys/YUdjKz9jR2MrP1pHY198Y0djX3xhR2NffGNHYys/ZEdjKz9jR2MrX2FHY198ZUdjKz9aR2MrX2JHYytfWkdjKz9kR2MrP2ZHY3orYUdjKz9mR2MrP2NHY198WUdjK19jR2MrP1lHY198Y0djK19aR2NffGRHYys/WkdjX3xkR2MrP2JHY198WkdjX3xhR2NffFlHYytfY0djX3xaR2NffGVHYys/Y0djKz9aR2NffGVHY198YUdjX3xmR2MrX2FHYytfWUdjKz9iR2NffGRHYytfWkdjK19iR2MrX1pHYys/WkdjK19ZR2MrP2NHYytfWkdjX3xlR2NffGNHY3orWkdjeitZR2MrX2FHYytfWkdjX3xkR2MrP2FHY198ZEdjK19iR2N6K1lHYys/WkdjX3xnR2MrX2NHYytfY0djX3xjR2MrP2NHYys/WEdjX3xjR2MrP1lHY198YkdjKz9mR2MrX1lHY198YkdjX3xlR2MrX1pHYytfYkdjK19aR2MrP1pHYytfWUdjK19ZR2MrX2JHYys/ZEdjeitYR2N6K1lHY3orWUdjeitYR2MrX1pHY198ZEdjKz9aR2NffGRHYys/YkdjX3xaR2NffGFHY198WEdjKz9mR2NgMFpHYys/WUdjKz9jR2MrP1hHY198Y0djKz9ZR2NffGJHYys/ZkdjK19ZR2N6K1hHYys/YkdjeitaR2NffFlHYytfWUdjeithR2MrP2VHY198Y0djejxhR2N6PGFHY3o8YUdjejxhR2N6PGFHY3o8YQ==
[+] Gc+_ZGc_|dGc+?ZGc_|dGc+?bGc_|bGcz+XGc_|dGc+_ZGc`0ZGc+_YGc+?cGc+?ZGc_|cGcz+XGc_|eGc+?dGc_|dGcz+ZGc_|dGc+?XGc_|dGc_|aGc+?ZGc+_YGc+_YGc+_bGc+?eGc_|cGc_|cGc_|ZGc+_aGc+_ZGc_|dGc+?ZGc_|eGc_|YGc_|aGc_|aGc_|gGc+_cGc+?cGc+_cGc+?cGc+?ZGc_|cGcz+XGc_|eGc+?dGc_|ZGc_|eGc+?cGc+?XGcz+YGc+?ZGc+?dGc+_cGc_|dGc+_cGc+?dGc_|aGcz+XGc+?aGc_|XGc+_ZGc_|dGc+?ZGc_|dGc+?bGc_|ZGc_|aGc_|bGc+?dGc+?cGc+_YGc+?cGc+?ZGc_|cGc_|aGc_|cGc+?dGc+?cGc+_cGc+?bGc_|eGc_|dGc_|aGc+?ZGc+_YGc+?cGc+_YGc_|dGc_|YGc_|bGc_|ZGc_|dGc+_ZGc_|dGc+?aGc_|eGc+?fGc_|aGc+?ZGc_|bGc+?fGc`0ZGc+?aGc+?cGc+?ZGc_|cGc_|aGc_|cGc+?dGc+?cGc+_aGc_|eGc+?ZGc+_bGc+_ZGc+?dGc+?fGcz+aGc+?fGc+?cGc_|YGc+_cGc+?YGc_|cGc+_ZGc_|dGc+?ZGc_|dGc+?bGc_|ZGc_|aGc_|YGc+_cGc_|ZGc_|eGc+?cGc+?ZGc_|eGc_|aGc_|fGc+_aGc+_YGc+?bGc_|dGc+_ZGc+_bGc+_ZGc+?ZGc+_YGc+?cGc+_ZGc_|eGc_|cGcz+ZGcz+YGc+_aGc+_ZGc_|dGc+?aGc_|dGc+_bGcz+YGc+?ZGc_|gGc+_cGc+_cGc_|cGc+?cGc+?XGc_|cGc+?YGc_|bGc+?fGc+_YGc_|bGc_|eGc+_ZGc+_bGc+_ZGc+?ZGc+_YGc+_YGc+_bGc+?dGcz+XGcz+YGcz+YGcz+XGc+_ZGc_|dGc+?ZGc_|dGc+?bGc_|ZGc_|aGc_|XGc+?fGc`0ZGc+?YGc+?cGc+?XGc_|cGc+?YGc_|bGc+?fGc+_YGcz+XGc+?bGcz+ZGc_|YGc+_YGcz+aGc+?eGc_|cGcz<aGcz<aGcz<aGcz<aGcz<aGcz<a
[+] 34423536343335363435353433323536344235413441343634333535333235373437353633343536343135363533343334413441344434383535353535323443344235363433353735313533353335393445343634453436343335353332353734373532353734363431333334333437344535363445343735333332343435303442353634333536343535323533353434373436344134363433353535333535343734363445343535373536353334333441343634413536353135343532353634423536343435373439353334333534343935413434343634333535353335353437343634433537343334443442343734393335343934363531344534323535344235363433353634353532353335313445353235373436343335373533353834433441343535363442344434423433344134363442353735353334333334433442353634343536344433333433353934453445353534363431353534323534343934413534353734423444344234333441344134443437333233333333333234423536343335363435353235333530343935413432343634313535343235343439344133323435333435313441333534383535334433443344334433443344
[+] 4B564356455432564B5A4A464355325747563456415653434A4A4D485555524C4B564357515353594E464E464355325747525746413343474E564E47533244504B5643564552535447464A464355535547464E45575653434A464A56515452564B56445749534354495A44464355535547464C57434D4B4749354946514E42554B564356455253514E525746435753584C4A45564B4D4B434A464B575534334C4B5644564D3343594E4E554641554254494A54574B4D4B434A4A4D47323333324B56435645525350495A424641554254494A324534514A3548553D3D3D3D3D3D
[+] KVCVET2VKZJFCU2WGV4VAVSCJJMHUURLKVCWQSSYNFNFCU2WGRWFA3CGNVNGS2DPKVCVERSTGFJFCUSUGFNEWVSCJFJVQTRVKVDWISCTIZDFCUSUGFLWCMKGI5IFQNBUKVCVERSQNRWFCWSXLJEVKMKCJFKWU43LKVDVM3CYNNUFAUBTIJTWKMKCJJMG2332KVCVERSPIZBFAUBTIJ2E4QJ5HU======
[+] UEROUVRQSV5yPVBJXzR+UEhJXiZQSV4lPlFmZihoUERFS1RQRT1ZKVBISXN5UGdHSFFQRT1Wa1FGPX44UERFPllQZWZIU1BIUjskUGVlXkhPP3Bge1BJXmozUERFOFBPP3BtNA==
[+] PDNQTPI^r=PI_4~PHI^&PI^%>Qff(hPDEKTPE=Y)PHIsyPgGHQPE=VkQF=~8PDE>YPefHSPHR;$Pee^HO?p`{PI^j3PDE8PO?pm4
[+] NEY0NzM4NzY2NjY0NzQ1RjIzNDY1NTZGNjQ2OTQzNTY2QzNCNDkyODU3NkU1ODM0MzY0NzJENDU1MzNC
[+] 4F4738766664745F2346556F646943566C3B4928576E583436472D45533B
[+] OG8vfdt_#FUodiCVl;I(WnX46G-ES;
[+] KCTF{dfs_0r_b4u7e_f04c3}
KCTF{dfs_0r_b4u7e_f04c3}

Toddler RSA (Cryptography 300)

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

・flag1: フラグの前半
・flag2: フラグの後半
・p, q: 512ビット素数
・n = p * q
・e = 0x10001
・phi = (p - 1) * (q - 1) 
・m = flag1を数値化したもの
・ct = pow(m, e, n)
・primes = [p, q]
・98回以下繰り返し
 ・primesに512ビット素数を追加
・primesをシャッフル
・primes2 = []
・以下繰り返し
 ・primes2の長さが16の場合、繰り返し終了
 ・p: 128ビット素数
 ・pがprimes2になければ、primes2にpを追加
・以下繰り返し
 ・n2 = 1
 ・primes2の各数値pについて以下を実行
  ・r: 0以上1以下のランダム整数
  ・rが1の場合、n2 *= p
 ・n2のビット長が1024より大きい場合、繰り返し終了
・m2 = flag2を数値化したもの
・ct2 = pow(m2, e, n2)
・infos.txtに以下の形式で書き込み
 [ct]
 [ct2]
 [primes[0]] [primes[1]] [primes[2]] ...
 [primes2[0]] [primes2[1]] [primes2[2]] ...

flag1の暗号化に使われているp, qは不明なので、primes1の素数のペアをブルートフォースして復号する。
flag2の暗号化に使われている素数はその積が1024bitを超えたときのものなので、それを使ってブルートフォースして復号する。

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

def is_printable(s):
    for c in s:
        if c < 32 or c > 126:
            return False
    return True

e = 0x10001

with open('infos.txt', 'r') as f:
    params = f.read().splitlines()

ct = int(params[0])
ct2 = int(params[1])
primes = [int(p) for p in params[2].split(' ')[:-1]]
primes2 = [int(p) for p in params[3].split(' ')[:-1]]

for pq in itertools.combinations(primes, 2):
    p = pq[0]
    q = pq[1]
    phi = (p - 1) * (q - 1)
    d = inverse(e, phi)
    m = pow(ct, d, p * q)
    flag1 = long_to_bytes(m)
    if flag1.startswith(b'KCTF{'):
        break

found = False
for i in range(1, 17):
    for ps in itertools.combinations(primes2, i):
        n = 1
        for p in ps:
            n *= p
        if n.bit_length() > 1024:
            phi = 1
            for p in ps:
                phi *= p - 1
            d = inverse(e, phi)
            m2 = pow(ct2, d, n)
            flag2 = long_to_bytes(m2)
            if flag2.endswith(b'}') and is_printable(flag2):
                found = True
                break
    if found:
        break

flag = (flag1 + flag2).decode()
print(flag)
KCTF{rsa_and_only_rsa_ftw}