DaVinciCTF 2023 Writeup

この大会は2023/3/11 17:00(JST)~2023/3/13 5:00(JST)に開催されました。
今回もチームで参戦。結果は301点で285チーム中106位でした。
自分で解けた問題をWriteupとして書いておきます。

Welcome (Misc)

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

dvCTF{Welcome_to_the_DVCTF2023!}

Principiante (Prog)

各音階がアルファベットで提示されるので、鍵盤のアスキーアートで該当する箇所を"X"にして回答する。各音階は以下のようになり、#はその音階の右肩の黒鍵盤を指す。

ド    C
ド#   C#
レ    D
レ#   D#
ミ    E
ファ  F
ファ# F#
ソ    G
ソ#   G#
ラ    A
ラ#   A#
シ    B

何番目かというのも提示されるので、その左までは固定で構成する。該当する鍵盤を場合分けして構成する。構成した鍵盤の図を答えていけば、フラグが得られる。

#!/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 display(index, key):
    outp = ''
    outp += '____________________________' * index + '_' + '\n'
    outp += '|  | | | |  |  | | | | | |  ' * index + '|' + '\n'
    outp += '|  | | | |  |  | | | | | |  ' * index + '|' + '\n'

    if key[-1] == "#":
        outp += '|  | | | |  |  | | | | | |  ' * (index - 1)
        if key[0] == 'C':
            outp += '|  |X| | |  |  | | | | | |  |' + '\n'
        elif key[0] == 'D':
            outp += '|  | | |X|  |  | | | | | |  |' + '\n'
        elif key[0] == 'F':
            outp += '|  | | | |  |  |X| | | | |  |' + '\n'
        elif key[0] == 'G':
            outp += '|  | | | |  |  | | |X| | |  |' + '\n'
        elif key[0] == 'A':
            outp += '|  | | | |  |  | | | | |X|  |' + '\n'
    else:
        outp += '|  | | | |  |  | | | | | |  ' * index + '|' + '\n'

    outp += '|  |_| |_|  |  |_| |_| |_|  ' * index + '|' + '\n'
    outp += '|   |   |   |   |   |   |   ' * index + '|' + '\n'

    if key[-1] == "#":
        outp += '|   |   |   |   |   |   |   ' * index + '|' + '\n'
    else:
        outp += '|   |   |   |   |   |   |   ' * (index - 1)
        if key[0] == 'C':
            outp += '| X |   |   |   |   |   |   |' + '\n'
        elif key[0] == 'D':
            outp += '|   | X |   |   |   |   |   |' + '\n'
        elif key[0] == 'E':
            outp += '|   |   | X |   |   |   |   |' + '\n'
        elif key[0] == 'F':
            outp += '|   |   |   | X |   |   |   |' + '\n'
        elif key[0] == 'G':
            outp += '|   |   |   |   | X |   |   |' + '\n'
        elif key[0] == 'A':
            outp += '|   |   |   |   |   | X |   |' + '\n'
        elif key[0] == 'B':
            outp += '|   |   |   |   |   |   | X |' + '\n'

    outp += '|___|___|___|___|___|___|___' * index + '|' + '\n'

    print(outp)
    return outp.encode()

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('prog.dvc.tf', 7751))

for _ in range(12):
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    index = int(data.split(' ')[3][0])
    key = data.split(' ')[4]
    ans = display(index, key)
    s.sendall(ans)

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

実行結果は以下の通り。

n° 1
Give me the 3rd G# plz
_____________________________________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | |X| | |  |
|  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

n° 2

D:\CTF\大会\22_DaVinciCTF\09_Prog\02_Principiante>

D:\CTF\大会\22_DaVinciCTF\09_Prog\02_Principiante>python3 solve.py
n° 1
Give me the 4th G# plz
_________________________________________________________________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | |X| | |  |
|  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

n° 2
Give me the 1st D plz
_____________________________
|  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |
|  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |
|   | X |   |   |   |   |   |
|___|___|___|___|___|___|___|

n° 3
Give me the 4th C plz
_________________________________________________________________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   | X |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

n° 4
Give me the 4th C# plz
_________________________________________________________________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  |X| | |  |  | | | | | |  |
|  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

n° 5
Give me the 2nd A# plz
_________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | |X|  |
|  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

n° 6
Give me the 2nd G plz
_________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   | X |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

n° 7
Give me the 2nd D# plz
_________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | |X|  |  | | | | | |  |
|  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

n° 8
Give me the 1st F plz
_____________________________
|  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |
|  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |
|   |   |   | X |   |   |   |
|___|___|___|___|___|___|___|

n° 9
Give me the 1st B plz
_____________________________
|  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |
|  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |
|   |   |   |   |   |   | X |
|___|___|___|___|___|___|___|

n° 10
Give me the 3rd E plz
_____________________________________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   | X |   |   |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

n° 11
Give me the 3rd F# plz
_____________________________________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  |X| | | | |  |
|  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

n° 12
Give me the 3rd A plz
_____________________________________________________________________________________
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |  | | | |  |  | | | | | |  |
|  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |  |_| |_|  |  |_| |_| |_|  |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
|   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   | X |   |
|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|___|

Noice, here is your flag : dvCTF{4r3_Y0U_7H3_N3X7_M0Z4r7?}
dvCTF{4r3_Y0U_7H3_N3X7_M0Z4r7?}

Vigenere XOR (Cryptography)

2進数としてデコードしたものをファイルに保存する。これをXOR Crackerでクラックする。一番の候補となるものの鍵の長さは6であるとわかる。最有力候補のファイルを保存する。
文中にフラグが崩れたような形式のデータがあるので、そのファイルを使って、調整するスクリプトで復号する。

#!/usr/bin/env python3
def is_printables(s):
    for c in s:
        if ord(c) < 32 or ord(c) > 126:
            return False
    return True

with open('message', 'r') as f:
    codes = f.read()

enc = b''
for i in range(0, len(codes), 8):
    enc += bytes([int(codes[i:i+8], 2)])

with open('enc', 'wb') as f:
    f.write(enc)

flag_head = b'dvCTF{'

with open('f21f33a5-033e-45c8-b12b-f69794be04d1', 'rb') as f:
    enc = f.read()

index = enc.index(b'{') - 5
assert index % 6 == 0

key = b''
for i in range(len(flag_head)):
    key += bytes([enc[i+index] ^ flag_head[i]])

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

復号結果は以下の通り。

You did it! The flag is dvCTF{80R3D_K3Y_15_K3Y_MY_FR13ND}. Well done !
dvCTF{80R3D_K3Y_15_K3Y_MY_FR13ND}

Desintegrated RSA (Cryptography)

2048ビットのpが2ビット間違っているので、総当たりで反転し、nを割り切れるものを探す。p, qがわかれば、あとは通常通り復号する。

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

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

e = int(params[0].split(' ')[-1])
N = int(params[1].split(' ')[-1])
c = int(params[2].split(' ')[-1])
str_p = eval(params[3].split(' ')[-1])

found = False
for i in range(len(str_p)):
    for j in range(i + 1, len(str_p)):
        s = list(str_p)
        s[i] = str(int(s[i]) ^ 1)
        s[j] = str(int(s[j]) ^ 1)
        p = int(''.join(s), 2)
        if N % p == 0:
            found = True
            break
    if found:
        break

q = N // p
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, N)
flag = long_to_bytes(m).decode()
flag = 'dvCTF{%s}' % flag
print(flag)
dvCTF{L30n4rd_M19ht_B3_0ld_But_5t1ll_Cunn1n9}