cscg24-adventure

CSCG 2024 Challenge 'Choose Your Own Adventure'
git clone https://git.sinitax.com/sinitax/cscg24-adventure
Log | Files | Refs | sfeed.txt

solve (2922B)


      1#!/usr/bin/env python3
      2
      3from pwn import *
      4from hashlib import md5
      5from ctypes import CDLL
      6
      7import subprocess
      8import sys
      9
     10# context.log_level = "DEBUG"
     11
     12args = sys.argv[1:]
     13if args == []:
     14    args = ["nc", "localhost", "1024"]
     15
     16libc = CDLL("libc.so.6")
     17
     18def connect():
     19    io = process(args)
     20    io.readuntil(b"After ")
     21    leak = int(io.readline().split()[0])
     22
     23    flips = ""
     24    for _ in range(5):
     25        io.sendline(b"H")
     26        io.readuntil(b"The coin lands on ")
     27        flips += io.readline().decode()[0]
     28
     29    return io, leak, flips
     30
     31def gen_key(seed, flips):
     32    libc.srand(seed)
     33    libc.rand()
     34    for _ in flips:
     35        libc.rand()
     36    key = flips
     37    value = libc.rand() & 0x7fff
     38    for _ in range(32):
     39        concat = (key + str(value) + "\n").encode()
     40        key = md5(concat).hexdigest() + "  -"
     41    return key
     42
     43def test_seed(seed, leak, flips):
     44    libc.srand(seed)
     45    value = libc.rand() & 0x7fff
     46    if value != leak:
     47        return False
     48    nflips = ""
     49    for _ in flips:
     50        value = libc.rand() & 0x7fff
     51        nflips += 'H' if value % 2 == 1 else 'T'
     52    return flips == nflips
     53
     54def main():
     55    while True:
     56        io, _, _ = connect()
     57        io.sendline(b"P")
     58        io.sendline(b"H")
     59        io.readuntil(b"The coin lands on")
     60        io.readline()
     61        if b"Fortune smiles upon you" in io.readline():
     62            io.readuntil(b"light is the flag part:")
     63            flag_suffix = io.readline().split(b"'")[1].decode()
     64            io.close()
     65            break
     66        io.close()
     67
     68    while True:
     69        timestamp = int(time.time())
     70        io, leak, flips = connect()
     71        io.sendline(b"O")
     72        io.sendline(b"H")
     73        io.readuntil(b"The coin lands on ")
     74        flips += io.readline().decode()[0]
     75        if b"Fortune smiles upon you" in io.readline():
     76            io.readuntil(b"cipher:\n")
     77            flag_prefix_enc = b""
     78            while True:
     79                line = io.readline()
     80                if b"  " not in line:
     81                    break
     82                print(line)
     83                parts = line.decode().split("  ")
     84                hexline = (parts[1] + parts[2]).replace(" ", "")
     85                flag_prefix_enc += bytes.fromhex(hexline)
     86            print(flag_prefix_enc)
     87            io.close()
     88            break
     89        io.close()
     90
     91    flag_prefix = None
     92    for offset in range(-2000000, 2000001):
     93        seed = timestamp + offset
     94        if test_seed(seed, leak, flips):
     95            key = gen_key(seed, flips)
     96            cmd = ["openssl", "enc", "-aes-256-cbc",
     97                   "-d", "-pass", f"pass:{key}"]
     98            out = subprocess.run(cmd, stdout=subprocess.PIPE,
     99                    input=flag_prefix_enc).stdout
    100            print(out)
    101            if b"CSCG" in out:
    102                flag_prefix = out.decode().strip()
    103                break
    104    assert(flag_prefix)
    105
    106    print(flag_prefix + flag_suffix)
    107
    108if __name__ == "__main__":
    109    main()