Skip to content

Instantly share code, notes, and snippets.

@PsHegger
Last active January 8, 2024 08:11
Show Gist options
  • Save PsHegger/96379860fae333bde0fd16777f1a8986 to your computer and use it in GitHub Desktop.
Save PsHegger/96379860fae333bde0fd16777f1a8986 to your computer and use it in GitHub Desktop.
irisctf2024_sources
#!/usr/bin/env python3
from pwn import *
RUN_LOCALLY = False
def get_tube():
p = None
if RUN_LOCALLY:
p = process(['python3', 'chal.py'])
else:
p = remote('accessible-sesasum-indicum.chal.irisc.tf', 10104)
recv_until_line(p, "What is the 4-digit PIN?")
return p
def recv_until_line(p, expected_line):
line_found = False
while not line_found:
line = p.recvline().decode().strip()
if len(line) > 4:
print(line)
line_found = line == expected_line
if __name__ == "__main__":
master_code = cyclic_gen("0123456789abcdef", 4).get() # de Bruijn implementation from pwntools
p = get_tube()
for _ in range(15):
p.sendline(master_code)
recv_until_line(p, "What is the 4-digit PIN?")
p.sendline(master_code)
recv_until_line(p, "You unlock the vault and find the flag.")
print(p.recvall().decode())
#!/usr/bin/env python3
from Crypto.Util.number import bytes_to_long, long_to_bytes
from pwn import *
RUN_LOCALLY = True
def ROTL(a, b):
return (((a) << (b)) | ((a % 2**32) >> (32 - (b)))) % 2**32
def qr(x, a, b, c, d):
x[a] += x[b]; x[d] ^= x[a]; x[d] = ROTL(x[d],16)
x[c] += x[d]; x[b] ^= x[c]; x[b] = ROTL(x[b],12)
x[a] += x[b]; x[d] ^= x[a]; x[d] = ROTL(x[d], 8)
x[c] += x[d]; x[b] ^= x[c]; x[b] = ROTL(x[b], 7)
ROUNDS = 20
def chacha_block(inp):
x = list(inp)
for i in range(0, ROUNDS, 2):
qr(x, 0, 4, 8, 12)
qr(x, 1, 5, 9, 13)
qr(x, 2, 6, 10, 14)
qr(x, 3, 7, 11, 15)
qr(x, 0, 5, 10, 15)
qr(x, 1, 6, 11, 12)
qr(x, 2, 7, 8, 13)
qr(x, 3, 4, 9, 14)
return [(a+b) % 2**32 for a, b in zip(x, inp)]
def buffer_to_state(buffer):
buffer_bytes = bytes.fromhex(buffer)
output = []
for i in range(0, len(buffer_bytes), 4):
output.append(bytes_to_long(buffer_bytes[i:i+4]))
return output
def find_flag(initial_state, encrypted_flag):
buffer = b""
state = chacha_block(initial_state) # we have to start with this since we already used the first state with our initial input
flag_bytes = bytes.fromhex(encrypted_flag)
flag_length = len(flag_bytes)
output = []
for i in range(flag_length):
if len(buffer) == 0:
buffer = b"".join(long_to_bytes(x).rjust(4, b"\x00") for x in state)
state = chacha_block(state)
output.append(chr(flag_bytes[i] ^ buffer[0]))
buffer = buffer[1:]
return "".join(output)
def get_tube():
p = None
lines_to_skip = 5
if RUN_LOCALLY:
p = process(['python3', 'chal.py'])
lines_to_skip = 4
else:
p = remote('babycha.chal.irisc.tf', 10100)
for _ in range(lines_to_skip):
p.recvline()
return p
def get_buffer0(p):
p.sendline(b'1')
p.recvline()
p.sendline(b'\x00'*64)
return p.recvline()[4:-1].decode()
def get_encrypted_flag(p):
p.sendline(b'2')
return p.recvline()[2:-1].decode()
if __name__ == "__main__":
p = get_tube()
buffer0 = get_buffer0(p)
initial_state = buffer_to_state(buffer0)
encrypted_flag = get_encrypted_flag(p)
print(find_flag(initial_state, encrypted_flag))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment