bytemancy 1 picoCTF 2026 Solution

Published: March 20, 2026

Description

Can you conjure the right bytes? Download app.py and recover the exact input the server expects.

Download and read app.py to understand what byte sequence the server expects.

Launch the challenge instance and connect via netcat.

bash
cat app.py

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1
    Read the source code
    Observation
    I noticed the challenge description says to 'recover the exact input the server expects' and provides app.py as a download, which suggested the expected byte sequence is hardcoded in the source and reading it directly is the fastest way to find the exact value.
    Open app.py. The check is literally expected = 'e' * 1751, so 1751 isn't arbitrary, it's the source. ASCII 101 = 'e'. See Python for CTF for payload-shaping idioms.
    bash
    cat app.py
    bash
    grep 'expected' app.py   # confirms 'e' * 1751
    python
    python3 -c 'print(len("e"*1751))'  # sanity: 1751

    Expected output

    expected = 'e' * 1751
    1751
    What didn't work first

    Tried: Manually count from the bytemancy-0 pattern and guess 3 repetitions or another small number.

    The check in app.py is 'e' * 1751, not 3 or any other small count. Sending a shorter string causes the server to print 'Incorrect!' and close the connection. Reading the source with cat app.py and grep 'expected' reveals the exact count so guessing is never needed.

    Tried: Interpret 'ASCII 101' as the repetition count and send 'e' 101 times.

    ASCII 101 is the decimal code for the character 'e', not the repetition count. The character to repeat comes from the character code, but the number of times to repeat it is a separate value (1751) found in the expected variable. Running python3 -c 'print(len("e"*101))' and comparing to 1751 shows the mismatch.

    Learn more

    The step from 3 repetitions (bytemancy-0) to 1751 repetitions (bytemancy-1) is designed to rule out manual typing. You cannot reasonably type 1751 'e' characters by hand, so the challenge forces you to use a script or shell one-liner to generate the payload programmatically. This is a key lesson: automation is a core CTF skill.

    Python string multiplication ('e' * 1751) creates a string of exactly 1751 'e' characters in a single expression. The same works for byte strings: b'e' * 1751. This technique extends to generating padding bytes (b'\x00' * 64), creating cyclic patterns, and building exploit payloads where length matters precisely.

    The python3 -c flag runs a single Python expression from the command line, making it ideal for quick payload generation. Combined with shell pipes (|) and netcat, you get a complete one-liner exploit. For more complex interactions, pwntools' remote() class handles the full connection lifecycle including reading responses and sending multiple payloads.

  2. Step 2
    Send the payload
    Observation
    I noticed the source confirmed the expected value is 'e' * 1751, which is far too long to type manually and suggested using a Python one-liner piped to netcat to programmatically generate and send all 1751 characters in one shot.
    Generate 1751 es and send. Note the s.recv(512) in the Python form is not optional, it consumes the prompt banner so the next read aligns. See netcat for CTF.
    python
    python3 -c "print('e' * 1751)" | nc <HOST> <PORT_FROM_INSTANCE>
    bash
    # Interactive variant - recv(512) syncs with the banner before sending:
    python
    python3 -c "import socket; s=socket.create_connection(('<HOST>', <PORT_FROM_INSTANCE>)); s.recv(512); s.sendall(b'e'*1751 + b'\n'); print(s.recv(512).decode())"
    What didn't work first

    Tried: Type 'e' * 1751 literally into the netcat prompt by hand.

    The shell interprets 'e' * 1751 as a string literal, not Python multiplication, so you get the characters 'e', '*', '1', '7', '5', '1' - six characters instead of 1751. The server compares the received string against the 1751-character expected value and rejects it immediately. The pipe form python3 -c "print('e' * 1751)" | nc <HOST> <PORT> is required to let Python perform the multiplication before sending.

    Tried: Omit the trailing newline by using sys.stdout.write instead of print when piping to nc.

    The server reads input line by line and blocks until it sees a newline character. Without the newline, nc holds the connection open but the server never receives a complete line, so no comparison is made and the connection eventually times out. Python's print() appends a newline automatically; using sys.stdout.write or b'e'*1751 without b'\n' requires adding the newline explicitly.

    Learn more

    The two approaches shown - piping through nc vs. using Python's socket module - differ in interactivity. The pipe approach is fire-and-forget: it sends the payload and displays whatever the server returns, but cannot respond to multiple prompts. The socket approach reads the banner first, then sends the payload, then reads the response - giving full control of the conversation.

    The socket module is Python's low-level network interface. socket.create_connection() is a convenience wrapper that resolves the host, creates a TCP socket, and connects - equivalent to socket.socket(AF_INET, SOCK_STREAM) followed by .connect(). For CTF use, pwntools' remote(host, port) is even more convenient and adds methods like recvuntil(), sendline(), and interactive().

    A subtle detail: the server reads input until a newline and then compares. Adding b'\n' (or using print() which adds one automatically) is important - without it, the server may block forever waiting for the line terminator. This is a common gotcha when working with line-buffered servers.

Interactive tools
  • Base64 & Base32 DecoderDecode Base64 and Base32 strings with auto-detection. Multi-layer mode unwraps nested encodings automatically.
  • Recipe ChainStack decoders into a pipeline: Base64, hex, ROT, XOR, Morse, URL, Atbash, Vigenère, and more. Magic mode auto-discovers the chain. Bookmark the URL to save it.
  • Number Base ConverterConvert numbers between binary, octal, decimal, and hexadecimal instantly. Enter any value and see all four bases update in real time.

Flag

Reveal flag

picoCTF{byt3m4ncy_1_...}

app.py asks for ASCII decimal 101 × 1751, no spaces. Send the string 'e' repeated 1751 times.

Related reading

Want more picoCTF 2026 writeups?

Useful tools for General Skills

What to try next