Fuzzing Vulnserver with Peach: Part 2


The vulnserver.exe server is a vulnerable server that was written specifically for fuzing purposes. Therefore the software intentionally contains vulnerabilities that we can exploit to gain control over the target operating system.

Peach is a fuzzer that is capable of performing both generation and mutation based fuzzing. It requires the Peach PIT file, which is an XML file used for fuzzing. Peach contains the following Peach elements:

  • Data Model: defines the protocol or file format we want to fuzz.
  • State Model: used for controlling the flow of the fuzzing process.
  • Publisher: I/O interface that we can use to read data from a file/socket, write data to a file/socket, etc.
  • Mutators: takes an existing input test case and changes it a little bit to make it invalid.
  • Agents: the Peach process that needs to run on the target system, which is used to restart the fuzzed server if it crashes.
  • Monitors: are used to capture the network traffic, attaching a debugger to the target process, etc.
  • Logger: saves the crashes and input test cases into a file for later analysis.

To install Peach on Windows, we need to satisfy the dependencies below:

We also need to add the path to the windbg.exe, which is located in the C:/Program Files/Debugging Tools for Windows (x86) directory, to the system PATH.

To install Peach on Linux, we first need to install the dependencies:

# emerge twisted twisted-web 4suite pyasn1 wxpython zope-interface

The above command installs the dependencies on Gentoo Linux distribution, but you need to install the equivalents of the named packages on your own Linux distribution.

We also need to cd into the directory under peach/peach/ and install the additional dependencies that were not previously installed. We need to move into the directories 4Suite-XML, cDeepCopy, cPeach and vdebug (needs to be unzipped first) and run the commands below:

# python setup.py build --debug
# python setup.py install

This will install all the dependencies. Afterwards we can successfully run the Peach fuzzer.

Presenting the vulnserver.xml

Part of the input file into the Peach fuzzer is shown below. We must add that the file is by no means complete, because there is too much code to include into this article to still make it readable and clear. This is why we're presenting only the KSTET data model, state model, etc. If we would like to check out the whole vulnserver.xml we can check it out on the Google Code git repository accessible here. The vulnserver.xml is accessible under the peach/ directory in git repository. The partial vulnserver.xml is presented below:

<?xml version="1.0" encoding="utf-8"?>
<Peach version="1.0" author="Dejan Lukan">
  <Include ns="default" src="file:defaults.xml"/>

  <DataModel name="DataKSTET">
    <String value="KSTET " mutable="false" token="true"/>
    <String value=""/>
    <String value="\r\n" mutable="false" token="true"/>

  <StateModel name="StateKSTET" initialState="Initial">
    <State name="Initial">
      <Action type="input" ><DataModel ref="DataResponse"/></Action>
      <Action type="output"><DataModel ref="DataKSTET"/></Action>
      <Action type="input" ><DataModel ref="DataResponse"/></Action>

  <Agent name="Agent" location="">
    <Monitor name="VulnseverMonitorDebugger" class="debugger.WindowsDebugEngine">
      <Param name="CommandLine" value="C:\Documents and Settings\user\Desktop\vulnserver\vulnserver.exe"/>

  <Test name="TestKSTET">
    <Agent ref="Agent"/>
    <StateModel ref="StateKSTET"/>
    <Publisher class="tcp.Tcp">
      <Param name="host" value=""/>
      <Param name="port" value="9999"/>

  <Run name="DefaultRun">
    <Test ref="TestKSTET"/>
    <Logger class="logger.Filesystem">
      <Param name="path" value="/home/user/peach/vulnserver/"/>

Let's describe the input file a little bit. First we're defining a data model, which determines the way the Peach will generate the invalid input test cases and send them to the vulnserver for processing. The data model has a name DataKSTET and consists of a static string KSTET, followed by a space character, followed by an arbitrary string and terminating with a CRLF end of command. This effectively fuzzes the KSTET command, making various invalid input test cases that are sent to the vulnerable server for processing. An example of invalid KSTET input test cases would be the examples below:

KSTET 1111111111111111111111111111111111111111111111111111111111111111111111111111
KSTET \xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed

Afterwards we're defining a state model that has a name StateKSTET. It has one state named Initial state. The initialState parameter specifies the state to be called on each iteration of the fuzzing process. We can see that we're calling the only defined state named Initial. This state connects to the vulnerable server, accepts the welcome message, sends the fuzzed command (that is modeled with data model defined before) and reads the result of the command.

We also need the Agent that is used to specify the address of the vulnerable server. The location parameter contains the value, which means that the agent will be running on localhost on port 9000. The agent is a program that comes with each installation of Peach fuzzer and should be run on the target system. Its responsibility is to listen for incoming connections on default port 9000 and accept commands that need to be executed on the target system. When we start fuzzing with Peach, the Peach process connects to the agent program on localhost 9000 and instructs it what it needs to do. The basic functionality of the Peach agent is to start the vulnerable server in a debugger and monitor it while fuzzing. If the vulnerable server crashes during processing one test case, the Agent needs to restart the vulnerable server, so the Peach can continue fuzzing without manual intervention. Without the agent, we would have to connect to the target system and start the vulnerable server on each crash. This would make the fuzzing process inefficient since there would need to be much manual work done in a consistent timely fashion. It's way better if the agent can do this work for us.

We're also defining a Test element that specifies the state model to be used when fuzzing the KSTET command. It also states that Peach should connect to the vulnerable server on localhost on port 9999, where it needs to send invalid test use cases.

At the end, we're using the Run element to tell Peach which Test element it needs to use while fuzzing and we're also telling Peach in which directory it needs to save the input test cases that cause the vulnerable server to crash. In our case this directory is /home/user/peach/vulnserver/.

Fuzzing the vulnserver.exe

When we have our whole vulnserver.xml file, we can run the fuzzing process by issuing the command below:

# python peach.py vulnserver.xml

Before that we must start the agent on the target system with the command below:

# peach.bat -a

Presenting the Results

Peach found all six vulnerabilities present in the vulnerable server and it found them quite a lot of times. The table below states the command and its corresponding number of times Peach was able to crash the vulnserver.exe with the input test case:


We can see that Peach found the vulnerabilities KSTET and GTER many more times than other vulnerabilities. This is because even a quite small argument passed to the KSTET or GTER command crashes the vulnerable server. This means that all iterations, those that append small and those that append long arguments to the mentioned command will crash the vulnserver.exe. This is not true for the other commands where only the input test cases with overly long arguments cause the vulnerable server to crash.

If we take a look at the /home/user/peach/vulnserver/ we can find a status.txt text file containing all the status information about the fuzzing process and input test cases that caused a crash. But there's also a Faults/ directory that contains the following folders:


All the folders are named based on the specific class of crash that occurred while fuzzing. The above categories are:


The exploitable directory holds the test cases that discovered the vulnerabilities that are surely exploitable. The probably_exploitable holds the test cases that found the vulnerabilities that are probably exploitable, but can't determine if they can truly be exploited. The last class is unknown and holds all the test cases that can't be classified in the other two classes, because it can't be determined if they found a vulnerability or not. We must manually check those to determine if vulnerability was found.

Let's choose the EXPLOITABLE_WriteAV_0x0a49666d_0x0a614c6d/ directory and analyze the results a little further. The command below lists all the existing files in that directory.

# find EXPLOITABLE_WriteAV_0x0a49666d_0x0a614c6d/

There is an 1876/ directory that denotes the number of the input test case used to cause the crash. In that directory are the files. The first file is Agent_StackTrace.txt that holds the trace of the program when the crash occurred. The data_1_output_Named_107.txt contains the actual input test cases that were used to cause a crash. This file contains the output below:


This is the input test case that crashes the vulnerable server. We won't go into too much detail if this can be used to actually exploit the vulnerable server, because this is outside of this article.


We've seen that Peach can successfully find all the vulnerabilities in vulnerable server, which proves that fuzzing is a useful method of discovering security vulnerabilities.

In the next article we'll present how to fuzz the vulnerable server with Sulley fuzzer and compare the results of Sulley and Peach fuzzers.