cscg24-haunted

CSCG 2024 Challenge 'Haunted'
git clone https://git.sinitax.com/sinitax/cscg24-haunted
Log | Files | Refs | sfeed.txt

server.py (2846B)


      1import os
      2import selectors
      3import shutil
      4import signal
      5import socketserver
      6import subprocess
      7import tempfile
      8from os import fdopen
      9
     10TIMEOUT = 60 * 10  # timeout after ten minutes
     11
     12
     13class Handler(socketserver.BaseRequestHandler):
     14    def handle(self):
     15        self.request.sendall(
     16            f"[?] Please provide the boot disk in hex format.\n".encode()
     17        )
     18        self.request.sendall(f'[*] End your input with "EOF"\n'.encode())
     19
     20        buffer = b""
     21        while b"EOF" not in buffer:
     22            buffer += self.request.recv(1024)
     23        buffer = buffer.replace(b"EOF", b"").lower()
     24        try:
     25            buffer = bytes(list(filter(lambda x: chr(x) in "0123456789abcdef", buffer)))
     26
     27            data = bytes.fromhex(buffer.decode())
     28        except:
     29            self.request.sendall(f"[!] Invalid input... bye!\n".encode())
     30            return
     31
     32        fd, disk_path = tempfile.mkstemp()
     33        with fdopen(fd, "wb") as f:
     34            f.write(data)
     35
     36        # make sure we use the fresh vars every time
     37        shutil.copy("OVMF_VARS.fd", "OVMF_VARS_CURRENT.fd")
     38        os.chmod("OVMF_VARS_CURRENT.fd", 0o660)
     39
     40        subprocess.call(
     41            ["sh", "-c", "kill -9 $(cat /tmp/qemu)"],
     42            stdin=subprocess.DEVNULL,
     43            stdout=self.request.fileno(),
     44            stderr=self.request.fileno(),
     45        )
     46
     47        cmd = [
     48            "/usr/bin/qemu-system-x86_64",
     49            "-pidfile", "/tmp/qemu",
     50            "-s", "-S",
     51            "-d", "int,in_asm",
     52            "-D", "/tmp/log",
     53            "-cpu",
     54            "max",
     55            "-machine",
     56            "q35",
     57            "-drive",
     58            "if=pflash,format=raw,readonly=on,unit=0,file=OVMF_CODE.fd",
     59            "-drive",
     60            "if=pflash,format=raw,unit=1,file=OVMF_VARS_CURRENT.fd",
     61            "-drive",
     62            f"file={disk_path},if=none,id=disk1,format=raw",
     63            "-device",
     64            "ide-hd,drive=disk1,bootindex=1",
     65            "-monitor",
     66            "none",
     67            "-display",
     68            "none",
     69            "-nographic",
     70        ]
     71
     72        self.request.sendall(f"[*] Starting qemu, good luck!\n".encode())
     73
     74        # signal.signal(
     75        #     signal.SIGALRM,
     76        #     lambda _n, _f: [self.request.sendall(b"[!] Timed out..\n"), exit(1)],
     77        # )
     78        #signal.alarm(TIMEOUT)
     79        subprocess.call(
     80            cmd,
     81            stdin=subprocess.DEVNULL,
     82            stdout=self.request.fileno(),
     83            stderr=self.request.fileno(),
     84        )
     85
     86
     87with socketserver.ForkingTCPServer(("0.0.0.0", 1024), Handler) as server:
     88    server.allow_reuse_address = True
     89    with selectors.PollSelector() as selector:
     90        selector.register(server, selectors.EVENT_READ)
     91        while True:
     92            ready = selector.select(0.5)
     93            if ready:
     94                server._handle_request_noblock()