EnglishFrenchGermanItalianPortugueseRussianSpanish


For the past several months I’ve been doing a fair amount of work with the Peach fuzzing framework. At times (many in fact), I’ve struggled with performing somewhat basic tasks with Peach but with a little perseverance and a lot of help (thanks Mike and Mikhail), I’ve been able to develop some fairly complete Peach templates. In an attempt to save those of you just beginning with Peach, I thought I’d put together a few short tutorials to help expose some of the more advanced features within the framework.

If this is your first time hearing of the Peach fuzzing framework, I invite you to take a look at the Peach project page.

I would also like to mention that this tutorial will be very similar to the one provided by Mike Eddington, on creating a Peach template for parsing WAV files. That document can be found here, at the Peach project page.

Getting Started

For this tutorial, we’ll be looking at the Zip file format. We’ll try and define a Peach template that covers as much functionality defined in the specification as possible. The latest Zip file format specification can be found here.

Before we begin, there are a few tools you’ll need to follow along with this tutorial.

  • Peach Fuzzing Framework
    • You must have the latest version of Peach to use the Pit included in this tutorial (rev. 2468 at the time of release). Several of the functions included in this tutorial will not work with the Peach installer. You can find the SVN information here.
  • 010 Binary Editor
    • The 010 Binary Editor utilizes binary templates for parsing a variety of file formats. Included in the base install is a template for the Zip file format. This will help us to debug our Pit as we progress. You can find this software here.


In order to instruct Peach on what we’d like to fuzz, we’ll begin by creating a Peach Pit, an XML based file that provides Peach with the structure of our data, how we’d like it fuzzed, and what application we’d like to target. A Peach Pit is comprised of 5 main sections:

Peach Structure

  • DataModel
    • The DataModel is the element within our pit that we’ll use to define the structure of our data. In this case, we’ll use the DataModel to provide Peach with the structure, layout, and functionality of the Zip file format. We also have the ability within the DataModel to inform Peach which elements we do and do not want to fuzz (fuzzable elements can also be defined in the Test block).
  • StateModel
    • The StateModel is responsible for managing the flow of data during the fuzz process.
  • Agents
    • The Agents are used for monitoring the behavior of an application during the fuzz process. This includes capturing data related to application state and any crashes that may be triggered during the fuzz process.
  • Test Block
    • The Test Block is responsible for correlating the configuration of the StateModel, Agents, and Publishers (responsible for managing the data generated by the DataModel) into a single test case.
  • Run Block
    • The Run Block is used for defining which tests will be executed during the fuzz process.. This block also manages logging of any data generated by the Agents during the fuzz process.


To begin, we’ll start by making a copy of the FileFuzzerGui.xml template located in C:\(Path-to-Peach-installation)\samples\FileFuzzerGui.xml and save it as zip.xml. Looking at this template we can see a very simple DataModel has already been defined which will simply generate the String “Hello World!” We’re going to remove that string and rename our DataModel to “Zip.” You should have something similar to the following:

	<DataModel name="Zip">

	</DataModel>

Within each DataModel, Peach allows several XML elements to define the structure and type of data we intend to generate or parse. I’ll go introduce each element needed to create our Zip file fuzzer as we need them. For now, let’s take a look at the file specification so that we can develop a plan for defining our Pit. Let’s scroll down to the section labeled “Overall .Zip file format.”

Looking at the file format we see that a Zip file is comprised of a number of sections beginning with a “Local File Header.” The Local File Header is followed by a “File Data” section which is in turn followed by another section called the “Data Descriptor.” It also appears that according to the specification, these three sections can occur multiple times, in this order, before we meet our next section, the “Archive Decryption Header”. Before we go any further, let’s see if we can create a rough definition for the first 3 sections.

Zip File Format

A. Local file header

Now when creating a file definition in Peach, several XML elements are available to us which allow us to structure our data and define the type of data to be handled or generated. Referencing the specification, we see that we’ll have multiple sections which represent an individual part of the Zip file format. It would be great if we had an XML element that would allows us to segment each section from the next. Luckily, we do. Peach defines a <Block> XML element which allows us to create groupings of data so that we can define specific instructions for that group or “block”. Each XML element as you might have guessed also has several parameters which can be assigned to that element. For our purposes, we’ll be using the following block parameters:

Block Parameters

  • name
    • The name parameter simply allows us to create a unique name for our block (and in fact, nearly all elements utilize the “name” parameter). This allows us to reference this name later when performing more advanced functions.
  • minOccurs
    • This parameter defines the minimum number of times our block should occur. Defining a minOccurs value of 0 will inform Peach that this block may be optional, and might not occur at all. Assigning a value of 10, as you would expect, informs Peach that we must use this block atleast 10 times.
  • maxOccurs
    • The maxOccurs parameter, much like minOccurs, defines the maximum number of times our block will appear. Using these two parameters are useful when we have an element that may occur more than once.



Now remember, when looking at the “Overall .Zip File Format” we noticed that each Zip file will begin with a Local File Header, File Data, and Data Descriptor sections (blocks) which may occur more than once (as a group). Let’s begin by creating a block within our Data Model to represent our Local File Header and inform Peach that this block must occur atleast once and may occur multiple times. For the purpose of this article, let’s define a maxOccurs of 1024 (although in all likelihood you will never reach this number unless your Zip file contains more than 1024 compressed files).

  <DataModel name="Zip">
    <Block name="LocalFileHeader" minOccurs="1" maxOccurs="1024">
    </Block>
  </DataModel>

Good. Now that we’ve created a block to hold our Local File Header, let’s go ahead and provide Peach with the structure of this section.

Looking at the specification we see that the Local File Header is compromised of 13 elements which we’ll need to define in our Pit. For this section, I’m going to discuss each element and what we’ll need to do to define it in Peach.

Basic Elements

Peach primarily uses 4 elements for representing data:

  • String
    • The <String> element is typically used to represent strings of text, or human readable data. If you recall from the FileFuzzerGui template, Peach defined a String element that would print out “Hello World!”. Strings are very flexible and can even be used to represent numbers using the <Hint> child-element, however the same fuzz logic (mutations) will not be applied had you used the <Number> element instead.
  • Number
    • As you would expect, the <Number> element is used to represent numerical data. The number element should be used any time we we expect a field to contain only numerical data. If we think that the field might contain alphanumerical data, a string might be better suited.
  • Flags
    • The <Flags> element is used to represent bit flags. It has a child element, “Flag” which is used to define each bit, or bit range in a bit flag.
  • Blob
    • The <Blob> element can be thought of as our last resort. Blobs are typically used to represent binary data that we lack proper definition for.



Further information on these and other Peach elements can be found here at the Peach project page.

Now back to our spec. Our first element, the local file header signature, is a 4 byte field which will always contain the hex value, 0x04034b50. In ASCII, this appears as “PK..” which is a magic number reference to Phil Katz, creator of the Zip File format and owner of PKWare. Let’s go ahead and create a definition for this inside our “LocalFileHeader” block. We know that this field is alpha-numeric, will contain the hex value “0x04034b50″, and will also be used to signify the start of the Local File Header. Knowing this, we can go ahead and use the string element to define this field.

***This element can easily be represented as a <Number> element, however for this tutorial we’ll use a <String> to demonstrate its use.

<String name="lfh_Signature" value="504b0304" valueType="hex" token="true" mutable="false">

So as with the block element, we’ve gone ahead and created a unique name for this element in the case we need to reference it later in our DataModel. We also see that we’ve defined 3 new parameters.

***It’s good practice to name all elements where possible.

String Parameters

  • value
    • This parameter tells Peach what value it should expect to see to match this field. Specifying a value also inherently provides Peach with a length for the string.
  • valueType
    • This parameter lets Peach know how to interpret our data. Had the Local File Header Signature been the word “Hello”, we could have entered this directly, ignoring the valueType parameter (or specified valueType=”string”). Since we defined a hex value, we would need to specify a hex valueType otherwise Peach will literally interpret this as the text string 504b0304.
  • Token
    • This parameter informs Peach that this string must exist and that Peach will need to identify it before continuing with the rest of the block. If a match doesn’t occur, Peach will move on to the next block in our DataModel.
  • mutable
    • This parameter tells Peach whether or not to fuzz this field. By setting this parameter to false, we instruct Peach not to modify this field directly, however this does not mean that this data will not be overwritten by neighboring fuzzed fields. In this example, we’ve chosen to mark this field as immutable because most Zip Applications will automatically discard files with corrupted signatures.



Hopefully that’s not too confusing. Let’s go ahead and take a look at our next field, “Version Needed to Extract”. We don’t have a great deal of information on this field except that it is 2 bytes in length. Looking at section J, “Explanation of Fields”, we see that this field will contain numerical data to represent the version number. Although the specification displays this field value as a decimal, it is actually represented as a whole number (2.0 == 20). So knowing this, let’s see if we can’t define this field in our Pit. We’ll place it in the Local File Header block directly below our signature.

<Number name="lfh_Ver" size="16" endian="little" signed="false"/>

Ok, well we see once again that we’ve provided a unique name for this element but we’ve also added 3 new parameters. Let’s briefly discuss these new parameters.

Number Parameters

  • size
    • The size parameter, as you might have guessed defines the size of our element. When using the Number element, sizes are defined in bits rather than bytes just as you would in most programming languages (think Byte, Word, DWord, QWord).
  • endian
    • The endian parameter defines the byte-order of our number. This parameter is somewhat unnecessary in our case as Peach automatically defaults to little endian.
  • signed
    • This parameter determines the signedness (signed or unsigned) of our number. If this option is not specified, Peach defaults to true.



Excellent. Let’s continue on by looking at the third field, the “general purpose bit flag.” As we discussed earlier, the Flag element can be used to represent bit flag data. Looking at this section of the spec, we don’t have a great deal of information about this bit flag, but enough to get us started. Let’s go ahead and create a 2 byte bit flag.

<Flags name="lfh_BitFlag" size="16" endian="little" signed="false">
</Flags>

You may have noticed that as with our number element, bit flags define size in bits rather than bytes. We’ve also gone ahead and defined the byte-order and signedness of this flag.

As I mentioned before, the “Flags” element has a child element “Flag” used to represent each bit or bits in a bit-flag. We still don’t have enough information to map out these bits just yet so let’s go ahead and return to section J in our specification and find the definition for “General Purpose Bit Flag.”

Looking at this part of the spec, we see that each individual bit flag (0-15) represents an option within the file spec. For now, we’re not going to concern ourselves with the purpose of each flag. Rather, we’ll begin by creating a each flag, assigning it a unique name, and defining it’s position and length in the bit-stream. Don’t forget to place the “Flag” elements inside our “Flags” element.

	<Flags name="lfh_BitFlag" size="16" endian="little" signed="false">
		<Flag name="lfh_bf_Encrypted" size="1" position="0"/>
		<Flag name="lfh_bf_CompMethod1" size="1" position="1"/>
		<Flag name="lfh_bf_CompMethod2" size="1" position="2"/>
		<Flag name="lfh_bf_Zeroed" size="1" position="3"/>
		<Flag name="lfh_bf_Deflate" size="1" position="4"/>
		<Flag name="lfh_bf_Patched" size="1" position="5"/>
		<Flag name="lfh_bf_Strong" size="1" position="6"/>
		<Flag name="lfh_bf_Unused1" size="1" position="7"/>
		<Flag name="lfh_bf_Unused2" size="1" position="8"/>
		<Flag name="lfh_bf_Unused3" size="1" position="9"/>
		<Flag name="lfh_bf_Unused4" size="1" position="10"/>
		<Flag name="lfh_bf_Efs" size="1" position="11"/>
		<Flag name="lfh_bf_Reserved1" size="1" position="12"/>
		<Flag name="lfh_bf_Enc_CD" size="1" position="13"/>
		<Flag name="lfh_bf_Reserved2" size="1" position="14"/>
		<Flag name="lfh_bf_Reserved3" size="1" position="15"/>
	</Flags>

So you can see here that we’ve defined our 16 bit flags, each with a length of 1 representing a single bit. Hopefully this isn’t too confusing.

Now with that out of the way, let’s go back to the Local File Header and move on to our next field, the “compression method”. As with the “version needed to extract” field, we simply need to create a 2 byte numerical field. We can determine it’s a number by looking at it’s definition in Section J.

	<Number name="lfh_CompMethod" size="16" endian="little" signed="false"/>

Good. Moving right along. Let’s take care of our next two fields, “last mod file time” and “last mod file date.” Again, we can use a number element to represent these fields.

	<Number name="lfh_LastModTime" size="16" endian="little" signed="false"/>
	<Number name="lfh_LastModDate" size="16" endian="little" signed="false"/>

By now you should already be able to determine why the number element was suitable for representing these fields. Our next field, CRC-32, will contain just that, the CRC-32 checksum of our compressed data. Now in this example we won’t be doing anything special with this field however it is worth noting that Peach, with the use of a FixUp element is capable of performing CRC-32 checks against referenced data. However due to complexities in the Zip file format, this solution is not so straight forward and is out of the scope of this article. I plan on writing a follow-up article to address just this, but for the time being, let’s go ahead and create this element and tell Peach not to fuzz it.

	<Number name="lfh_CRC32" size="32" endian="little" signed="false" mutable="false"/>

With that out of the way, let’s continue by defining our next 4 fields, “compressed size”, “uncompressed size”, “file name length”, and “extra field length”.

	<Number name="lfh_CompSize" size="32" endian="little" signed="false"/>
	<Number name="lfh_DecompSize" size="32" endian="little" signed="false"/>
	<Number name="lfh_FileNameLen" size="16" endian="little" signed="false"/>
	<Number name="lfh_ExtraFldLen" size="16" endian="little" signed="false"/>

As with our previous fields we’ve chosen the number element, defined a size, and marked these fields as little endian and unsigned.

Now looking at our next two elements we have a bit of a problem. Neither field has a value or length which makes it very difficult for Peach to determine where the field begins or ends. Looking back at our previous 4 elements we see that lfh_FileNameLen and lfh_ExtraFldLen will provide the length of these fields, but how will we tell Peach to look at these two fields when determining the size of “file name” and “extra field”?

Size Relations

Relations are one of Peach’s most powerful features. In this case, we can go ahead and use a size relation to inform Peach that the size of “File Name” is located in “lfh_FileNameLen”. Additionally, this relation will work both ways so that when we begin fuzzing, if the amount of data in “File Name” increases, Peach will update lfh_FileNameLen to contain the correct value (or not depending on the fuzz strategy).

Size Relation Parameters

  • type
    • Type obviously will define the type of relation to use. In this article, we’ll only discuss “size” and “when” relations.
  • of
    • The “of” parameter specifies which element to reference in this relation.



Before we can go ahead and apply our relation, let’s go ahead and define two elements for our file name and extra field.

	<String name="lfh_FileName"/>
	<String name="lfh_FldName"/>

Ok, now that we’ve created our fields let’s apply the size relation.

	<Number name="lfh_CompSize" size="32" endian="little" signed="false"/>
	<Number name="lfh_DecompSize" size="32" endian="little" signed="false"/>
	<Number name="lfh_FileNameLen" size="16" endian="little" signed="false">
		<Relation type="size" of="lfh_FileName"/>
	</Number>
	<Number name="lfh_ExtraFldLen" size="16" endian="little" signed="false">
		<Relation type="size" of="lfh_FldName"/>
	</Number>
	<String name="lfh_FileName"/>
	<String name="lfh_ExtraField"/>

As you can see we’ve instructed Peach that whenever it parses the lfh_FileNameLen and lfh_ExtraFldLen fields, to store this data and apply it as the size for lfh_FileName and lfh_FldName.

Let’s go ahead and move on to our next section.

B. File data

Looking at the next section in the Zip specification, we see a single field, “File Data”, which is intended to hold the compressed data for this Local File Header. Now unfortunately we can’t just go ahead and add a blank element in Peach without defining a size (or value) unless the element is followed by an element with a supplied value and marked as a token. So to help us, we’re going to use the size-relation we learned about earlier. Looking at the LFH header we see a field named “Compressed Size” or lfh_CompSize in our Pit. We’re going to assume that this defines the size of “File Data.”

(To verify we can always fire-up the 010 Binary Editor and run the Zip template.)

Now since we can expect compressed data for this field, a number or string element won’t be suitable to represent this field. Let’s go ahead and use our fall-back, the blob element.

<Blob name="lfh_CompData" mutable="false"/>

Now, as I mentioned earlier, Peach provides some advanced features for performing additional operations on our data (remember our CRC-32 Fixup?). Peach also has an additional feature, “transformers,” which allows us, in two directions, to perform operations against our data. In this case, we could use the “Compress” transformer to decompress this field, fuzz our data, and re-compress it. However as with the CRC-32 Fixup, this feature will be discussed in the follow-up article. Because of this, we’ve also marked this element as immutable.

Now, looking at the definition for Section B, we see that this block will immediately follow the LocalFileHeader. A combination of Local File Header, File Data, and our next block Data Descriptor, will repeat (as a group) for every file in the archive. Since we’ve already marked the LocalFileHeader to repeat (using maxOccurs), let’s go ahead and include section B (and Section C shortly) within the same block as our LocalFileHeader.

It should look something like this.

<!--  A.  Local file header -->
  <Block name="LocalFileHeader">
    <String name="lfh_Signature" valueType="hex" value="504b0304" token="true" mutable="false"/>
    <Number name="lfh_Ver" size="16" endian="little" signed="false"/>
    ...
    [truncated for space]
    ...
    <Number name="lfh_CompSize" size="32" endian="little" signed="false">
      <Relation type="size" of="lfh_CompData"/>
    </Number>
    <Number name="lfh_DecompSize" size="32" endian="little" signed="false"/>
    <Number name="lfh_FileNameLen" size="16" endian="little" signed="false">
      <Relation type="size" of="lfh_FileName"/>
    </Number>
    <Number name="lfh_ExtraFldLen" size="16" endian="little" signed="false">
      <Relation type="size" of="lfh_FldName"/>
    </Number>
    <String name="lfh_FileName"/>
    <String name="lfh_FldName"/>
    <!--  B.  File data -->
    <Blob name="lfh_CompData"/>
  </Block>


C. Data Descriptor

Ok good. Moving on. Section C describes the Data Descriptor block. Now before we move on there are several issues when building this block that aren’t immediately apparent when reading the specification. In fact I didn’t discover several hidden functions within the Zip file format until I had already completed my Pit and began testing it. In an attempt to save you time (and more than likely a lot of frustration), I’ll go ahead and detail some of the nuances of the Zip file format below in an easier to read format and we’ll then go ahead and create this block.

(These items are listed in order of readability and not necessarily the ordered in which they are defined in the specification.)

  • 1. The Data Descriptor block only exists if bit 3 of our general purpose bit-flag is set to yes (1).
  • 2. The Data Descriptor block may provide the size info for lfh_CompData.
  • 3. The Data Descriptor block may or may not begin with a block signature.
  • 4. The Data Descriptor block may use 8 byte values to describe the compressed and decompressed data sizes if the archive is in Zip64 format.

Ok, now that doesn’t seem like a lot but it will here in a bit. Let’s begin by building a basic representation of this block.

<!--  C.  Data descriptor -->
  <Block name="DataDescriptor">
    <Number name="dd_CRC32" size="32" endian="little" signed="false"/>
    <Number name="dd_CompSize" size="32" endian="little" signed="false"/>
    <Number name="dd_DecompSize" size="32" endian="little" signed="false"/>
  </Block>

Now, looking at item number 1, we see that this block will only occur if bit 3 of the general purpose bitflag is set to 1. Now we need to find some way to have Peach check bit 3 of our general purpose bitflag before we continue parsing beyond the File Data block.

When Relations

“When” Relations are useful for doing simple conditional statements. For example, in our specification, when lfh_BitFlag.lfh_bf_Zeroed is set to 1, the “Data Descriptor Block” will exist immediately after our compressed “File Data.” If this fields contain anything other than 1, this block will be removed.

When Relation Parameters

  • type
    • As with size relations, here we’ll be defining our relation type as “when.”
  • when
    • The “when” parameter allows us to define a python expression to determine whether or not the assigned element should be used.



So to implement this, we’ll do the following:

<!--  C.  Data descriptor -->
  <Block name="DataDescriptor">
    <Relation type="when" when="int(self.find('lfh_BitFlag.lfh_bf_Zeroed').defaultValue) == 1"/>
    <Number name="dd_CRC32" size="32" endian="little" signed="false"/>
    <Number name="dd_CompSize" size="32" endian="little" signed="false"/>
	  <Number name="dd_DecompSize" size="32" endian="little" signed="false"/>
	</Block>

In the code above you can see that we’ve defined a short conditional statement that means if lfh_BitFlag.lfh_bf_Zeroed equal 1, that this block will exist. Now with that out of the way we can tackle our second issue.

In some instances, when the Data Descriptor block exists, lfh_CompSize, our element responsible for providing the size information for lfh_CompData, may be set to 0. If this happens, our current size relation will fail and Peach will be unable to parse the rest of the Zip file. Luckily, if lfh_CompSize is set to 0, our size data will be provided by the dd_CompSize element within our Data Descriptor (a little bit more on this in a bit).

To handle either situation, we’ll go ahead and create two independent blocks for our file data; one which utilizes the “size” relation and another which doesn’t (sort of). Since our “size” relation is actually applied to lfh_CompSizeData, we’ll need to go ahead and update that “of” parameter to match our newly named file data element. We’ll also go ahead and add a “when” relation to each block so that Peach knows which one to select.

<!--  A.  Local file header -->
	<Number name="lfh_CompSize" size="32" endian="little" signed="false">
		<Relation type="size" of="lfh_CompSizeData"/>
	</Number>
	...
	[truncated for space]
	...
<!--  B.  File data -->
	<Block name="lfh_Data">
		<Block name="lfh_DataHasSize">
			<Relation type="when" when="int(self.find('lfh_CompSize').defaultValue) != 0"/>
			<Blob name="lfh_CompSizeData" mutable="false"/>
		</Block>
		<Block name="lfh_DataNoSize">
			<Relation type="when" when="int(self.find('lfh_CompSize').defaultValue) == 0"/>
			<Blob name="lfh_CompNoSizeData" mutable="false"/>
		</Block>
	</Block>

Ok, so now you can see that we have two blocks. Our first block begins with a “when” relation that states that this block should only exist if lfh_CompSize does not equal 0 (the exact opposite of our Data Descriptor block). We’ve also updated the element name for our file data element and made sure that our “size” relation matches this name.

Our second block also begins with a “when” relation, followed by an unsized blob element for our file data. Now, in doing so we’ve actually created a new issue for ourselves. If we look back to our list of requirements for the Data Descriptor block, specifically item #3, we see that the Data Descriptor block may or may not begin with a block signature. What does this mean to us? Well if we don’t have a block signature (more specifically, an item marked as a token), we won’t have anyway of telling Peach what to look for to signify the termination of lfh_CompNoSizeData, our unsized blob. In other words, Peach won’t be able to determine the size for this element, and will exit.

Now, what I’ve done is not necessarily a perfect solution. Based on what I’ve seen with the Zip files that I’ve sampled and parsed is that most (actually all that I’ve tested) do begin with a block signature. Because of this, I’ve chosen to go ahead and ignore item #3 and only create a definition for blocks which do contain a signature. Now this does mean that we will be excluding a small portion of the specification from our Pit, however I felt that this was an acceptable loss. If you are able to find an easier way around this I certainly welcome the solution!

Ok, with that said let’s go ahead modify our Data Descriptor block to include the block signature.

<!--  B.  File data -->
  <Block name="lfh_Data">
    <Block name="lfh_DataHasSize">
      <Relation type="when" when="int(self.find('lfh_CRC32').getInternalValue()) != 0 and int(self.find('lfh_CompSize').getInternalValue()) != 0 and int(self.find('lfh_DecompSize').getInternalValue()) != 0"/>
      <Blob name="lfh_CompSizeData" mutable="false"/>
    </Block>
    <Block name="lfh_DataNoSize">
      <Relation type="when" when="int(self.find('lfh_CRC32').getInternalValue()) == 0 and int(self.find('lfh_CompSize').getInternalValue()) == 0 and int(self.find('lfh_DecompSize').getInternalValue()) == 0"/>
      <Blob name="lfh_CompNoSizeData" mutable="false"/>
    </Block>
  </Block>
<!--  C.  Data descriptor -->
  <Block name="DataDescriptor">
    <Relation type="when" when="int(self.find('lfh_BitFlag.lfh_bf_Zeroed').defaultValue) == 1"/>
    <!-- Below is our newly added block signature -->
    <String name="dd_Sig" valueType="hex" value="504b0708" token="true" mutable="false"/>
    <Number name="dd_CRC32" size="32" endian="little" signed="false"/>
    <Number name="dd_CompSize" size="32" endian="little" signed="false"/>
    <Number name="dd_DecompSize" size="32" endian="little" signed="false"/>
  </Block>

With that done, let’s move on to item #4.

Item #4 states that the compressed and decompressed size elements within our Data Descriptor may be either 4 or 8 bytes depending on whether or not we’re working with a Zip64 archive. Luckily for us, Peach provides us with a mechanism to define several “choices” for determining the layout of our Data Descriptor.

Choice Element

Choice elements allow us to define a number of possible blocks (or individual elements) and instruct Peach that only one (or none — think minOccurs!) is valid. The Choice element tests each block from top down and will select the first block that matches the supplied data.

The Choice element accepts the same arguments as our Block elements (i.e. name, minOccurs, and maxOccurs).

So let’s go ahead and create our choice element and populate it with our two blocks to accommodate both 4 and 8 byte sizes. We’ll precede our choice element with our Data Descriptor Signature and CRC32 fields as these won’t change regardless of block selection. Our Choice structure should look like the following.

<!--  C.  Data descriptor -->
  <Block name="DataDescriptor">
    <Relation type="when" when="int(self.find('lfh_BitFlag.lfh_bf_Zeroed').defaultValue) == 1"/>
    <String name="dd_Sig" valueType="hex" value="504b0708" token="true" mutable="false"/>
    <Number name="dd_CRC32" size="32" endian="little" signed="false"/>
    <Choice name="dd_chooser">
      <Block name="dd_64">
        <Number name="dd_CompSize64" size="64" endian="little" signed="false"/>
        <Number name="dd_DecompSize64" size="64" endian="little" signed="false"/>
      </Block>
      <Block name="dd_32">
        <Number name="dd_CompSize32" size="32" endian="little" signed="false"/>
        <Number name="dd_DecompSize32" size="32" endian="little" signed="false"/>
      </Block>
    </Choice>
  </Block>

With the above section, Peach will now be able to parse the lfh_Data block because we’ve provided it with a token to look for signifying the end of that element. Unfortunately, we’ve introduced yet another issue into our fuzzer. Our current setup utilizes a choice element in order to provide Peach the capability to adapt in the event that the field sizes change between 4 and 8 bytes. However, with the way our fuzzer is currently configured, Peach would begin parsing the Zip64 field sizes first. Since we haven’t specified a value for either of these fields, Peach has no way of determining if the data it parses, is invalid. The worst case scenario would occur if the field sizes were actually 4 bytes, and Peach continues parsing on to our next block making it impossible for us to continue parsing beyond this block definition. To adjust for this, we need to define a way for Peach to determine that our Zip64 elements do not contain the next block header.

Constraints

Constraints allow us to define a Python expression, which if the outcome is true, will enable the element. If the outcome of our expression is false, Peach will disregard the element and exit the current routine. In the scenario we’ve created above, this will cause a false outcome to exit the current block and move onto our next choice.

So rather than defining an explicit expression which checks to see if any of our block signatures are present in the element, we’ll go ahead and check for the existence of PK, the first 2 bytes of all Zip block signatures. To do this, we’ll update the second element in our Zip64 block to look as follows:

<Number name="dd_DecompSize64" size="64" endian="little" signed="false" constraint="'4b50' not in hex(value)"/>

Good. Your final product should look as follows:

<!--  B.  File data -->
  <Block name="lfh_Data">
    <Block name="lfh_DataHasSize">
      <Relation type="when" when="int(self.find('lfh_CompSize').defaultValue) != 0"/>
      <Blob name="lfh_CompSizeData" mutable="false"/>
    </Block>
    <Block name="lfh_DataNoSize">
      <Relation type="when" when="int(self.find('lfh_CompSize').defaultValue) == 0"/>
      <Blob name="lfh_CompNoSizeData" mutable="false"/>
    </Block>
  </Block>
<!--  C.  Data descriptor -->
  <Block name="DataDescriptor">
    <Relation type="when" when="int(self.find('lfh_BitFlag.lfh_bf_Zeroed').defaultValue) == 1"/>
    <String name="dd_Sig" valueType="hex" value="504b0708" token="true" mutable="false"/>
    <Number name="dd_CRC32" size="32" endian="little" signed="false"/>
    <Choice name="dd_chooser">
      <Block name="dd_64">
        <Number name="dd_CompSize64" size="64" endian="little" signed="false"/>
        <Number name="dd_DecompSize64" size="64" endian="little" signed="false" constraint="'4b50' not in hex(value)"/>
      </Block>
      <Block name="dd_32">
    	<Number name="dd_CompSize32" size="32" endian="little" signed="false"/>
    	<Number name="dd_DecompSize32" size="32" endian="little" signed="false"/>
      </Block>
    </Choice>
  </Block>
</Block>

Wow, that was a lot of work for 30 lines of code. I recommend you take a deep breath and stare at a fixed object for the next 30 seconds before you loose consciousness…

D. Archive Decryption Header

All jokes aside, let’s continue on. Looking back at the specification we see our next section, the Archive Decryption Header. Unfortunately since the specification doesn’t provide any definition for this section, we’ll go ahead and skip it.

E. Archive Extra Data Record

Our next block, the “Archive Extra Data Record,” is a fairly simple block. It begins with a static 4 byte signature, followed by a static length field that provides the length of our next field. We’ll start by telling Peach to not fuzz our signature field, and we’ll use a size relation again to determine the size of our variable length field. This block should look similar to the following:

  <Block name="ArchiveExtraDataRecord" minOccurs="0" maxOccurs="1">
    <String name="aedr_Sig" valueType="hex" value="504b0608" token="true" mutable="false"/>
    <Number name="aedr_ExtFldLen" size="32" endian="little" signed="false"/>
    <Blob name="aedr_ExtFld"/>
  </Block>


F. Central Directory Structure

Looking at this portion of the specification, we can see that the Central Directory Structure is made up of an arbitrary number of file header blocks, followed up by a single “Digital Signature.” Knowing that, we can use the maxOccurs attribute on the block element to specify that this block may repeat up to n times. We’ll go ahead and set that to 1,024 just for safe measure, although in all likelihood we’ll never hit that threshold.

Further review of the Central Directory Structure reveals 19 static-length fields including 1 bit flag and 4 variable length fields (including both the file header and digital signature). Based on the field names we can determine the following size relations:

[File Header]
file name length(2) => file name
extra field length(2) => extra field
file comment length(2) => file comment

[Digital Signature]
size of data(2) => signature data

Based on what we’ve learned during the Local File Header, let’s go ahead and create one container block for the entire Central Directory Structure, and two sub-blocks, FileHeader and DigitalSignature. We’ll also go ahead and populate them with the data we see in the specification.

<Block name="CentralDirectoryStructure">
	<Block name="FileHeader" maxOccurs="1024">
		<String name="cfh_Signature" valueType="hex" value="504b0102" token="true" mutable="false"/>
		<Number name="cfh_Ver" size="16" endian="little" signed="false"/>
		<Number name="cfh_VerReq" size="16" endian="little" signed="false"/>
		<Flags name="cfh_BitFlag" size="16" endian="little" signed="false">
			<Flag name="cfh_bf_Encrypted" size="1" position="0"/>
			<Flag name="cfh_bf_CompMethod1" size="1" position="1"/>
			<Flag name="cfh_bf_CompMethod2" size="1" position="2"/>
			<Flag name="cfh_bf_Zeroed" size="1" position="3"/>
			<Flag name="cfh_bf_Deflate" size="1" position="4"/>
			<Flag name="cfh_bf_Patched" size="1" position="5"/>
			<Flag name="cfh_bf_Strong" size="1" position="6"/>
			<Flag name="cfh_bf_Unused1" size="1" position="7"/>
			<Flag name="cfh_bf_Unused2" size="1" position="8"/>
			<Flag name="cfh_bf_Unused3" size="1" position="9"/>
			<Flag name="cfh_bf_Unused4" size="1" position="10"/>
			<Flag name="cfh_bf_EFS" size="1" position="11"/>
			<Flag name="cfh_bf_Reserved1" size="1" position="12"/>
			<Flag name="cfh_bf_Enc_Cd" size="1" position="13"/>
			<Flag name="cfh_bf_Reserved2" size="1" position="14"/>
			<Flag name="cfh_bf_Reserved3" size="1" position="15"/>
		</Flags>
		<Number name="cfh_CompMethod" size="16" endian="little" signed="false"/>
		<Number name="cfh_LastModTime" size="16" endian="little" signed="false"/>
		<Number name="cfh_LastModDate" size="16" endian="little" signed="false"/>
		<Number name="cfh_CRC32" size="32" endian="little" signed="true" mutable="false"/>
		<Number name="cfh_CompSize" size="32" endian="little" signed="false"/>
		<Number name="cfh_CompSize" size="32" endian="little" signed="false"/>
		<Number name="cfh_DecompSize" size="32" endian="little" signed="false"/>
		<Number name="cfh_FileNameLen" size="16" endian="little" signed="false">
			<Relation type="size" of="cfh_FileName"/>
		</Number>
		<Number name="cfh_ExtraFldLen" size="16" endian="little" signed="false">
			<Relation type="size" of="cfh_FldName"/>
		</Number>
		<Number name="cfh_FileCommLen" size="16" endian="little" signed="false">
			<Relation type="size" of="cfh_FileComment"/>
		</Number>
		<Number name="cfh_DiskNumStart" size="16" endian="little" signed="false"/>
		<Number name="cfh_IntFileAttrib" size="16" endian="little" signed="false"/>
		<Number name="cfh_ExtFileAttrib" size="32" endian="little" signed="false"/>
		<Number name="cfh_RelOffsetLFH" size="32" endian="little" signed="false"/>
		<String name="cfh_FileName"/>
		<String name="cfh_FldName"/>
		<Blob name="cfh_FileComment"/>
	</Block>
	<Block name="CDSDigitalSignature">
		<String name="cdsds_Signature" valueType="hex" value="504b0505" token="true" mutable="false"/>
		<Number name="cdsds_DataSize" size="16" endian="little" signed="false">
			<Relation type="size" of="cdsds_Data"/>
		</Number>
		<Blob name="cdsds_Data" mutable="false"/>
	</Block>

Good. But before we move on there’s one more thing we’re going to add. If we were to open up an archive containing a single file, we’d notice that the file name element contained in our Local File Header will always match up with the file name element in our Central Directory structure. To make sure that this happens during the fuzz process, we’ll need to find a way to let Peach know that when the file name element of the Local File Header is mutated, to apply the same change to file name element residing in the Central Directory Structure.

Fixups

Fixups allow us to perform 1 way modifications of elements. Typically these are used in preparation for a transformer, but in the case described above we can use them to monitor our lfh_FileName and update our cfh_FileName accordingly.

Fixup Parameters

  • class

    • There really is only 1 universal Fixup parameter, and that’s “class”. This defines the actual Fixup we’ll be using. A full list of available Fixup’s can be found here.


So with that said, we’ll go ahead and make the following change. Don’t be to worried about understanding the syntax right now. I’ll be doing a follow up article on Fixups and how to create your own.

  <String name="cfh_FileName">
    <Fixup class="checksums.ExpressionFixup">
      <Param name="ref" value="lfh_FileName" />
      <Param name="expression" value="data" />
    </Fixup>
  </String>


G. Zip64 End of Central Directory Record

So hopefully by now, the Peach Pit format and the zip file structure are becoming a bit more familiar. Looking at the Zip64 end of central directory record we see 10 static length fields and one variable length field. Unlike our past examples however, we see that the size of this field is not explicitly defined in another field (well, not exactly). The specification notes that the number contained within the field, “size of zip64 end of central directory record”, specifies the size of our variable length data field as the following:

(Size of Zip64 End of Central Directory Record) – (All static length fields) – (12 (to include the size of itself (8 bytes) and the block signature (4 bytes)))

Using Peach there are a number of ways we can overcome this obstacle but our best may be the simplest. We’ll go ahead and wrap everything below the field “size of zip64 end of central directory record” including our variable length “zip64 extensible data sector” in another block. We can then go ahead and apply our standard size relation to the field “size of zip64 end of central directory record”, and reference our newly created block.

  <Block name="Zip64EndOfCentralDirectoryRecord">
    <String name="z64eocd_Signature" valueType="hex" value="504b0606" token="true" mutable="false"/>
    <Number name="z64eocd_SizeOfRecord" size="64" endian="little" signed="false">
      <Relation type="size" of="CentralDirectoryRecord"/>
    </Number>
    <Block name="CentralDirectoryRecord">
      <Number name="z64eocd_VerMadeBy" size="16" endian="little" signed="false"/>
      <Number name="z64eocd_VerNeeded" size="16" endian="little" signed="false"/>
      <Number name="z64eocd_ThisDiskNum" size="32" endian="little" signed="false"/>
      <Number name="z64eocd_SofCDDiskNum" size="32" endian="little" signed="false"/>
      <Number name="z64eocd_CDOnDisk" size="64" endian="little" signed="false"/>
      <Number name="z64eocd_TotNumEntries" size="64" endian="little" signed="false"/>
      <Number name="z64eocd_SizeOfCenDir" size="64" endian="little" signed="false"/>
      <Number name="z64eocd_OffsetToCenDir" size="64" endian="little" signed="false"/>
      <Number name="z64eocd_Z64ExtensDS" endian="little" signed="false"/>
    </Block>
  </Block>

How does this work? Well, by referencing a block with our size relation, Peach will define a static length for that block (the value contained within “size of zip64 end of central directory record”). For our example, let’s say that this number is 608 (this value will be in bytes). After Peach totals the sum of our static length fields (352 bits == 44 bytes), it’ll then subtract that from the overall block size (608 – 44 = 564). The result will be the size applied to our variable data field.

Before we move on, let’s see if we can’t add more detail to our variable data field. Looking back at the specification we see that this variable data field “may” retain special purpose data. The structure of this special purpose data is as follows:

  <Block name="z64eocd_Z64ExtensDS">
    <Number name="z64eocd_ExtensDs_Header" size="16" endian="little" signed="false"/>
    <Number name="z64eocd_ExtensDs_Size" size="32" endian="little" signed="false">
      <Relation type="size" of="z64eocd_ExtensDs_Data"/>
    </Number>
    <Blob name="z64eocd_ExtensDs_Data"/>
  </Block>

Further detail of this extra data block can be found in Appendix C of the specification. It may be worth adding, but for now, we’ll leave it as it is. So let’s go ahead and replace our extensible data sector with a block, and place the code above in our block.

  <Block name="Zip64EndOfCentralDirectoryRecord">
    <String name="z64eocd_Signature" valueType="hex" value="504b0606" token="true" mutable="false"/>
    <Number name="z64eocd_SizeOfRecord" size="64" endian="little" signed="false">
      <Relation type="size" of="CentralDirectoryRecord"/>
    </Number>
    <Block name="CentralDirectoryRecord">
      <Number name="z64eocd_VerMadeBy" size="16" endian="little" signed="false"/>
      <Number name="z64eocd_VerNeeded" size="16" endian="little" signed="false"/>
      <Number name="z64eocd_ThisDiskNum" size="32" endian="little" signed="false"/>
      <Number name="z64eocd_SofCDDiskNum" size="32" endian="little" signed="false"/>
      <Number name="z64eocd_CDOnDisk" size="64" endian="little" signed="false"/>
      <Number name="z64eocd_TotNumEntries" size="64" endian="little" signed="false"/>
      <Number name="z64eocd_SizeOfCenDir" size="64" endian="little" signed="false"/>
      <Number name="z64eocd_OffsetToCenDir" size="64" endian="little" signed="false"/>
      <Block name="z64eocd_Z64ExtensDS">
        <Number name="z64eocd_ExtensDs_Header" size="16" endian="little" signed="false"/>
        <Number name="z64eocd_ExtensDs_Size" size="32" endian="little" signed="false">
          <Relation type="size" of="z64eocd_ExtensDs_Data"/>
        </Number>
        <Blob name="z64eocd_ExtensDs_Data"/>
      </Block>
    </Block>
  </Block>

Before we move on, I’d like to make one additional change. We’re going to add a size relation to z64eocd_SizeOfCenDir and z64eocd_OffsetToCenDir. However, based on the structure of our Pit we can’t just add a standard size relation otherwise it’ll prevent us from properly parsing the Zip file. Instead, we’re going to add a parameter to our relation that will inform Peach that this will only get applied while Fuzzing and not during the initial parse. So let’s go ahead and make the following changes:

  <Number name="eocd_SizeOfCenDir" size="32" endian="little" signed="false">
    <Relation type="size" of="CentralDirectoryStructure" isOutputOnly="true"/>
  </Number>
  <Number name="eocd_OffsetToCenDir" size="32" endian="little" signed="false">
    <Relation type="size" of="LocalFileHeader" isOutputOnly="true"/>
  </Number>

As you can see here, we’ve added a new parameter, isOutputOnly which lets Peach know that this relation will only get applied during the fuzz process. This parameter is only available in SVN so make sure you are running the latest version of Peach.

H. Zip64 End of Central Directory Locator

Excellent. Only two blocks left, both of which appear to be fairly straight forward. Our first block, the “Zip64 end of central directory locator”, begins with a static string to identify the block, followed by 3 static length fields. Let’s go ahead and create this block in our Pit.

    <!-- H.  Zip64 end of central directory locator -->
    <Block name="Zip64EndOfCentralDirectoryLocator" minOccurs="0" maxOccurs="1">
      <String name="eocdl_Signature" valueType="hex" value="504b0607" token="true" mutable="false"/>
      <Number name="eocdl_NumOfDisk" size="32" endian="little" signed="false"/>
      <Number name="eocdl_RelOffsetofZ64" size="64" endian="little" signed="false"/>
      <Number name="eocdl_TotNumDisk" size="32" endian="little" signed="false"/>
    </Block>

Hopefully your results look similar to the code above. You can see that we’ve defined our signature and marked it as a token so that Peach knows to look for this specific value when identifying the block. We finished up this block by defining our 4 static length fields and adding the correct length for each.

I. End of central directory record

Our final block, the “End of central directory record,” again contains our static signature, followed by 7 static length fields and 1 variable length field. Looking at the field names we also see that we can go ahead and apply a size relation to 2 of our elements.

  <Block name="EndOfCentralDirectoryRecord">
    <String name="eocd_Signature" valueType="hex" value="504b0506" token="true" mutable="false"/>
    <Number name="eocd_NumOfDisk" size="16" endian="little" signed="false"/>
    <Number name="eocd_NumOfDiskWCD" size="16" endian="little" signed="false"/>
    <Number name="eocd_TotNumEntriesOD" size="16" endian="little" signed="false"/>
    <Number name="eocd_TotNumEntriesICD" size="16" endian="little" signed="false"/>
    <Number name="eocd_SizeOfCenDir" size="32" endian="little" signed="false">
      <Relation type="size" of="CentralDirectoryStructure"/>
    </Number>
    <Number name="eocd_OffsetToCenDir" size="32" endian="little" signed="false"/>
    <Block minOccur="0" maxOccur="1">
      <Number name="eocd_CommLen" size="16" endian="little" signed="false">
        <Relation type="size" of="eocd_Comment"/>
      </Number>
      <Blob name="eocd_Comment"/>
    </Block>
  </Block>

Again, you can see that we’ve defined our static signature, defined our 7 static length fields, 1 variable field, and applied a size relation to the “size of [...] central directory” field and “Zip file comment length” field. Make sure that you’re “size of [...] central directory” relation points directly at the “Central Directory” block. This will ensures that this field will remain valid while fuzzing the “Central Directory” block.

Our completed DataModel should look like the following:

  <DataModel name="ZipFileFormat">
    <!--  A.  Local file header -->
    <Block name="LocalFileHeader" maxOccurs="1024">
      <String name="lfh_Signature" valueType="hex" value="504b0304" token="true" mutable="false"/>
      <Number name="lfh_Ver" size="16" endian="little" signed="false"/>
      <Flags name="lfh_BitFlag" size="16" endian="little" signed="false">
        <Flag name="lfh_bf_Encrypted" size="1" position="0"/>
        <Flag name="lfh_bf_CompMethod1" size="1" position="1"/>
        <Flag name="lfh_bf_CompMethod2" size="1" position="2"/>
        <Flag name="lfh_bf_Zeroed" size="1" position="3"/>
        <Flag name="lfh_bf_Deflate" size="1" position="4"/>
        <Flag name="lfh_bf_Patched" size="1" position="5"/>
        <Flag name="lfh_bf_Strong" size="1" position="6"/>
        <Flag name="lfh_bf_Unused1" size="1" position="7"/>
        <Flag name="lfh_bf_Unused2" size="1" position="8"/>
        <Flag name="lfh_bf_Unused3" size="1" position="9"/>
        <Flag name="lfh_bf_Unused4" size="1" position="10"/>
        <Flag name="lfh_bf_Efs" size="1" position="11"/>
        <Flag name="lfh_bf_Reserved1" size="1" position="12"/>
        <Flag name="lfh_bf_Enc_CD" size="1" position="13"/>
        <Flag name="lfh_bf_Reserved2" size="1" position="14"/>
        <Flag name="lfh_bf_Reserved3" size="1" position="15"/>
      </Flags>
      <Number name="lfh_CompMethod" size="16" endian="little" signed="false"/>
      <Number name="lfh_LastModTime" size="16" endian="little" signed="false"/>
      <Number name="lfh_LastModDate" size="16" endian="little" signed="false"/>
      <Number name="lfh_CRC32" size="32" endian="little" signed="false"/>  
      <Number name="lfh_CompSize" size="32" endian="little" signed="false">
        <Relation type="size" of="lfh_CompSizeData"/>
      </Number>
      <Number name="lfh_DecompSize" size="32" endian="little" signed="false"/>
      <Number name="lfh_FileNameLen" size="16" endian="little" signed="false">
        <Relation type="size" of="lfh_FileName"/>
      </Number>
      <Number name="lfh_ExtraFldLen" size="16" endian="little" signed="false">
        <Relation type="size" of="lfh_FldName"/>
      </Number>
      <String name="lfh_FileName"/>
      <String name="lfh_FldName"/>
    <!--  B.  File data -->
      <Block name="lfh_Data">
        <Block name="lfh_DataHasSize">
          <Relation type="when" when="int(self.find('lfh_CompSize').defaultValue) != 0"/>
          <Blob name="lfh_CompSizeData" mutable="false"/>
        </Block>
        <Block name="lfh_DataNoSize">
          <Relation type="when" when="int(self.find('lfh_CompSize').defaultValue) == 0"/>
          <Blob name="lfh_CompNoSizeData" mutable="false">
		    <!--<Relation type="size" of="dd_CompSize64"/>-->
			<!--<Relation type="size" of="dd_CompSize32"/>-->
          </Blob>
        </Block>
      </Block>
    <!--  C.  Data descriptor -->
      <Block name="DataDescriptor">
	    <Relation type="when" when="int(self.find('lfh_BitFlag.lfh_bf_Zeroed').defaultValue) == 1"/>
        <String name="dd_Sig" valueType="hex" value="504b0708" token="true" mutable="false"/>
        <Number name="dd_CRC32" size="32" endian="little" signed="false"/>
		<Choice name="dd_chooser">
		  <Block name="dd_64">
            <Number name="dd_CompSize64" size="64" endian="little" signed="false"/>
            <Number name="dd_DecompSize64" size="64" endian="little" signed="false" constraint="'4b50' not in hex(value)"/>
          </Block>
		  <Block name="dd_32">
            <Number name="dd_CompSize32" size="32" endian="little" signed="false"/>
            <Number name="dd_DecompSize32" size="32" endian="little" signed="false"/>
          </Block>
        </Choice>
      </Block>
    </Block>

    <!-- E.  Archive Extra Data Record: -->
    <Block name="ArchiveExtraDataRecord" minOccurs="0" maxOccurs="1">
      <String name="aedr_Sig" valueType="hex" value="504b0608" token="true" mutable="false"/>
      <Number name="aedr_ExtFldLen" size="32" endian="little" signed="false"/>
      <Blob name="aedr_ExtFld"/> <!-- Look into adding more definition -->
    </Block>

    <!-- F.  Central directory structure: -->
    <Block name="CentralDirectoryStructure" minOccurs="0" maxOccurs="1">
      <Block name="FileHeader" maxOccurs="1024">
        <String name="cfh_Signature" valueType="hex" value="504b0102" token="true" mutable="false"/>
        <Number name="cfh_Ver" size="16" endian="little" signed="false"/>
        <Number name="cfh_VerReq" size="16" endian="little" signed="false"/>
        <Flags name="cfh_BitFlag" size="16" endian="little" signed="false">
          <Flag name="cfh_bf_Encrypted" size="1" position="0"/>
          <Flag name="cfh_bf_CompMethod1" size="1" position="1"/>
          <Flag name="cfh_bf_CompMethod2" size="1" position="2"/>
          <Flag name="cfh_bf_Zeroed" size="1" position="3"/>
          <Flag name="cfh_bf_Deflate" size="1" position="4"/>
          <Flag name="cfh_bf_Patched" size="1" position="5"/>
          <Flag name="cfh_bf_Strong" size="1" position="6"/>
          <Flag name="cfh_bf_Unused1" size="1" position="7"/>
          <Flag name="cfh_bf_Unused2" size="1" position="8"/>
          <Flag name="cfh_bf_Unused3" size="1" position="9"/>
          <Flag name="cfh_bf_Unused4" size="1" position="10"/>
          <Flag name="cfh_bf_EFS" size="1" position="11"/>
          <Flag name="cfh_bf_Reserved1" size="1" position="12"/>
          <Flag name="cfh_bf_Enc_Cd" size="1" position="13"/>
          <Flag name="cfh_bf_Reserved2" size="1" position="14"/>
          <Flag name="cfh_bf_Reserved3" size="1" position="15"/>
        </Flags>
        <Number name="cfh_CompMethod" size="16" endian="little" signed="false"/>
        <Number name="cfh_LastModTime" size="16" endian="little" signed="false"/>
        <Number name="cfh_LastModDate" size="16" endian="little" signed="false"/>
        <Number name="cfh_CRC32" size="32" endian="little" signed="false" mutable="false"/>
        <Number name="cfh_CompSize" size="32" endian="little" signed="false"/>
        <Number name="cfh_CompSize" size="32" endian="little" signed="false"/>
        <Number name="cfh_DecompSize" size="32" endian="little" signed="false"/>
        <Number name="cfh_FileNameLen" size="16" endian="little" signed="false">
          <Relation type="size" of="cfh_FileName"/>
        </Number>
        <Number name="cfh_ExtraFldLen" size="16" endian="little" signed="false">
          <Relation type="size" of="cfh_FldName"/>
        </Number>
        <Number name="cfh_FileCommLen" size="16" endian="little" signed="false">
          <Relation type="size" of="cfh_FileComment"/>
        </Number>
        <Number name="cfh_DiskNumStart" size="16" endian="little" signed="false"/>
        <Number name="cfh_IntFileAttrib" size="16" endian="little" signed="false"/>
        <Number name="cfh_ExtFileAttrib" size="32" endian="little" signed="false"/>
        <Number name="cfh_RelOffsetLFH" size="32" endian="little" signed="false"/>
        <String name="cfh_FileName">
	      <Fixup class="checksums.ExpressionFixup">
            <Param name="ref" value="lfh_FileName" />
            <Param name="expression" value="data" />
          </Fixup>
        </String> 
        <String name="cfh_FldName"/>
        <String name="cfh_FileComment"/>
      </Block>
      <Block name="CDSDigitalSignature" minOccurs="0" maxOccurs="1">
        <String name="cdsds_Signature" valueType="hex" value="504b0505" token="true" mutable="false"/>          
        <Number name="cdsds_DataSize" size="16" endian="little" signed="false">
          <Relation type="size" of="cdsds_Data"/>
        </Number>
        <Blob name="cdsds_Data" mutable="false"/>
      </Block>
    </Block>

    <!--  G.  Zip64 end of central directory record -->
    <Block name="Zip64EndOfCentralDirectoryRecord" minOccurs="0" maxOccurs="1">
      <String name="z64eocd_Signature" valueType="hex" value="504b0606" token="true" mutable="false"/>
      <Number name="z64eocd_SizeOfRecord" size="64" endian="little" signed="false">
        <Relation type="size" of="CentralDirectoryRecord"/>
      </Number>
      <Block name="CentralDirectoryRecord">
        <Number name="z64eocd_VerMadeBy" size="16" endian="little" signed="false"/>
        <Number name="z64eocd_VerNeeded" size="16" endian="little" signed="false"/>
        <Number name="z64eocd_ThisDiskNum" size="32" endian="little" signed="false"/>
        <Number name="z64eocd_SofCDDiskNum" size="32" endian="little" signed="false"/>
        <Number name="z64eocd_CDOnDisk" size="64" endian="little" signed="false"/>
        <Number name="z64eocd_TotNumEntries" size="64" endian="little" signed="false"/>
        <Number name="z64eocd_SizeOfCenDir" size="64" endian="little" signed="false"/>
        <Number name="z64eocd_OffsetToCenDir" size="64" endian="little" signed="false"/>
        <Block name="z64eocd_Z64ExtensDS" minOccurs="0" maxOccurs="1">
          <Number name="z64eocd_ExtensDs_Header" size="16" endian="little" signed="false"/>
          <Number name="z64eocd_ExtensDs_Size" size="32" endian="little" signed="false">
            <Relation type="size" of="z64eocd_ExtensDs_Data"/>
          </Number>
          <Blob name="z64eocd_ExtensDs_Data"/>
        </Block>
      </Block>
    </Block>
    
    <!-- H.  Zip64 end of central directory locator -->
    <Block name="Zip64EndOfCentralDirectoryLocator" minOccurs="0" maxOccurs="1">
      <String name="eocdl_Signature" valueType="hex" value="504b0607" token="true" mutable="false"/>
      <Number name="eocdl_NumOfDisk" size="32" endian="little" signed="false"/>
      <Number name="eocdl_RelOffsetofZ64" size="64" endian="little" signed="false"/>
      <Number name="eocdl_TotNumDisk" size="32" endian="little" signed="false"/>
    </Block>
    
    <!--  I.  End of central directory record: -->
    <Block name="EndOfCentralDirectoryRecord">
      <String name="eocd_Signature" valueType="hex" value="504b0506" token="true" mutable="false"/>
      <Number name="eocd_NumOfDisk" size="16" endian="little" signed="false"/>
      <Number name="eocd_NumOfDiskWCD" size="16" endian="little" signed="false"/>
      <Number name="eocd_TotNumEntriesOD" size="16" endian="little" signed="false"/>
      <Number name="eocd_TotNumEntriesICD" size="16" endian="little" signed="false"/>
      <Number name="eocd_SizeOfCenDir" size="32" endian="little" signed="false">
        <Relation type="size" of="CentralDirectoryStructure" isOutputOnly="true"/>
      </Number>
      <Number name="eocd_OffsetToCenDir" size="32" endian="little" signed="false">
	    <Relation type="size" of="LocalFileHeader" isOutputOnly="true"/>
      </Number>
      <Block name="ZipFileCommentBlock" minOccur="0" maxOccur="1">
        <Number name="eocd_CommLen" size="16" endian="little" signed="false">
          <Relation type="size" of="eocd_Comment"/>
        </Number>
        <Blob name="eocd_Comment"/>
      </Block>
    </Block>
  </DataModel>


Fuzzer Configuration

Now that we have our DataModel created, we can go ahead and complete our Pit by telling Peach what to do with the structure we’ve defined in our DataModel. Luckily the FileFuzzerGui.xml template already contains most of the data we need to configure, but for the purpose of this document, we’ll go ahead and discuss them anyway. Let’s take a look at our StateModel.

StateModel

<StateModel name="State" initialState="Initial">
  <State name="Initial">
    <Action type="open" />

    <!-- Write out contents of file -->
    <Action name="WriteFile" type="output" publisher="file">
      <DataModel ref="FileData" />
    </Action>

    <!-- Close file -->
    <Action type="close" publisher="file" />
      <!-- Launch the file consumer -->
      <Action type="call" method="notepad.exe" publisher="launch"/>
  </State>
</StateModel>

Looking at the above snippet from our FileFuzzerGui.xml you can see that I’ve left all the original comments in-line. Mike Eddington has already provided us with a great explanation of each of the functions within our StateModel (and the rest of our template for that matter) so there’s no point in me reinventing the wheel. I’ll just add a few quick notes in line to discuss some of the more obscure parameters in use here. For a listing of parameters not already included in the FileFuzzerGui.xml, please see the documentation here at the Peach project page.

Looking at our template, we can see that the StateModel is defined in a similar way as our DataModel with the exception of 1 additional parameter.

StateModel Parameters

  • name
    • As with our past elements, the name parameter allows us to define a name for this StateModel. More complex Pits can contain multiple StateModels so defining a unique name is best in the event you need to reference this element later. This parameter is required.
  • initialState
    • The initialState parameter, as the name implies, defines the first State to be used in the StateModel. Each StateModel can utilize multiple States depending on the fuzzer’s requirements. This parameter is required.



With our <StateModel> container out of the way, we can see that the template defines a single <State> (atleast one “State” is required within our “StateModel”). Luckily for us, that’s all we’ll need. Multiple States are more common in complex network fuzzing rather than file format fuzzing. The purpose of each State is to act as an container for the Action element.

The Action element is responsible for instructing Peach exactly what do do with our data. Before we modify the Actions defined in our template, let’s briefly discuss the options available to Action elements.

Action Parameters
This is only a small sub-set of the possible parameters available to the Action element. Please reference the full spec available here, at the Peach project page.

  • type
    • The “type” parameter defines the purpose of the action. For instance, our first action type is “open.” This action is response for opening the file and preparing it for any further actions to be performed. The three actions listed in the FileFuzzerGui.xml template are only a small subset of the possible Action types available. A full listing of Peach’s action types can be found here, at the Peach project page.
  • publisher
    • The “publisher” parameter as you would expect defines which publisher we would like to pass this data to. Our first two actions instruct Peach to use the file publisher for opening the file. writing our fuzzed data, and saving the file (typically to a temporary location). Our third action defines the “launch” publisher responsible for opening our application to be fuzzed. We’ll talk more about this in a bit.
  • method
    • The “method” parameter identifies the application consumer. This parameter is only valid for Action type “call”



Working from the FileFuzzerGui.xml template we’ll only need to modify 2 lines within the StateModel.

First let’s modify the Action call:

<Action type="call" method="notepad.exe" publisher="launch"/>

Rather than including the executable, we’ll specify a unique string to tie our StateModel and Agent together. Most of the documentation and samples Mike’s provided with the Peach framework use the variable “ScoobySnacks” and we’ll do the same here. However it’s important to note that this string can be anything as long as our Agent configuration matches it. More on that in a bit.

<Action type="call" method="ScoobySnacks" publisher="launch"/>


Agent

Now onto our Agent configuration. The Agent is responsible for monitoring our application and recording any crashes that our fuzzer might trigger. Peach also utilizes Microsoft’s !Exploitable (pronounced Bang-Exploitable) which is useful when classifying the exploitability of crashes. Further information on !exploitable can be found at here.

Here’s what you should be seeing in the FileFuzzerGui.xml:

<!-- Setup a local agent that will monitor for faults -->
<Agent name="LocalAgent">
  <Monitor class="debugger.WindowsDebugEngine">

    <!-- The command line to run.  Notice the filename provided matched up
         to what is provided below in the Publisher configuration -->
    <Param name="CommandLine" value="c:\windows\system32\notepad.exe fuzzedfile.txt" />

    <!-- This parameter will cause the debugger to wait for an action-call in
         the state model with a method="notepad.exe" before running
         program.  -->
    <Param name="StartOnCall" value="notepad.exe" />
  </Monitor>

  <!-- Enable heap debugging on our process as well. -->
  <Monitor class="process.PageHeap">
    <Param name="Executable" value="notepad.exe"/>
  </Monitor>
</Agent>

With the comments in line this should be fairly self explanatory. The <Agent> element acts as a container for our monitor configurations. Here you can specify what the type and behavior of our monitor. For a full listing of available monitors, please refer to the documentation here at the Peach project page.

Within our Agent container, we see that the template is configured to use the Windows Debug Engine as our primary monitor. We can also see 2 additional parameters defined within this monitor. The first parameter, “CommandLine” is used to define the path to the application we’ll be launching (and monitoring), the filename of our fuzzed data, and any flags that may be needed to launch the application.

ProTip: If you ever find that the application you are fuzzing is being launched but it appears that its not actually opening your fuzzed data, try adding a full path to the fuzzed file and wrap it in html encoded quotes (i.e. &quot;C:\peach\fuzzed.zip&quot;)

Our next parameter defines the method to wait for before attaching the debugger. We’ll need to change this to the same value we provided to our <Action type=”call” …/> element within the StateModel.

Following that we also see that the PageHeap Monitor is being enabled for our tests. Again, the comments here are pretty self-explanatory and this Monitor is used for deubugging and recording data affecting the application’s heap. This parameter only accepts the executable name and does not require the full file path.

For testing purposes, we’ll try to re-identify vulnerabilities associated with the GlobalScape – Cutezip Archiver. You can find a vulnerable copy of this application here.

Once you’ve installed CuteZip, we can go ahead and apply our 3 required changes to this section of the template. We’ll be adding the correct path to our application for the “CommandLine” parameter, modifying the “StartOnCall” value to match what we have in our StateModel (ScoobySnacks), and the executable name of our application. Remember, for this configuration we’ll need to provide the exact same command line paramaters required to launch the application and extract our file.

Your Agent section should look like the following:

  <Agent name="LocalAgent">
    <Monitor class="debugger.WindowsDebugEngine">
      <Param name="CommandLine" value="C:\Program Files\GlobalSCAPE\CuteZIP\CuteZip.exe -x fuzzed.zip C:\temp"/>
      <Param name="StartOnCall" value="ScoobySnacks"/>
    </Monitor>
    <Monitor class="process.PageHeap">
      <Param name="Executable" value="CuteZip.exe"/>
    </Monitor>
  </Agent>

Good, nearly done. We only have 2 more sections to define.

Test Block

The Test section of our template is responsible for tying everything together. It correlates our State and Agent configuration and allows us to configure our Publishers, the functions responsible for receiving and writing our fuzzed data to disk. Let’s take a look at the configuration for this section defined in the template.

	<Test name="TheTest">
		<Agent ref="LocalAgent" />

		<StateModel ref="State"/>

		<!-- Configure our publisher with correct filename to write too -->
		<Publisher class="file.FileWriter" name="file">
			<Param name="fileName" value="fuzzedfile.txt" />
		</Publisher>

		<Publisher class="process.DebuggerLauncherGui" name="launch">
			<Param name="windowName" value="Notepad" />
		</Publisher>
	</Test>

You can see here that we let Peach know that we’ll be using our named Agent, LocalAgent, and our named StateModel, State. We also see two Publishers being defined, file.FileWrite and process.DebuggerLauncherGui. We’re actually going to go ahead and remove both of these publishers and combine them with one (sort of) to accomplish the same job.

FileWriterLauncherGui
We can use the FileWriterLauncherGui publisher to write a single file to disk, then have our fuzzed application open this fuzzed file. Once open, Peach will wait for the CPUTime to hit 0 before sending a WM_CLOSE message to kill the application. With this configuration, we’ll need 3 parameters; one to define the name of the file to be written (this must be the same as the parameter we supplied to “CommandLine” in our Agent configuration), the windowName parameter so that Peach knows where to send the WM_CLOSE message, and mark debugger as true.

Let’s go ahead and update the named Agent and StateModel references to match what we have defined in our modified configuration and add our Publisher. Your template should look like the following:

  <Test name="TheTest">
    <Agent ref="LocalAgent"/>
    <StateModel ref="TheState"/>
	<Publisher class="file.FileWriterLauncherGui">
      <Param name="fileName" value="fuzzed.zip"/>
      <Param name="windowName" value="CuteZip"/>
      <Param name="debugger" value="true"/>
    </Publisher>
  </Test>

Now typically I like to add two Publishers, one for GUI applications and another that can be run solely from the command line. Why? Well, typically fuzzing command line applications is significantly faster than fuzzing GUI applications. So as long as you can get the same amount of coverage fuzzing an application via the command line as you would fuzzing the GUI interface, it may decrease fuzz time substantially. So to prepare for this, we’ll go ahead and add the FileWriteLauncher (NonGUI) Publisher to our Test element.

Although we’ll have both Publishers in our Test block, we shouldn’t actually use both. Since the command line arguments we provide above in our Agent configuration allow us to launch the application directly from within the command-line without a GUI interface, let’s go ahead and comment our our file.FileWriterLauncherGui Publisher.

If we decide to fuzz an application with a GUI we’ll simply comment out our FileWriterLauncher and uncomment FileWriterLauncherGui.

Your Test configuration should look like the following:

  <Test name="TheTest">
    <Agent ref="LocalAgent"/>
    <StateModel ref="TheState"/>
	<!--<Publisher class="file.FileWriterLauncherGui">
      <Param name="fileName" value="fuzzed.zip"/>
      <Param name="windowName" value="CuteZip"/>
      <Param name="debugger" value="true"/>
    </Publisher>-->
	<Publisher class="file.FileWriterLauncher">
      <Param name="fileName" value="fuzzed.zip" />
      <Param name="debugger" value="true"/>
    </Publisher>
  </Test>

As you can see, our configuration is nearly the same as our GUI publisher with the exception of the windowName parameter.

Run Block

Our final section, Run, is used for combining multiple tests and defining a place to log our crash data. For this example we’ve only defined a single Test section. Your Run section should look like the following:

  <Run name="DefaultRun">
    <Test ref="TheTest"/>
    <Logger class="logger.Filesystem">
       <Param name="path" value="Z:\logs.zip.cutezip"/>
    </Logger>
  </Run>

You can find the entire Peach Pit here

Testing Our Fuzzer

Now that we’ve finished our Pit, we’ll need to go ahead and do a few test runs before we actually kick off the fuzzer. But before we do that we’ll need to create a quick test Zip file for our Pit to parse. Once you have a Zip file selected, modify the following Data parameter within your StateModel so that Peach knows which file to parse:

  <Data name="data" fileName="C:\peachfuzz\Test.zip"/>

Ok, with our Pit updated, the first thing that we’ll do is run a quick configuration check that’ll let us know if there are any errors in our Pit. So to begin, open up a command window, change directory to the location of your Peach installation and run the following command.

peach.bat -t zip.xml

If no errors were detected, your output should look like the following:

Peach Configuration Test

With our check complete, we’ll take it one step further and run a single test case of our fuzzer. The first test case does not actually fuzz our sample data. It’ll parse the sample zip file, regenerate another copy and provide this data to our target application.

To do so, we’ll run the following command:

peach.bat -1 --debug zip.xml

After executing that command, Peach will go ahead and parse our test Zip file using the DataModel we created, dump the output to a single file without applying any mutations on it, and provide it to the target application. This is essentially a dry run. Peach (and you) will make sure that the Application is properly receiving the file that we’ve provided it and ensure that the Peach Agent is able to detect the process and wait for it to exit (or be killed). If a fault is thrown or something goes wrong, the first test case will fail and Peach (even without the -1 parameter) will exit the fuzz process.

However if all goes well, you should see something similar to the following:

Peach - First Run

Also take note of the Agent output:

Peach - First Run - Agent Output

***Using the –debug option is incredibly helpful for detecting issues within your DataModel. It essentially prints out the logic that Peach uses to crack our provided file. If there’s an issue in your DataModel that prevents Peach from cracking the entire file, we can go ahead and find the position in the file and the element that is failing. Again, this is another reason why naming your elements proves to be helpful.

Looking through the Agent output we can see that Peach launches the process with our monitor set to the newly created process, the test is executed, and once the process reaches a CPU time of 0, Peach kills the application.

Before we move on, we’re going to take our fuzzed.zip, the file created by Peach and we’ll diff it against our Test.zip to make sure they are identical. This will prove to us that Peach is properly parsing and writing out our file. This shouldn’t be much of an issue in our Pit, however more complex fuzzers utilizing Transformers and Fixups may alter the data and the output might not be identical to the input.

In the screen shot below, I’m using the 010 Binary editor to do a byte level comparison of the two files. Additionally, we can also run the template on both files to verify that the data is the same.

Peach - First Run - Diff
Excellent. We’re just about ready to begin fuzzing. Before we do, let’s give it one more sample debug run.

peach.bat -1 --debug zip.xml

Uh oh. This time we see that after launching the application and providing it with our Peach generated file, a popup occurs informing us that the file we wish to extract already exists. Unfortunately, CuteZip doesn’t provide us with an option to automatically overwrite old files via the command line. Because of this, we’ll need to find a way to select “Yes” in our popup so that our file is overwritten each time and our new file is extracted.

Popupkiller.py

Popupkiller.py is an additional application included within the Peach framework that might become useful while fuzzing GUI applications. Before I describe this application, let’s go ahead and download the AutoHotKey application here.

Once you have the AutoHotKey installed, let’s go ahead and open up the popupkiller.py in our favorite editor. You can find this file at the following location:

C:\(Path to Peach Installation)\tools\popupkiller.py

Looking at the top few lines, we see that Popupkiller.py allows us to define the application (or popup) window title, any text that we might want to look for in the event of a common window title, the button to be clicked (if we wish to close or execute an action), or if we’d like to save the popup. With this script, we can have Peach instruct the application to overwrite our previous file on each test case.

So before we can configure our script we need a few key pieces of information. Namely our window title and button text. In most cases you will likely be able to enumerate this information just by looking at the popup. However, in this instance we’ll fire up WindowSpy, an application included with the AutoHotKey package.

Once we’ve launched WindowSpy, let’s go ahead and click on the popup generated.

If you’re having a hard time catching the popup during the fuzzing process you can always launch the application directly. As long as the extracted file already exists in the defined location the popup will occur.

AutoHotKey - WindowSpy

In the screenshot above, we can confirm that the popup window title is “Confirm File Replace” and the button text we’re looking for is “&Yes”. With this information, let’s add the following line to our popupkiller.py:

	[ 'Confirm File Replace', None, '&Yes', False ],

Now to test it, let’s go ahead and launch popup killer by executing the following command:

C:\peachfuzz\tools\> python popupkiller.py

We’ll then manually trigger the overwrite confirmation window by launching our application from the command-line. If we don’t see the popup, we’re good to go!

Now that we’ve verified that our Pit can properly parse a Zip file, provide that file to the Target application, and successfully monitor the process we can go ahead and begin fuzzing. But before we do, there are some additional items we may wish to consider.

Code Coverage

To improve the effectiveness of our fuzzing process, it’s important that we consider how much of the application we’re actually affecting with our sample data. For example, looking at our test file using the 010 Binary Editor and running the Zip template, we can see that only 3 blocks, Local File Header (containing our File Data), Central Directory Structure, and End of Central Directory Record blocks are being used.

This file essentially utilizes only about 40% of our Pit, and 40% of the specification for that matter. Now lets consider a Zip64 archive which will be using the Data Descriptor, Zip64 End of Central Directory Record, and Zip64 End of Central Directory Locator in addition to those blocks used by a standard Zip archive. If we choose not to fuzz using a Zip64 archive, any functions specific to those blocks will not be tested.

Further information on code coverage can be found here.

Since our Pit replicates the functionality of our target applications, they too will only need to utilize a smaller subset of code in order to parse our sample data. Therefore, any bugs that may potentially lie in other blocks of the Zip specification will go untested. Luckily for us, Peach provides us with a very quick and easy way to parse through a large data sample and determine which files affect the most of our application.

Minset

Minset is an application provided with the Peach framework that allows us to determine which files affect the greatest amount of code within our application. By providing a directory containing our sample files, minset will monitor the application and determine how many basic blocks (different than our DataModel “Block” elements) of code are being used to process each file. We’ll run minset against a quick sample to see what it provides.

I’ve put together a small archive containing 12 Zip files that you can download here to test.

In the minset output below you may notice references to the file, zip64.zip. As this file was created by a third party, I can’t distribute it however you can download the archive here. Unpack the archive and rename “SampleXpsDocuments_1_0/MXDW/Zip64Interleaving/Zip64I_60FixedPage_out.xps” to zip64.zip.

Once you’ve downloaded the archive, unpack it to the following directory:

C:\(Path to Peach Installation)\tools\minset\zip

Now we’re ready to fire up minset. For this test, we’ll be checking our files against the 7-Zip application. If you don’t have it already, you can download it here.

Open up a command window and execute the following command in the minset directory:

C:\peachfuzz\tools\minset>minset -s zip\*.zip -m minset "C:\Program Files\7-Zip\7z.exe" t %

Your output should look similar to the following.

Peach - minset

Once minset completes, it’ll go ahead and copy the minimal file set to the directory we specified with the -m option.

For this discussion, we’ll use the Zip files contained in this archive for our fuzz process.

Now that we have several files to mutate we’ll need to decide how we’d like to fuzz them. Let’s modify our Pit to use the Test.zip archive as our base mutation file and run our fuzzer. We’ll go ahead and kill the agent window after the first or second test case.

Not that as the Peach fuzz process continues, we see two numbers in the first column next to each test case. These numbers display the current test case number, and the total number of test cases for that file. Now, we can go ahead and fuzz each file, running all iterations, and slowly work our way to over each file, however this would likely take a great deal of time. With that said, Peach offers us another strategy for fuzzing our dataset: the random mutation strategy.

Random Mutation Strategy

The random mutation strategy, in comparison with the default strategy allows us to fuzz any number of fields concurrently, rather than a single element, block, or tree per iteration. This allows us to trigger crashes that might only occur if multiple fields are affected in comparison to a single element or tree. Additionally, the random mutation strategy allows us to define the maximum number of fields to be fuzzer per iteration, a directory containing our minset data, and the number of iterations to be run per file. This strategy will essentially run indefinitely since once all of our files are consumed, Peach resumes the process with the first file in the list, and continues by fuzzing randomly selected elements.

To enable the random mutation strategy, we’ll go ahead and modify the Data element within our StateModel and add the following line to our Test block within our Pit. Make sure it is added to the top-level of the Test block and not to one of the sub elements such as the Agent, StateModel, or Publisher.

  <StateModel name="TheState" initialState="Initial">
    <State name="Initial">
      <Action type="output">
        <DataModel ref="ZipFileFormat"/>
        <Data name="data" fileName="C:\peachfuzz\tools\minset\zip\minset\*.zip"/>
      </Action>
      <Action type="close"/>
      <Action type="call" method="ScoobySnacks"/>
        </State>
  </StateModel>


<Test name="TheTest">
  <Strategy class="rand.RandomMutationStrategy" switchCount="1500" maxFieldsToMutate="7"/>
  <Agent ref="LocalAgent"/>
  <StateModel ref="TheState"/>
  <Publisher class="file.FileWriterLauncherGui">
    <Param name="fileName" value="fuzzed.zip"/>
    <Param name="windowName" value="ZipGenius"/>
    <Param name="debugger" value="true"/>
  </Publisher>
</Test>

Looking at the above line, we see that we’ve instructed Peach to use the random mutation strategy, fuzzing a maximum of 7 fields, and we’ll be running 1500 iterations per file before moving on.

Before we start our fuzzer, we’re going to discuss one additional command line parameter.

The random mutation strategy also provides us with a seed number so that in the event our fuzzer crashes or we’d like to replicate a test case later, we can specify the seed number and the iteration to be able to return to that exact test case. The seed value will be generated at the start of each new test and will also be stored in the status.txt file located within your specified log directory. So, in the event that the fuzzer crashes on say test case #500 using a seed value of 1305094305.21 we can resume our session by entering the following command:

peach.bat --seed 1305094305.21 --skipto 500 zip.xml


Running Our Fuzzer

Ok, now it’s time to get down to business. If you’ve added the random mutation strategy to your Test block above, let’s go ahead and comment that out for now. We’ll also be mutating the Test.zip file so make sure you update the Data element within your StateModel.

Once you’ve made these changes, lets open up a command window and run the following command.

***Remember! Since we’ll be fuzzing the CuteZip application, don’t forget to fire up popupkiller.py before our test begins!

peach.bat zip.xml

Once the fuzz process has begun, we’ll let it run for a while.

After a few minutes you should notice that Peach has been able to trigger a few exceptions. Let’s take a look at the first exception which occurs at testcase #400

Feeling impatient? You can always run “peach.bat –skipto 400 zip.xml” to replicate the crash.

Crash Logs

So let’s change to our CuteZip logging directory (specified in the Logger element of our Run block) and list the directory contents.

[pyoor@Unknown ~]$ cd logs.zip.cutezip/
[pyoor@Unknown logs.zip.cutezip]$ ls
zip.xml_2011Jul18174449

Here, we see that Peach created a single directory named after our Pit filename and a timestamp denoting the start of our fuzz process. Let’s change in this directory as well.

[pyoor@Unknown logs.zip.cutezip]$ cd zip.xml_2011Jul18174449/
[pyoor@Unknown zip.xml_2011Jul18174449]$ ls
Faults  status.txt

Here we’re greeted with a directory, Faults, which as you would assume containing our crash data and a single file, status.txt, which updates as our fuzz process progresses. Let’s take a quick look at status.txt.

Peach Fuzzer Run
=================

Command line: C:\peachfuzz\\peach.py zip.xml 
Date of run: Mon Jul 18 13:44:49 2011
SEED: 1311011087.38
Pit File: zip.xml
Run name: DefaultRun

Mon Jul 18 13:44:53 2011: 
Mon Jul 18 13:44:53 2011: Test starting: TheTest
Mon Jul 18 13:44:53 2011: 
Mon Jul 18 13:44:53 2011: On test variation # 1
Mon Jul 18 13:54:33 2011: Fault was detected on test 44
Mon Jul 18 13:54:33 2011: Origional file name: C:\peachfuzz\minset\test.zip
Mon Jul 18 13:59:47 2011: Fault was detected on test 68
Mon Jul 18 13:59:47 2011: Origional file name: C:\peachfuzz\minset\test.zip
Mon Jul 18 14:03:38 2011: Fault was detected on test 85
Mon Jul 18 14:03:38 2011: Origional file name: C:\peachfuzz\minset\test.zip
Mon Jul 18 14:36:13 2011: Fault was detected on test 231
Mon Jul 18 14:36:13 2011: Origional file name: C:\peachfuzz\minset\test.zip
Mon Jul 18 14:40:22 2011: Fault was detected on test 248
Mon Jul 18 14:40:23 2011: Origional file name: C:\peachfuzz\minset\test.zip
Mon Jul 18 14:52:11 2011: Fault was detected on test 293
Mon Jul 18 14:52:11 2011: Origional file name: C:\peachfuzz\minset\test.zip
Mon Jul 18 14:59:48 2011: Fault was detected on test 326
Mon Jul 18 14:59:48 2011: Origional file name: C:\peachfuzz\minset\test.zip
Mon Jul 18 15:07:58 2011: Fault was detected on test 361
Mon Jul 18 15:07:58 2011: Origional file name: C:\peachfuzz\minset\test.zip
Mon Jul 18 15:17:12 2011: Fault was detected on test 400

Status.txt provides us with a good bit of information should we ever need to revist results from a previous fuzz. It lists the start time of our fuzz, the seed used (which really only matters if we’re using the random mutation strategy), as well as the specific test cases and the file used to generate a crash.

Within the Faults directory we see several sub-directories, each denoting a specific class of crash as designated by !Exploitable.

AgentConnectionFailed                      UNKNOWN_ReadAV_0x4c52190c_0x6b36390c
EXPLOITABLE_WriteAV_0x0a617d5e_0x08266247  UNKNOWN_TaintedDataPassedToFunction_0x0160787d_0x216e3a20

Inside EXPLOITABLE_WriteAV_0x0a617d5e_0x08266247, we see one directory, 400 (named after the test case number which triggered the crash). Let’s change into this directory and list the contents.

  • data_1_output_Named_49_fileName.txt
    • This file contains the name of the original file mutated to trigger this crash. This is useful when determining which file was used when specifying a directory as the source file.
  • data_1_output_Named_49.txt
    • This file contains the data actually provided to the application when the crash was triggered. This will be useful when reproducing the crash and determining exploitability.
  • data_2_call_Named_51.txt
    • This contains the call method parameter. When the crash was triggered. In simple fuzz processes containing only a single method call, this file provides us with little benefit.
  • LocalAgent_StackTrace.txt
    • This file contains the stacktrace generated at crashtime as well as the information generated by !Exploitable.


Let’s take a quick look at the LocalAgent_StackTrace.txt. Specifically the registers, faulting instruction, and stack unwind.

eax=000000b0 ebx=05b7fccb ecx=0000010d edx=00000000 esi=046b0336 edi=05b80000
eip=0047cc50 esp=05b7fa24 ebp=05b7fa2c iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00010206
*** WARNING: Unable to verify checksum for CuteZip.exe
*** ERROR: Module load completed but symbols could not be loaded for CuteZip.exe
CuteZip+0x7cc50:
0047cc50 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
...
[truncated for space]
...
WARNING: Stack unwind information not available. Following frames may be wrong.
05b7fa2c 0047a648 05b7fccb 046b0001 00000769 CuteZip+0x7cc50
05b7fa50 0047a5d3 00000769 00000001 0000093c CuteZip+0x7a648
05b7fa70 00464660 05b7faf8 00000001 0000093c CuteZip+0x7a5d3
05b7fa74 05b7faf8 00000001 0000093c 004f7110 CuteZip+0x64660
05b7fa78 00000000 0000093c 004f7110 0012d8ac 0x5b7faf8



Looking at the registers and faulting instruction, it looks like an unexpected change was made to the esi register (though we can’t be certain). Also the stack wind doesn’t provide us with anything obvious as to the cause of the crash.

Let’s rename our data_1_output_Named_49.txt to cutezip-400.zip. Next we’ll open this file and our original Test.zip in the 010 binary editor and perform a diff.

Crash Comparison

Looking at our diff results we see a few changes have been made to our mutated zip file. We can see that the file name length and file name for both our Local File Header and Central Directory structure has been changed, as well as our Central Directory Size and Offset. Many of these (i.e. file name length, directory size, offset) more than likely have been changed due to a Peach fuzzing the filename element (due to our relations and fixup).

If we were to open up the CuteZip application within our debugger and parse the cutezip-400.zip archive, we can see that the following SEH record has been corrupted.

SEH Overwrite

I’m not going to go through the entire process of developing an exploit for this as my friend corelanc0d3r has already done an excellent on the subject. You can find his tutorial here.

But, just for kicks, let’s go ahead and replace our filename with an msfpattern of the same length and open the application within our debugger.

Now that looks much better. I’ll let !pvefindaddr do all the talking for me:

0BADF00D  -------------------------------------------------------------------------
0BADF00D  Searching for metasploit pattern references
0BADF00D  -------------------------------------------------------------------------
0BADF00D  [1] Searching for first 8 characters of Metasploit pattern : Aa0Aa1Aa
0BADF00D  =====================================================================
069BFAF8   - Found begin of Metasploit pattern at 0x069bfaf8
0BADF00D  
0BADF00D   ** Could not find begin of Metasploit pattern (unicode expanded) in memory ! **
0BADF00D  
0BADF00D  [2] Checking register addresses and contents
0BADF00D  ============================================
0BADF00D   - Register EBX points to Metasploit pattern at position 467
0BADF00D   - Register ESI points to Metasploit pattern at position 1288
0BADF00D  
0BADF00D  [3] Checking seh chain
0BADF00D  ======================
0BADF00D   - Checking seh chain entry at 0x069bff74, value 42346d42
0BADF00D     => record is overwritten with Metasploit pattern after 1152 bytes
0BADF00D   - Checking seh chain entry at 0x336d4232, value c0c0c0c0
0BADF00D   - Checking seh chain entry at 0xc0c0c0c0, value c0c0c0c0
0BADF00D     Evaluated 3 SEH entries
0BADF00D  -------------------------------------------------------------------------
0BADF00D  Exploit payload information and suggestions :
0BADF00D  ---------------------------------------------
0BADF00D   [+] Type of exploit : SEH (SE Handler is overwritten)
0BADF00D       Offset to next SEH : 1148 
0BADF00D       Offset to SE Handler : 1152 
0BADF00D   [+] Payload suggestion (perl) :
0BADF00D       my $junk="\x41" x 1148; 
0BADF00D       my $nseh="\xeb\x06\x90\x90";
0BADF00D       my $seh= XXXXXXXX;  #pop pop ret - use !pvefindaddr p -n    to find a suitable address
0BADF00D       my $nops="\x90" x 24;
0BADF00D       my $shellcode="<your shellcode here>";
0BADF00D       my $payload = $junk.$nseh.$seh.$nops.$shellcode;
0BADF00D   [+] Read more about this type of exploit at 
0BADF00D       http://www.corelan.be:8800/index.php/2009/07/25/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part-3-seh/
0BADF00D  ---------------------------------------------------------------

I chose to use !pvefindaddr for the above output but for those of you who didn’t know, Team Corelan’s new Immunity plugin, Mona, has been released. I highly recommend checking it out. You can find the project page here.

Now that was pretty straight forward. In a short amount of time we were able to fuzz our target application and isolate the element which triggered the crash. Now, had we used the random mutation strategy, identifying the crashing element might have been a bit more difficult.

Mincrash

Mincrash, another tool provided in the Peach arsenal, allows us to compare our baseline data with our crash triggering data. By making small changes each time, it’s able to isolate the element or elements required to trigger a crash. This can be incredibly helpful when using the random mutation strategy where you might have several fields mutating at the same time.

For this discussion, we’ll look at an application crash triggered by the random mutation strategy.

Note: Using mincrash on mutated Zip files is not really that helpful. Most Zip applications, CuteZip in particular, have a very stringent set of requirements for parsing Zip files. If these requirements are not met, the archive is discarded and the application exits before a crash can be triggered. Because of this, we’ll more than likely only see our Filename elements mutated along with other elements that don’t have much of an impact on the Zip structure.

To replicate this crash, enable the random mutation strategy in your Pit and issue the following command:

peach.bat --seed 1311053420.97 --skipto 95 zip.pit

As with our previous example, we’ll make a copy of our data_1_Output_Named_49.txt and save it as cutezip-rand-95.zip. Opening up a command line, browser to the tools directory within your Peach installation. Once there, we’ll execute the following command:

C:\peachfuzz\tools>mincrash.py C:\cutezip-rand-95.zip C:\peachfuzz\minset\test.zip foo.zip "C:\Program Files\GlobalSCAPE\CuteZIP\CuteZip.exe -x foo.zip C:\temp"

If everything worked as planned, your output should look similar to the following.

Peach - Minset

Now to see what minset was able to do for us, let’s go ahead and run a quick diff on the original crashing archive, and our newly generated mincrash.bin.

Peach - Mincrash Diff

Here we can see several changes have been made to the file length element as well as the central directory size and offset elements. Most notably however, we can see that the application still crashes successfully when only the file name element of the central directory is mutated. This may or may not impact our exploit development but we can see that mincrash has done its job correctly and shown us the minimal amount of change required to trigger a crash.

Fin!

Welp, that’s it. Hopefully it wasn’t too terrible. Please feel free to post any comments, questions or requests!

Also, I’d just like to extend a huge thanks to Nicolas Krassas for not only hosting this blog, but rereading this gibberish every time I made a change!