Tuesday, January 14, 2014

Fuzzing Vulnserver with Peach 3

Vulnserver

Vulnserver is a purposely vulnerable application that is meant for practicing exploitation written by Stephan Bradshaw. It's basically a server that accepts TCP connections and takes in random input that will result in various buffer overflows and SEH overwrites. It's a pretty good way of learning how buffer overflows and SEH overwrites work in a manageable setting. There are also lots of good walkthroughs on how to achieve code execution on Bradshaw's blog and on Infosecinstitute. There's even a good walkthrough on fuzzing Vulnserver with Peach 2.x by Dejan Lukan. I probably wouldn't have even bothered with this posting if it wasn't for the fact that Peach 3.0 was a complete rewrite so some of the syntax in Lukan's example is a tad out of date. 

Peach

Peach is a fuzzer that supports generational and mutation based fuzzing. It uses XML files to determine the structure of the protocol you are trying to fuzz and how it should go about performing the actual fuzzing, i.e. make a network connection or output to a file. I've been meaning to practice fuzzing with a fuzzer like Peach or Spike. I ultimately settled on Peach because from the looks of it it has a more active support community so if I ran in to issues it could be easier to find answers. 

Setting Up

After downloading peach from here, downloading Vulnserver from here, netcat for Windows from here (with or without the -e option), and installing the Windbg for Windows 7 Standalong Debugging Tools (also for Windows XP) from here we are more or less ready to go. 

First we fire up a command prompt and execute vulnserver. By default it will listen on port 9999, but if you give it a port number it will listen on that instead. 


Next, we'll open up another command prompt and connect to it with netcat on port 9999 and poke around the application. Typing, 'HELP', we are presented with a list of commands that vulnserver supports. The exact meaning of these commands are not important. They are just there to provide different ways of supplying input that can crash the application.

If you go ahead and type a command and provide some input you should get a response back saying that the input was received fine. Here are a few examples of interaction with vulnserver:

So it appears that the general protocol used by vulnserver is: [command] [input] [newline]. This should be enough knowledge to start making a Peach Pit and start fuzzing vulnserver.

Peach Pit

Peach Pits have the general form of Data Models, followed by State Models, followed by Agents, followed by Tests.

Data Model

The Data Model describes the format of data that Peach can accept as input or that it should use when attempting to fuzz something. Fortunately our format is fairly simple with just a fixed command, a space, a string that is fuzzable, a carriage return character, and a new line character. More complex protocols may require you to have more fields, numbers and strings mixed, fields that are dependent on the size of other fields, etc. 
Something to note is that you can have multiple Data Models in a Peach Pit. Although in our case we will only focus on one command, you could have a Data Model for each command in vulnserver in your Peach Pit.

State Model

Next up we have the State Model. The State Model basically tells Peach how to behave so that it cooperates with the protocol is it trying to fuzz. The State Model will consist one or more States which are comprised of one or more Actions which lay out the exact steps that Peach should take when fuzzing. Does Peach need to accept output from a network connection before supplying input? Your actions will have to model that. Not only that, but if you are accepting output, you need to tell Peach what that output will look like in the form of a Data Model. If you are fuzzing a file format, you may have to have actions that tell Peach to open, write fuzzed data to, and close files. Again, fortunately for us vulnserver is pretty basic so our State Model will just consist of an input action to accept the initial welcome message, and output action to send our fuzzed data model, and another input action to receive the confirmation output from vulnserver if it hasn't crashed.

Agents

While fuzzing, run one of the things you will have to do is start Peach in agent mode. This agent will run the program that you are trying to fuzz and a debugger to monitor the program. It will also be responsible for detecting crashes and logging those instances. Agents can be a tricky thing to configure. 

Tests

Finally, there are Tests. A Test will kind of bring everything together and describe how you want your fuzzing run to proceed. Here you get to decide which Agent and State Model should be used. There also two other important things you determine in a Test as well. The Publisher tells Peach in what manner it will input and output with the program. Are we communicating via a file? TCP? UDP? You will specify that in a Publisher. The Logger is where you tell Peach to place the logs that it will generate.

HTER Example

Here is what a Peach Pit for the HTER command might look like (modified from Lukan's tutorial):
As a short run down here is a summary of what we have. First there is a Data Model named DataHTER which basically describes how to will send out HTER command to vulnserver. We will always send the string "HTER " (observe the space!), then a string which we will let Peach decide what that should be, followed by a carriage return and a new line.

Next, the StateHTER State Model says we will accept output from vulnserver that will look like the DataResponse Data Model (which we haven't defined yet!), send a DataHTER Data Model, and then accept more output that looks like a DataResponse Data Model.

Now we define the DataResponse DataModel. This is merely a string. Nothing fancy.

The Agent comes next. Here we indicate that Peach fuzzer will connect to the Peach Agent at 127.0.0.1 on TCP port 9001. We also say that the Monitor for this Agent will be a WindowsDebugger and we indicate that the command line program to run is vulnserver.exe and where it can be found. Then we tell the Monitor where it can find WinDbg.

Test is last and here we say that we want to use the Agent named "RemoteAgent", perform a test using the protocol described in the State Model named "StateHTER", that we should publish the fuzzed output using the TcpClient on IP address 127.0.0.1 at TCP port 9999. Finally we say that we should record the findings in a subfolder named "Logs".

Whew!

Fuzzing

Now comes the fun part. First we will fire up a Peach Agent and tell it to use the TCP channel. The Peach Agent will wait for instructions from a Peach fuzzer and ultimately be responsible for running vulnserver each and every time and detect if a crash occurred.

Next, the moment of truth, we will run Peach, pass in our Peach Pit, and the name of the test we want to run. 


Hopefully every once in a while you should see output from your Peach command shell that looks similar to this:

This is an indication that Peach sent a value that caused a crash. Peach should then save off the same input for you look at later. Peach can take a while to run through its test cases so you can feel free to stop Peach whenever you feel like or leave it running for as long as you care.

Examining the Output

Let's take a closer look at the input that caused the crash at iteration 171. From where you ran Peach, you should have a folder named Logs. Inside of that you should have a folder that was created from your run and inside of that you should have a folder named Faults. This folder will store the runs that caused a crash. One of the nice feature of Peach is that when it runs a program using WinDbg, it will automatically load a module from Microsoft, MSEC Debugger Extensions, that will make an attempt to determine if the crash is exploitable or not. MSEC is currently on 1.6 but Peach only comes with 1.0.6 so hopefully that will change in the future. 
We are in luck because in our Faults folder we see a folder named, EXPLOITABLE_0x264d5172_0x00000000. Opening up that folder we see yet another folder named after the iteration that caused the crash, 171. Inside the 171 folder there are several text files. Probably, the two most interesting ones in this cause will be WindowsDebugEngine_StackTrace.txt and action_2_Output_Unknown Action 2.txt. WindowsDebugEngine_StackTrace.txt is, not surprisingly, a stack trace of vulnserver at the time of the crash. It's worth it to take a look just to see what the state of the registers are to see if we could potentially have control over any of them. The other interesting file, action_2_Output_Unknown Action 2.txt, is what Peach sent to vulnserver. The output and action 2 part of the title correspond to the StateHTER State Model that we specified in TestHTER in our Peach Pit.

Now we know that sending HTER followed by 9,526 As will crash vulnserver in a potentially exploitable way. 

Hooray! 

Can we do better and turn this in to remote code execution? Maybe I'll write this up if there's interest in this, but there a bunch of tutorials that explain how to do this.

3 comments:

  1. Nice tutorial!

    Make more tutorials!

    pusheax
    http://blog.pusheax.com/ (Security Research)

    ReplyDelete
  2. Good article of Peach practice!!

    ReplyDelete
  3. I like your article.
    I am beginning to use Peach. I am trying to write a file fuzzer that *waits* for a trigger before starting to fuzz.
    The trigger is a UDP packet. Can you give me a sample pit file that does this?

    Thanks
    Joshua

    ReplyDelete