How Peach Fuzzer Works (Execution Flow)

  • No guess work
  • Mutates the researcher provided structured inputs systematically
  • Maintains protocol validity while breaking logic assumptions

Setup Diagram

None
Image created by Author

DockerFile

FROM ubuntu:18.04

ENV DEBIAN_FRONTEND=noninteractive

# Update and install tools in one layer to save space
RUN apt-get update && apt-get install -y \
    python2.7 \
    mono-runtime \
    nano \
    wget \
    unzip \
    && rm -rf /var/lib/apt/lists/*

# Fix the python shortcut
RUN ln -sf /usr/bin/python2.7 /usr/bin/python

WORKDIR /work
CMD ["/bin/bash"]
None
None
docker run -it --name peach-workshop peachfuzzer /bin/bash
None
None

Lab 1 | Vulnerable TCP Service

  • The Python script represents a intentionally vulnerable network service.
  • Simulate a custom protocol using a length-prefixed message.
  • Provide a realistic fuzzing target without crashing the OS

💣 Root Cause: The service trusts user-supplied length values

fuzz_lab1.py

import socket

HOST = "127.0.0.1"
PORT = 9001

def read_line(conn):
    data = b""
    while not data.endswith(b"\n"):
        chunk = conn.recv(1)
        if not chunk:
            break
        data += chunk
    return data

def handle(conn):
    try:
        # Read ASCII length line safely
        length_line = read_line(conn).strip()
        declared_len = int(length_line)

        # Read payload (up to declared length)
        data = b""
        while len(data) < declared_len:
            chunk = conn.recv(declared_len - len(data))
            if not chunk:
                break
            data += chunk

        # Logic bug (intentional)
        if len(data) != declared_len:
            print("[!] Logic error triggered!")
            print(f"Declared={declared_len}, Actual={len(data)}")

        # Dangerous allocation (intentional)
        buffer = bytearray(declared_len)
        buffer[:len(data)] = data

        conn.send(b"OK\n")

    except Exception as e:
        print(f"[!] Crash / exception: {e}")

    finally:
        conn.close()

s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(5)

print("[+] Listening on 127.0.0.1:9001")

while True:
    conn, addr = s.accept()
    handle(conn)
  • Unbounded length trust : declared_lenhas no validation
  • Logic flaw: Program continues execution even when len(data) != declared_len
  • Malformed length + payload can break protocol assumptions.
  • recv(1) in read_line() allows slow client to hold connection indefinitely.
  • Connections can remain open forever, exhausting file descriptors.
  • Any local client can interact with the service.

📥 Download Peach Fuzzer

It's old and no longer maintained, so I am directly installing the binaries from sourceforget

None
cd /work
mkdir peach_fuzzer
cd peach_fuzzer
wget https://sourceforge.net/projects/peachfuzz/files/Peach/3.1/peach-3.1.124-linux-x86_64-release.zip/download
None
None

Verify it's working

peach_fuzzer/peach -h
None

Create the vulnerable server file and paste the code described above to simulate a test environment.

None
None
docker exec -it peach-workshop /bin/bash
None

What is .PIT file?

In this file, we instruct the peach fuzzer framework what to fuzz, how to fuzz and where to fuzz.

None
Image created by Author

fuzz_logic1.pit

<Peach>
  <DataModel name="LengthProtocol">
    <Block name="Request">

      <String name="Length" value="64" mutable="true" token="true">
        <Hint name="CharSet" value="0123456789"/>
      </String>

      <String name="Delimiter" value="\n"/>

      <Blob name="Payload" length="64" mutable="true"/>

    </Block>
  </DataModel>

  <StateModel name="OneShot" initialState="Send">
    <State name="Send">
      <Action type="output">
        <DataModel ref="LengthProtocol"/>
      </Action>
    </State>
  </StateModel>

  <Test name="Default">
    <StateModel ref="OneShot"/>
    <Publisher class="TcpClient">
      <Param name="Host" value="127.0.0.1"/>
      <Param name="Port" value="9001"/>
      <Param name="Timeout" value="2000"/>
    </Publisher>
  </Test>
</Peach>

Peach Fuzzer Execution

apt-get install -y mono-devel
peach_fuzzer/peach fuzz_logic1.pit
None
None
None

Every crash doesn't implies a valid vulnerability.

What a researcher does after collecting all crashes

Analyze the crash & identify the category of the crash root cause:

  • Logic error
  • Out-of-bounds read
  • Out-of-bounds write
  • Use-after-free
  • Integer overflow
  • Infinite loop / hang
  • Resource exhaustion
None

Fuzzing + crash analysis = how you find bugs Exploit development = how you turn them into 0-days

It's just the beginning 🤘

None
GIF from TENOR