Files
ctf/2026/cscg/crypto/dino-vault/solve.py
2026-03-09 21:44:25 +01:00

38 lines
1.1 KiB
Python

from pwn import remote
from math import gcd
from sympy import mod_inverse
from Crypto.Util.number import long_to_bytes, bytes_to_long
def from_dna(dna: str):
lookup = {"A": 0, "T": 1, "G": 2, "C": 3}
result = []
for i in range(0, len(dna), 4):
chunk = dna[i:i+4]
c = 0
for j, base in enumerate(chunk):
c |= lookup[base] << (j * 2)
result.append(chr(c))
return "".join(result)
def download_flag():
p.sendline(b"3")
p.recvuntil(b"?")
p.sendline(b"Vexillum Rex")
buf = p.recvuntil(b"?")
buf = buf.split(b"\n")
return (buf[2].decode(), int(buf[4].decode()))
with remote("7s6shzivkoaegie7wslgzswa7m-5000-dino-vault.challenge.cscg.live", 443, ssl=True) as p:
p.recvuntil(b"Exit\n")
flag_enc, n1 = download_flag()
_, n2 = download_flag()
vault_key = gcd(n1, n2)
transmission_key = n1 // vault_key
e = 2 ** 16 + 1
phi = (transmission_key - 1) * (vault_key - 1)
d = mod_inverse(e, phi)
ciphertext = bytes_to_long(bytes.fromhex(flag_enc))
plaintext = pow(ciphertext, d, n1)
print(from_dna(long_to_bytes(plaintext).decode()))