38 lines
1.1 KiB
Python
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()))
|