HackBlue

Tools · CTF categories for beginners · 14 / 18

Scripting CTF interactions in Python: talking to netcat services and solving math prompts

Automate challenges that require answering many prompts quickly by connecting with Python sockets, reading lines, parsing questions, and sending answers, tested against your own local service.

10 min read · practice only with authorization

Why script

Some challenges run a service you connect to with nc host port that asks hundreds of questions under a time limit, such as arithmetic or decoding tasks. Doing it by hand is impossible. A short script that reads a prompt, computes the answer, and sends it back is the expected solution.

Build a local practice service

Write your own small service so you can test without touching event infrastructure. This one asks 50 additions and prints a flag if all are correct within 10 seconds.

Snippet
cat > server.py <<'EOF'
import socketserver, random, time
class H(socketserver.StreamRequestHandler):
    def handle(self):
        start = time.time()
        for i in range(50):
            a, b = random.randint(1, 9999), random.randint(1, 9999)
            self.wfile.write(f'Q{i}: {a} + {b} = ?\n'.encode())
            if self.rfile.readline().strip() != str(a + b).encode() or time.time() - start > 10:
                self.wfile.write(b'wrong or too slow\n'); return
        self.wfile.write(b'flag{scripted_practice}\n')
socketserver.TCPServer.allow_reuse_address = True
socketserver.TCPServer(('127.0.0.1', 9001), H).serve_forever()
EOF
python3 server.py &

Lab: write the client

Connect with a socket, wrap it in a file object for line reading, parse each question with a regular expression, and send the answer. Run it against your local service and confirm you receive the flag. Then add a timeout and handle unexpected lines gracefully.

Snippet
import re, socket
s = socket.create_connection(('127.0.0.1', 9001), timeout=5)
f = s.makefile('rwb', buffering=0)
while True:
    line = f.readline().decode().strip()
    if not line:
        break
    print(line)
    m = re.search(r'(\d+) \+ (\d+)', line)
    if m:
        f.write(f'{int(m[1]) + int(m[2])}\n'.encode())
    elif 'flag{' in line or 'wrong' in line:
        break

Libraries

pwntools provides remote(), recvuntil(), and sendline() helpers that make these scripts shorter, and works against local processes too. Whichever you use, never evaluate server-provided text with eval, because a malicious service could send code; parse it explicitly instead.

Diagram

Scripted challenge loop

  1. Connect

    socket.create_connection to host and port.

  2. Read

    Read a line and print it for debugging.

  3. Parse and answer

    Regex out the values; compute; send.

  4. Stop

    Break on flag, error, or end of stream.

Check yourself

1. Where should you test a scripting solution first?

2. How should the client extract numbers from a prompt?

3. Why avoid eval on text received from a service?