59 lines
1.4 KiB
Python
Executable File
59 lines
1.4 KiB
Python
Executable File
#!/usr/bin/env nix-shell
|
|
#!nix-shell -i python3 -p python3 python3Packages.pwntools
|
|
|
|
from pwn import *
|
|
from pathlib import Path
|
|
|
|
addr, port, *_ = "mercury.picoctf.net 36449".split(" ")
|
|
|
|
def chunks(l, n):
|
|
for i in range(0, len(l), n):
|
|
yield l[i:i + n]
|
|
|
|
def unhex(hex: str) -> list[int]:
|
|
return [int(x, 16) for x in chunks(hex, 2)]
|
|
|
|
def xor_bytes(a: bytes, b: bytes) -> bytes:
|
|
assert len(a) == len(b)
|
|
return bytes(x ^ y for x, y in zip(a, b))
|
|
|
|
KEYLEN = 50000
|
|
|
|
def conn():
|
|
if args.REMOTE:
|
|
return remote(addr, int(port))
|
|
else:
|
|
return process([str(Path(__file__).parent / "otp.py")])
|
|
|
|
def main():
|
|
r = conn()
|
|
r.recvuntil(b'This is the encrypted flag!\n')
|
|
enc_flag = r.recvline().strip()
|
|
print(f"{enc_flag=}")
|
|
|
|
flag_len = len(enc_flag) // 2
|
|
assert flag_len % 2 == 0
|
|
|
|
remaining_bytes_until_key_reset = KEYLEN - flag_len
|
|
|
|
r.recvuntil(b'What data would you like to encrypt? ')
|
|
r.sendline(b'A'*remaining_bytes_until_key_reset)
|
|
|
|
# Ignore output, we're only trying to make the program
|
|
# reset the key offset
|
|
|
|
r.recvuntil(b'What data would you like to encrypt? ')
|
|
payload = b"A" * flag_len
|
|
r.sendline(payload)
|
|
r.recvuntil(b'Here ya go!\n')
|
|
response = r.recvline().strip()
|
|
|
|
key = xor_bytes(payload, unhex(response))
|
|
print(f"{key=}")
|
|
|
|
flag = xor_bytes(unhex(enc_flag), key).decode().strip()
|
|
print(f"picoCTF{{{flag}}}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|