Description
Can you conjure the right bytes? Download app.py and recover the exact input the server expects.
Setup
Download and read app.py.
Launch the challenge instance and connect via netcat.
cat app.pySolution
Walk me through it- Step 1Read the source codeDownload app.py. It reads via sys.stdin.buffer (raw bytes) and checks that the input equals b'\xff\xff\xff' (hex byte 0xFF, three times, no space). The key difference from bytemancy-0/1 is that it reads raw binary, not text, so you must send literal byte 0xFF, not the string 'ff'.bash
cat app.pyLearn more
The critical distinction here is between text mode and binary mode I/O. Python's
sys.stdinis a text stream that decodes bytes to Unicode strings using the terminal encoding (usually UTF-8).sys.stdin.bufferis the underlying binary stream - it gives you raw bytes without any Unicode decoding. A server usingsys.stdin.buffer.read()compares raw bytes, so you must send actual byte values, not their text representations.Byte 0xFF (255 decimal) is the highest possible byte value. It is not a valid UTF-8 byte on its own (UTF-8 uses 0xFF only in specific multi-byte sequences) and is not printable ASCII. Terminals typically cannot type or display it directly, which is why you need either
printfwith octal/hex escapes or a Python socket that sendsb'\xff'as a raw byte.printf '\xff\xff\xff\n'in bash interprets\xffas a hex escape and outputs the literal byte 0xFF. This is different fromecho '\xff', which on most shells outputs the six characters backslash, x, f, f (text) rather than the binary byte. Understanding this shell behavior is essential for binary exploitation work where you need to inject exact byte sequences. - Step 2Send the raw bytesSend three raw 0xFF bytes plus a newline. Try the text form first; if the server rejects it, switch to raw bytes.
printf '\xff\xff\xff\n'works in bash but not allshimplementations, so prefer the Python socket form for portability. See Python for CTF.bash# bash only - dash/busybox printf may not honor \x escapes:bashprintf '\xff\xff\xff\n' | nc <HOST> <PORT_FROM_INSTANCE>bash# Portable Python form, with try/except. Server-side close mid-handshake is common:pythonpython3 - <<'PY' import socket try: s = socket.create_connection(('<HOST>', <PORT_FROM_INSTANCE>)) s.recv(512) s.sendall(b'\xff\xff\xff\n') print(s.recv(2048).decode(errors='replace')) except (BrokenPipeError, ConnectionResetError) as e: print('server closed:', e) PYLearn more
Python byte literals (
b'\xff') let you specify exact byte values using hex escapes. The bytes object is a sequence of integers 0-255 - completely independent of any character encoding. When you callsocket.sendall(b'\xff\xff\xff\n'), Python sends four bytes to the server: 255, 255, 255, 10 (the newline is byte 10 in ASCII).This challenge teaches the concept of raw binary protocol interaction, which is essential for network binary exploitation. Tools like pwntools are designed specifically for this:
p.sendline(b'\xff\xff\xff')sends the bytes plus a newline, andp.recv()reads raw bytes back. You never need to worry about encoding layers because pwntools stays in binary mode throughout.The progression from bytemancy-0 (printable ASCII) to bytemancy-2 (raw non-printable bytes) mirrors real exploit development: shellcode and ROP gadget addresses contain arbitrary byte values, many of which are non-printable. Mastering raw byte I/O is a prerequisite for buffer overflow and format string exploitation.
Flag
picoCTF{byt3m4ncy_2_...}
app.py reads raw bytes via sys.stdin.buffer and expects the three literal bytes 0xFF 0xFF 0xFF. Use printf '\xff\xff\xff\n' | nc; sending the text string 'ff' will not work.