Description
Can you conjure the right bytes? Download app.py and recover the exact input the server expects.
Setup
cat app.pySolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Read the source code
ObservationThe challenge asks for the exact input the server expects and hands you app.py. The value is hardcoded in there, so read it.Open app.py. The check is literallyif user_input == "\x65"*1751:, so 1751 isn't arbitrary, it's the source. ASCII 101 ='e'. See Python for CTF for payload-shaping idioms.bashcat app.pybashgrep -n 'user_input ==' app.py # confirms "\x65" * 1751pythonpython3 -c 'print(len("e"*1751))' # sanity: 1751Expected output
11: if user_input == "\x65"*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 wants 1751 characters, not three or any other small number. A shorter string gets an 'Incorrect' and a closed connection. The count is right there in the source, so there is nothing to guess.
Tried: Interpret 'ASCII 101' as the repetition count and send 'e' 101 times.
101 is the code point for the letter e, not how many times to repeat it. The character comes from the code, the count comes from the expected variable, and those are 101 and 1751 respectively.
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 -cflag 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.Step 2Send the payload
ObservationThe expected value is the letter e repeated 1751 times, far too long to type. Generate it with a Python one-liner and pipe it to netcat.Generate 1751es and send. Note thes.recv(512)in the Python form is not optional, it consumes the prompt banner so the next read aligns. See netcat for CTF.pythonpython3 -c "print('e' * 1751)" | nc <HOST> <PORT_FROM_INSTANCE>bash# Interactive variant - recv(512) syncs with the banner before sending:pythonpython3 -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 reads that as a literal string, not a multiplication, so six characters go out instead of 1751 and the server rejects them immediately. Let Python do the multiplication and pipe its output into netcat.
Tried: Omit the trailing newline by using sys.stdout.write instead of print when piping to nc.
The server's input() call returns only once it sees a newline or the connection closes. Without a newline, whether you get an answer comes down to whether your netcat closes the socket at EOF, so the run either hangs or looks like a silent rejection. print() adds the newline for you; writing bytes directly does not.
Learn more
The two approaches shown - piping through nc vs. using Python's
socketmodule - 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 tosocket.socket(AF_INET, SOCK_STREAM)followed by.connect(). For CTF use, pwntools'remote(host, port)is even more convenient and adds methods likerecvuntil(),sendline(), andinteractive().A subtle detail: the server reads input until a newline and then compares. Adding
b'\n'(or usingprint()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{h0w_m4ny_e's???_...}
app.py asks for ASCII decimal 101 × 1751, no spaces. Send the string 'e' repeated 1751 times.