Sie sind auf Seite 1von 55

Flinkd!

fuzzing, reverse engineering, exploit development, pure gibberish Home Projects About

12
Jul/11

Fuzzing with Peach Part 1


by pyoor under Fuzzing

Search keyw ords

Search

Categories
For the past several months Ive been doing a fair amount of work with the Peach fuzzing framework. At times (many in fact), Ive struggled with performing somewhat basic tasks with Peach but with a little perseverance and a lot of help (thanks Mike and Mikhail), Ive been able to develop some fairly complete Peach templates. In an attempt to save those of you just beginning with Peach, I thought Id 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. Fuzzing

Blogroll
0Entropy Corelan Team Nullthreat Security Phed

Contents [hide] Getting Started Peach Structure Zip File Format A. Local file header Block Parameters Basic Elements String Parameters Number Parameters Size Relations browser PRO version Are you a developer? Try out the HTML to PDF API

open in

pdfcrowd.com

B. File data C. Data Descriptor When Relations Choice Element Constraints D. Archive Decryption Header E. Archive Extra Data Record F. Central Directory Structure Fixups G. Zip64 End of Central Directory Record H. Zip64 End of Central Directory Locator I. End of central directory record Fuzzer Configuration StateModel Agent Test Block Run Block Testing Our Fuzzer Popupkiller.py Code Coverage Minset Random Mutation Strategy Running Our Fuzzer Crash Logs Mincrash Fin!

Getting Started
For this tutorial, well be looking at the Zip file format. Well 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 youll 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

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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 wed like to fuzz, well begin by creating a Peach Pit, an XML based file that provides Peach with the structure of our data, how wed like it fuzzed, and what application wed like to target. A Peach Pit is comprised of 5 main sections:

Peach Structure
DataModel The DataModel is the element within our pit that well use to define the structure of our data. In this case, well 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, well start by making a copy of the FileFuzzerGui.xml template located in C:\(Path-to-Peachinstallation)\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! Were going to remove that string and rename our DataModel to Zip. You should have something similar to the following: 1 2 3 <DataModel name="Zip"> </DataModel>

Within each DataModel, Peach allows several XML elements to define the structure and type of data we

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

intend to generate or parse. Ill go introduce each element needed to create our Zip file fuzzer as we need them. For now, lets take a look at the file specification so that we can develop a plan for defining our Pit. Lets 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, lets 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 well 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, well 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

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

(as a group). Lets 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, lets 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). 1 2 3 4 <DataModel name="Zip"> <Block name="LocalFileHeader" minOccurs="1" maxOccurs="1024"> </Block> </DataModel>

Good. Now that weve created a block to hold our Local File Header, lets 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 well need to define in our Pit. For this section, Im going to discuss each element and what well 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

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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. Lets 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, howev er f or this tutorial well use a <String> to demonstrate its use.

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

So as with the block element, weve 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 weve defined 3 new parameters.
***Its 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 doesnt 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, weve chosen to mark this field as immutable because most Zip Applications will automatically discard files with corrupted signatures. Hopefully thats not too confusing. Lets go ahead and take a look at our next field, Version Needed to Extract. We dont 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, lets see if we cant define this field in our Pit. Well place it in the Local File Header block directly below our signature.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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

Ok, well we see once again that weve provided a unique name for this element but weve also added 3 new parameters. Lets 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. Lets 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 dont have a great deal of information about this bit flag, but enough to get us started. Lets go ahead and create a 2 byte bit flag. 1 2 <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. Weve 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 dont have enough information to map out these bits just yet so lets 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, were not going to concern ourselves with the purpose of each flag. Rather, well begin by creating a each flag, assigning it a unique name, and defining its position and length in the bitstream. Dont forget to place the Flag elements inside our Flags element. 1 2 3 4 5 <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"/>
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

5 6 7 8 9 10 11 12 13 14 15 16 17 18

<Flag <Flag <Flag <Flag <Flag <Flag <Flag <Flag <Flag <Flag <Flag <Flag <Flag </Flags>

name="lfh_bf_Zeroed" size="1" position="3"/> name="lfh_bf_Deflate" size="1" position="4"/> name="lfh_bf_Patched" size="1" position="5"/> name="lfh_bf_Strong" size="1" position="6"/> name="lfh_bf_Unused1" size="1" position="7"/> name="lfh_bf_Unused2" size="1" position="8"/> name="lfh_bf_Unused3" size="1" position="9"/> name="lfh_bf_Unused4" size="1" position="10"/> name="lfh_bf_Efs" size="1" position="11"/> name="lfh_bf_Reserved1" size="1" position="12"/> name="lfh_bf_Enc_CD" size="1" position="13"/> name="lfh_bf_Reserved2" size="1" position="14"/> name="lfh_bf_Reserved3" size="1" position="15"/>

So you can see here that weve defined our 16 bit flags, each with a length of 1 representing a single bit. Hopefully this isnt too confusing. Now with that out of the way, lets 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 its a number by looking at its definition in Section J. 1 <Number name="lfh_CompMethod" size="16" endian="little" signed="false"/>

Good. Moving right along. Lets 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. 1 2 <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 wont 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, lets go ahead and create this element and tell Peach not to fuzz it. 1 <Number name="lfh_CRC32" size="32" endian="little" signed="false" mutable="false"

With that out of the way, lets continue by defining our next 4 fields, compressed size, uncompressed size, file name length, and extra field length. 1 2 3 4 <Number <Number <Number <Number name="lfh_CompSize" size="32" endian="little" signed="false"/> name="lfh_DecompSize" size="32" endian="little" signed="false"/> name="lfh_FileNameLen" size="16" endian="little" signed="false"/> name="lfh_ExtraFldLen" size="16" endian="little" signed="false"/>

As with our previous fields weve chosen the number element, defined a size, and marked these fields

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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 Peachs 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, well 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, lets go ahead and define two elements for our file name and extra field. 1 2 <String name="lfh_FileName"/> <String name="lfh_FldName"/>

Ok, now that weve created our fields lets apply the size relation. 1 2 3 4 5 6 7 8 9 10 <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 weve instructed Peach that whenever it parses the lfh_FileNameLen and

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

lfh_ExtraFldLen fields, to store this data and apply it as the size for lfh_FileName and lfh_FldName. Lets 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 cant 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, were 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. Were 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 wont be suitable to represent this field. Lets go ahead and use our fall-back, the blob element. 1 <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, weve 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 weve already marked the LocalFileHeader to repeat (using maxOccurs), lets go ahead and include section B (and Section C shortly) within the same block as our LocalFileHeader. It should look something like this. 1 2 3 4 5 6 7 8 9 10 <!-- A. Local file header --> <Block name="LocalFileHeader"> <String name="lfh_Signature" valueType="hex" value="504b0304" token="true" <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>
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

10 11 12 13 14 15 16 17 18 19 20 21 22

</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 arent immediately apparent when reading the specification. In fact I didnt 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), Ill go ahead and detail some of the nuances of the Zip file format below in an easier to read format and well 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 doesnt seem like a lot but it will here in a bit. Lets begin by building a basic representation of this block. 1 2 3 4 5 6 <!-- 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.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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 well 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, well do the following: 1 2 3 4 5 6 7 <!-- 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 weve 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, well go ahead and create two independent blocks for our file data; one which utilizes the size relation and another which doesnt (sort of). Since our size relation is actually applied to lfh_CompSizeData, well need to go ahead and update that of parameter to match our newly named file data element. Well also go ahead and add a when relation to each block so that Peach knows which one to select. 1 2 3 4 <!-- A. Local file header --> <Number name="lfh_CompSize" size="32" endian="little" signed="false"> <Relation type="size" of="lfh_CompSizeData"/> </Number>
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

</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). Weve 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 weve 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 dont have a block signature (more specifically, an item marked as a token), we wont have anyway of telling Peach what to look for to signify the termination of lfh_CompNoSizeData, our unsized blob. In other words, Peach wont be able to determine the size for this element, and will exit. Now, what Ive done is not necessarily a perfect solution. Based on what Ive seen with the Zip files that Ive sampled and parsed is that most (actually all that Ive tested) do begin with a block signature. Because of this, Ive 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 lets go ahead modify our Data Descriptor block to include the block signature. 1 2 3 4 5 6 7 8 9 10 11

<!-- 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').getInte <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').getInte <Blob name="lfh_CompNoSizeData" mutable="false"/> </Block> </Block>
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

11 12 13 14 15 16 17 18 19 20

</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 <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, lets 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 were 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 lets go ahead and create our choice element and populate it with our two blocks to accommodate both 4 and 8 byte sizes. Well precede our choice element with our Data Descriptor Signature and CRC32 fields as these wont change regardless of block selection. Our Choice structure should look like the following. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <!-- 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 <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>
Are you a developer? Try out the HTML to PDF API

With the above section, Peach will now be able to parse the lfh_Data block because weve provided it

open in browser PRO version

pdfcrowd.com

With the above section, Peach will now be able to parse the lfh_Data block because weve provided it with a token to look for signifying the end of that element. Unfortunately, weve 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 havent 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 weve 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, well go ahead and check for the existence of PK, the first 2 bytes of all Zip block signatures. To do this, well update the second element in our Zip64 block to look as follows: 1 <Number name="dd_DecompSize64" size="64" endian="little" signed="false" constraint

Good. Your final product should look as follows: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <!-- 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 <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">
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

22 23 24 25 26 27 28

<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, lets continue on. Looking back at the specification we see our next section, the Archive Decryption Header. Unfortunately since the specification doesnt provide any definition for this section, well 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. Well start by telling Peach to not fuzz our signature field, and well use a size relation again to determine the size of our variable length field. This block should look similar to the following: 1 2 3 4 5 <Block name="ArchiveExtraDataRecord" minOccurs="0" maxOccurs="1"> <String name="aedr_Sig" valueType="hex" value="504b0608" token="true" mutable <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. Well go ahead and set that to 1,024 just for safe measure, although in all likelihood well 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

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

[Digital Signature] size of data(2) => signature data Based on what weve learned during the Local File Header, lets go ahead and create one container block for the entire Central Directory Structure, and two sub-blocks, FileHeader and DigitalSignature. Well also go ahead and populate them with the data we see in the specification. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 <Block name="CentralDirectoryStructure"> <Block name="FileHeader" maxOccurs="1024"> <String name="cfh_Signature" valueType="hex" value="504b0102" token <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 <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"
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

42 43 44 45 46 47 48 49 50 51 52 53 54

<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 <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 theres one more thing were going to add. If we were to open up an archive containing a single file, wed 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, well 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 thats class. This defines the actual Fixup well be using. A full list of available Fixups can be found here. So with that said, well go ahead and make the following change. Dont be to worried about understanding the syntax right now. Ill be doing a follow up article on Fixups and how to create your own. 1 2 3 4 5 6 <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

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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. Well 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. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <Block name="Zip64EndOfCentralDirectoryRecord"> <String name="z64eocd_Signature" valueType="hex" value="504b0606" token="true" <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= <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, lets 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), itll 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, lets see if we cant 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: 1 2 3 4 <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"/>
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

4 5 6 7

<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, well leave it as it is. So lets go ahead and replace our extensible data sector with a block, and place the code above in our block. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <Block name="Zip64EndOfCentralDirectoryRecord"> <String name="z64eocd_Signature" valueType="hex" value="504b0606" token="true" <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= <Block name="z64eocd_Z64ExtensDS"> <Number name="z64eocd_ExtensDs_Header" size="16" endian="little" signed <Number name="z64eocd_ExtensDs_Size" size="32" endian="little" signed <Relation type="size" of="z64eocd_ExtensDs_Data"/> </Number> <Blob name="z64eocd_ExtensDs_Data"/> </Block> </Block> </Block>

Before we move on, Id like to make one additional change. Were going to add a size relation to z64eocd_SizeOfCenDir and z64eocd_OffsetToCenDir. However, based on the structure of our Pit we cant just add a standard size relation otherwise itll prevent us from properly parsing the Zip file. Instead, were 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 lets go ahead and make the following changes: 1 2 3 4 5 6 <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, weve 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.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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. Lets go ahead and create this block in our Pit. 1 2 3 4 5 6 7 <!-- H. Zip64 end of central directory locator --> <Block name="Zip64EndOfCentralDirectoryLocator" minOccurs="0" maxOccurs="1"> <String name="eocdl_Signature" valueType="hex" value="504b0607" token="true" <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 weve 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. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <Block name="EndOfCentralDirectoryRecord"> <String name="eocd_Signature" valueType="hex" value="504b0506" token="true" <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 weve 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 youre 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.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

Our completed DataModel should look like the following: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <DataModel name="ZipFileFormat"> <!-- A. Local file header --> <Block name="LocalFileHeader" maxOccurs="1024"> <String name="lfh_Signature" valueType="hex" value="504b0304" token="true" <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"/>-->
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

<!--<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" <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= </Block> <Block name="dd_32"> <Number name="dd_CompSize32" size="32" endian="little" signed="false" <Number name="dd_DecompSize32" size="32" endian="little" signed= </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" <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= <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"/>
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

<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 <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 <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 <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= <Number name="z64eocd_SofCDDiskNum" size="32" endian="little" signed
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194

<Number name="z64eocd_SofCDDiskNum" size="32" endian="little" signed <Number name="z64eocd_CDOnDisk" size="64" endian="little" signed="false" <Number name="z64eocd_TotNumEntries" size="64" endian="little" signed <Number name="z64eocd_SizeOfCenDir" size="64" endian="little" signed <Number name="z64eocd_OffsetToCenDir" size="64" endian="little" signed <Block name="z64eocd_Z64ExtensDS" minOccurs="0" maxOccurs="1"> <Number name="z64eocd_ExtensDs_Header" size="16" endian="little" signed <Number name="z64eocd_ExtensDs_Size" size="32" endian="little" signed <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= <String name="eocdl_Signature" valueType="hex" value="504b0607" token= <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" <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= <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 weve 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, well go ahead and discuss them anyway. Lets take a look at our StateModel.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

discuss them anyway. Lets take a look at our StateModel.

StateModel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <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 Ive 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 theres no point in me reinventing the wheel. Ill 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 fuzzers 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, thats all well 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.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

The Action element is responsible for instructing Peach exactly what do do with our data. Before we modify the Actions defined in our template, lets 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 Peachs 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. Well 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 well only need to modify 2 lines within the StateModel. First lets modify the Action call: 1 <Action type="call" method="notepad.exe" publisher="launch"/>

Rather than including the executable, well specify a unique string to tie our StateModel and Agent together. Most of the documentation and samples Mikes provided with the Peach framework use the variable ScoobySnacks and well do the same here. However its important to note that this string can be anything as long as our Agent configuration matches it. More on that in a bit. 1 <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 Microsofts !Exploitable (pronounced BangExploitable) which is useful when classifying the exploitability of crashes. Further information on

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

!exploitable can be found at here. Heres what you should be seeing in the FileFuzzerGui.xml: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <!-- 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 well 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. Well 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 applications heap. This parameter only accepts the executable name and does not require the full file path. For testing purposes, well try to re-identify vulnerabilities associated with the GlobalScape Cutezip Archiver. You can find a vulnerable copy of this application here.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

Once youve installed CuteZip, we can go ahead and apply our 3 required changes to this section of the template. Well 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 well 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: 1 2 3 4 5 6 7 8 9 <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. Lets take a look at the configuration for this section defined in the template. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <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 well be using our named Agent, LocalAgent, and our named StateModel, State. We also see two Publishers being defined, file.FileWrite and process.DebuggerLauncherGui. Were actually going to go ahead and remove both of these publishers and combine them with one (sort of) to accomplish the same job.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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, well 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. Lets 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: 1 2 3 4 5 6 7 8 9 <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, well go ahead and add the FileWriteLauncher (NonGUI) Publisher to our Test element. Although well have both Publishers in our Test block, we shouldnt 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, lets go ahead and comment our our file.FileWriterLauncherGui Publisher. If we decide to fuzz an application with a GUI well simply comment out our FileWriterLauncher and uncomment FileWriterLauncherGui. Your Test configuration should look like the following: 1 2 3 4 5 6 7 <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"/>
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

7 8 9 10 11 12 13

<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 weve only defined a single Test section. Your Run section should look like the following: 1 2 3 4 5 6 <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 weve finished our Pit, well need to go ahead and do a few test runs before we actually kick off the fuzzer. But before we do that well 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: 1 <Data name="data" fileName="C:\peachfuzz\Test.zip"/>

Ok, with our Pit updated, the first thing that well do is run a quick configuration check thatll 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. 1 peach.bat -t zip.xml

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

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

With our check complete, well 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. Itll parse the sample zip file, regenerate another copy and provide this data to our target application. To do so, well run the following command: 1 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 weve 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:

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

Also take note of the Agent output:

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

***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 theres 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, were going to take our fuzzed.zip, the file created by Peach and well 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 shouldnt 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, Im 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.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

Excellent. Were just about ready to begin fuzzing. Before we do, lets give it one more sample debug run. 1 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 doesnt provide us with an option to automatically overwrite old files via the command line. Because of this, well 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, lets go ahead and download the AutoHotKey application here. Once you have the AutoHotKey installed, lets go ahead and open up the popupkiller.py in our favorite editor. You can find this file at the following location:

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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 wed 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 well fire up WindowSpy, an application included with the AutoHotKey package. Once weve launched WindowSpy, lets go ahead and click on the popup generated.
If youre 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.

In the screenshot above, we can confirm that the popup window title is Confirm File Replace and the button text were looking for is &Yes. With this information, lets add the following line to our popupkiller.py: 1 [ 'Confirm File Replace', None, '&Yes', False ],
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

Now to test it, lets go ahead and launch popup killer by executing the following command: 1 C:\peachfuzz\tools\> python popupkiller.py

Well then manually trigger the overwrite confirmation window by launching our application from the command-line. If we dont see the popup, were good to go! Now that weve 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, its important that we consider how much of the application were 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

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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. Well run minset against a quick sample to see what it provides. Ive 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 cant 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 youve downloaded the archive, unpack it to the following directory: 1 C:\(Path to Peach Installation)\tools\minset\zip

Now were ready to fire up minset. For this test, well be checking our files against the 7-Zip application. If you dont have it already, you can download it here. Open up a command window and execute the following command in the minset directory: 1 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.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

Once minset completes, itll go ahead and copy the minimal file set to the directory we specified with the -m option. For this discussion, well use the Zip files contained in this archive for our fuzz process. Now that we have several files to mutate well need to decide how wed like to fuzz them. Lets modify our Pit to use the Test.zip archive as our base mutation file and run our fuzzer. Well 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, well 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-

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

level of the Test block and not to one of the sub elements such as the Agent, StateModel, or Publisher. 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 <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 <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 weve instructed Peach to use the random mutation strategy, fuzzing a maximum of 7 fields, and well be running 1500 iterations per file before moving on. Before we start our fuzzer, were 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 wed 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: 1 peach.bat --seed 1305094305.21 --skipto 500 zip.xml

Running Our Fuzzer


Ok, now its time to get down to business. If youve added the random mutation strategy to your Test block above, lets go ahead and comment that out for now. Well also be mutating the Test.zip file so make sure you update the Data element within your StateModel. Once youve made these changes, lets open up a command window and run the following command.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

***Remember! Since well be fuzzing the CuteZip application, dont forget to fire up popupkiller.py before our test begins!

peach.bat zip.xml

Once the fuzz process has begun, well let it run for a while. After a few minutes you should notice that Peach has been able to trigger a few exceptions. Lets 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 lets change to our CuteZip logging directory (specified in the Logger element of our Run block) and list the directory contents. 1 2 3 [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. Lets change in this directory as well. 1 2 3 [pyoor@Unknown logs.zip.cutezip]$ cd zip.xml_2011Jul18174449/ [pyoor@Unknown zip.xml_2011Jul18174449]$ ls Faults status.txt

Here were 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. Lets take a quick look at status.txt. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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 Mon Mon Mon Mon Mon Jul Jul Jul Jul Jul Jul 18 18 18 18 18 18 13:44:53 13:44:53 13:44:53 13:44:53 13:54:33 13:54:33 2011: 2011: 2011: 2011: 2011: 2011: Test starting: TheTest On test variation # 1 Fault was detected on test 44 Origional file name: C:\peachfuzz\minset\test.zip

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

Mon Mon Mon Mon Mon Mon Mon Mon Mon Mon Mon Mon Mon Mon Mon Mon

Jul Jul Jul Jul Jul Jul Jul Jul Jul Jul Jul Jul Jul Jul Jul Jul

18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18

13:54:33 13:59:47 13:59:47 14:03:38 14:03:38 14:36:13 14:36:13 14:40:22 14:40:23 14:52:11 14:52:11 14:59:48 14:59:48 15:07:58 15:07:58 15:17:12

2011: 2011: 2011: 2011: 2011: 2011: 2011: 2011: 2011: 2011: 2011: 2011: 2011: 2011: 2011: 2011:

Origional Fault was Origional Fault was Origional Fault was Origional Fault was Origional Fault was Origional Fault was Origional Fault was Origional Fault was

file name: C:\peachfuzz\minset\test.zip detected on test 68 file name: C:\peachfuzz\minset\test.zip detected on test 85 file name: C:\peachfuzz\minset\test.zip detected on test 231 file name: C:\peachfuzz\minset\test.zip detected on test 248 file name: C:\peachfuzz\minset\test.zip detected on test 293 file name: C:\peachfuzz\minset\test.zip detected on test 326 file name: C:\peachfuzz\minset\test.zip detected on test 361 file name: C:\peachfuzz\minset\test.zip 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 were 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. 1 2 AgentConnectionFailed EXPLOITABLE_WriteAV_0x0a617d5e_0x08266247 UNKNOWN_ReadAV_0x4c52190c_0x6b36390c UNKNOWN_TaintedDataPassedToFunction_0x0160787d_0x216e3a20

Inside EXPLOITABLE_WriteAV_0x0a617d5e_0x08266247, we see one directory, 400 (named after the test case number which triggered the crash). Lets 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. Lets take a quick look at the LocalAgent_StackTrace.txt. Specifically the registers, faulting instruction, and stack unwind.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

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 cant be certain). Also the stack wind doesnt provide us with anything obvious as to the cause of the crash. Lets rename our data_1_output_Named_49.txt to cutezip-400.zip. Next well open this file and our original Test.zip in the 010 binary editor and perform a diff.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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.

Im 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, lets 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. Ill let !pvefindaddr do all the talking for me: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 069BFAF8 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D ------------------------------------------------------------------------Searching for metasploit pattern references ------------------------------------------------------------------------[1] Searching for first 8 characters of Metasploit pattern : Aa0Aa1Aa ===================================================================== - Found begin of Metasploit pattern at 0x069bfaf8 ** Could not find begin of Metasploit pattern (unicode expanded) in memory ! ** [2] Checking register addresses and contents ============================================ - Register EBX points to Metasploit pattern at position 467 - Register ESI points to Metasploit pattern at position 1288 [3] Checking seh chain ====================== - Checking seh chain entry at 0x069bff74, value 42346d42 => record is overwritten with Metasploit pattern after 1152 bytes
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D 0BADF00D

=> record is overwritten with Metasploit pattern after 1152 bytes - Checking seh chain entry at 0x336d4232, value c0c0c0c0 - Checking seh chain entry at 0xc0c0c0c0, value c0c0c0c0 Evaluated 3 SEH entries ------------------------------------------------------------------------Exploit payload information and suggestions : --------------------------------------------[+] Type of exploit : SEH (SE Handler is overwritten) Offset to next SEH : 1148 Offset to SE Handler : 1152 [+] Payload suggestion (perl) : my $junk="\x41" x 1148; my $nseh="\xeb\x06\x90\x90"; my $seh= XXXXXXXX; #pop pop ret - use !pvefindaddr p -n to find a suitable address my $nops="\x90" x 24; my $shellcode="<your shellcode here>"; my $payload = $junk.$nseh.$seh.$nops.$shellcode; [+] Read more about this type of exploit at http://www.corelan.be:8800/index.php/2009/07/25/writing-buffer-overflow-exploits-a-quick-and-basic-tutorial-part ---------------------------------------------------------------

I chose to use !pvefindaddr for the above output but for those of you who didnt know, Team Corelans 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, its 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, well 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, well more than likely only see our Filename elements mutated along with other elements that dont 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: 1 peach.bat --seed 1311053420.97 --skipto 95 zip.pit
Are you a developer? Try out the HTML to PDF API

open in browser PRO version

pdfcrowd.com

As with our previous example, well 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, well execute the following command: 1

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

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

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

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

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, thats it. Hopefully it wasnt too terrible. Please feel free to post any comments, questions or requests! Also, Id 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!

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

file format, fuzzer, peach, tutorial, zip

18 Comments for this entry


Nicolas
July 21st, 2011 on 6:45 am

Excellent post, its the most complete information on building a Peach pit and using Peach fuzzer to its full extend. Reply

Red
July 21st, 2011 on 12:39 pm

Very good article! Do you mind if I translate it into Russian and will publish on its website? Reply pyoor
July 21st, 2011 on 2:31 pm

Certainly. Please dont modify the content or remove references to the original source. Reply

white
August 3rd, 2011 on 10:17 am

hi, im run peach 2.3.9 but get an error at rand.py on line 59. Did you fix that in peach? Can you share me the way you fix? Regards, Sorry for my bad english ! Reply

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

pyoor
August 4th, 2011 on 10:08 am

Could you provide me with a bit more detail on the error?

Reply

xssww2
August 12th, 2011 on 6:01 pm

do you sure that the second block of the element will be generated? I think that the only first block will be output. see: http://groups.google.com/group/peachfuzz/browse_thread/thread/ee2f3429856df70d/10f904c8fd3b9d90? lnk=gst&q=choice#10f904c8fd3b9d90 Reply xssww2
August 12th, 2011 on 6:01 pm

element: Choice

Reply pyoor
August 12th, 2011 on 8:06 pm

xssww2: Short answer, yes. If youre referring to the dd_chooser choice element, itll first begin cracking the dd_64 block. If the constraint fails, Peach will discard this block and select the dd_32. If this fails as well neither block will be chosen and Peach will move to the next major block in the list. If youre seeing otherwise please let me know. Reply

mushu
August 29th, 2011 on 4:50 am

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

] Peach 2.3.9 DEV Runtime ] Copyright (c) Michael Eddington [*] Optmizing DataModel for cracking: ZipFileFormat [*] Cracking data from C:\fuzz\test.zip into ZipFileFormat [*] Total time to crack data: 0.08 [*] Building relation cache Traceback (most recent call last): File C:\Peach\\peach.py, line 393, in parser.asParser(args[0]) File C:\Peach\Peach\Analyzers\pit.py, line 57, in asParser return parser.parse(uri) File C:\Peach\Peach\Engine\parser.py, line 161, in parse obj = self.HandleDocument(doc, uri) File C:\Peach\Peach\Engine\parser.py, line 364, in HandleDocument tests = self.HandleTest(child, None) File C:\Peach\Peach\Engine\parser.py, line 2464, in HandleTest test.mutator = self.HandleFuzzingStrategy(child, test) File C:\Peach\Peach\Engine\parser.py, line 2511, in HandleFuzzingStrategy exec(strategy = PeachXml_%s(node, parent) % cls) File , line 1, in File C:\Peach\Peach\MutateStrategies\rand.py, line 59, in __init__ RandomMutationStrategy.SEED = Engine.context.SEED AttributeError: NoneType object has no attribute SEED Reply pyoor
August 30th, 2011 on 2:12 am

Without the syntax that caused this error I cant be certain but I imagine youre seeing this error when runningpeach.bat -t zip.xml. Im not sure why but Peach will throw an error when running the syntax test with the random mutation strategy enabled in the PIT. To run a syntax check, simply comment out the Strategy element within your test model. To use it during fuzzing remove the comment. Reply mushu
August 30th, 2011 on 1:24 pm

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

thanks,pyoor,it works now

Reply

Jinghao
November 29th, 2011 on 1:39 am

Hi, nice guide. From my understanding, this process will fuzz the test.zip, and check by cutezip. Am I right? If I just want to fuzz the test.zip file, and save the fuzzed zip file to some place. No need to monitor and check, just need the fuzzed result. What should I do? Thanks. Reply pyoor
November 29th, 2011 on 4:49 am

Jinghao, Yes, you are correct. Also, have a look at the following: http://peachfuzzer.com/HowDoI#Generate_All_Fuzzed_Files This will generate all fuzzed files and write them to disk. Reply Jinghao
December 6th, 2011 on 5:52 am

When I use this xml to fuzz, the CPU usage will grow up quickly. Then the whole system will be hang. It is very strange. Thanks,

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

-Jinghao Reply pyoor


December 7th, 2011 on 12:59 am

Jinghao, This is more than likely dependent on the application youve chosen to fuzz. Once the sample file has been cracked, Peach uses very little resources for the actual fuzz process. Try looking at alternative monitors available in Peach as this may cause the application to spike in CPU usage. Reply Jinghao
December 12th, 2011 on 2:31 am

Thanks for your reply. Actually, I dont use any monitor. I just generated the fuzzed files. And after remove the random Strategy, it will be OK. I dont know why. Thanks.

Steven John
February 2nd, 2012 on 12:30 pm

Hi pyoor, Excellent writeup. Thanks for your patience. I tried to generate fuzz files using your datamodel. I am receiving the following error while executing peach.bat zip.xml. I didnt receive syntax errors by the way. Any help would be appreciated. Thanks ] Peach 2.3.8 Runtime ] Copyright (c) Michael Eddington [*] Starting run DefaultRun [-] Test: TheTest (None) [1:?:?] Element: N/A

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

Mutator: N/A PK\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ x00\x00\x00\x00\x00\x00\x00 PK\x01\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\ x00\x00\x00\x00\x00\x00\x00 (, AttributeError(ExpressionFixup instance ha s no attribute getRoot,), ) [1:?:?] Caught error on receave, ignoring [None] Traceback (most recent call last): File peach.py, line 516, in File Peach\Engine\engine.pyo, line 471, in Run File Peach\Engine\engine.pyo, line 678, in _runTest File Peach\Engine\state.pyo, line 136, in run File Peach\Engine\state.pyo, line 253, in _runState File Peach\Engine\dom.pyo, line 2851, in getValue File Peach\Engine\dom.pyo, line 2363, in getValue File Peach\Engine\dom.pyo, line 2976, in getRawValue File Peach\Engine\dom.pyo, line 2918, in getInternalValue File Peach\Engine\dom.pyo, line 2363, in getValue File Peach\Engine\dom.pyo, line 3402, in getRawValue File Peach\Engine\dom.pyo, line 3334, in getInternalValue File Peach\Engine\dom.pyo, line 2363, in getValue File Peach\Engine\dom.pyo, line 3402, in getRawValue File Peach\Engine\dom.pyo, line 3334, in getInternalValue File Peach\Engine\dom.pyo, line 2363, in getValue File Peach\Engine\dom.pyo, line 3626, in getRawValue File Peach\Engine\dom.pyo, line 3539, in getInternalValue File Peach\Engine\dom.pyo, line 2233, in getRelationValue File Peach\Engine\dom.pyo, line 2313, in getSize File Peach\Engine\dom.pyo, line 2363, in getValue File Peach\Engine\dom.pyo, line 4123, in getRawValue File Peach\Engine\dom.pyo, line 4100, in getInternalValue File Peach\fixup.pyo, line 60, in dofixup File Peach\Fixups\checksums.pyo, line 58, in fixup File Peach\Engine\common.pyo, line 190, in evalEvent File Peach\Engine\common.pyo, line 111, in buildImports AttributeError: ExpressionFixup instance has no attribute getRoot

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

Reply pyoor
February 13th, 2012 on 4:56 pm

Steven, Are you running the latest svn of Peach? Some of the features included in those pits are only available via svn. If youre still having issues let me know. Reply

Leave a Reply
Name (required) Mail (will not be published) (required) Website

Leave com m ent

Notify me of follow-up comments by email. Notify me of new posts by email.

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

RSS feed for this post (comments) TrackBack URI

Copyright 1996-2010 Flinkd!. All rights reserved.

iDream theme by Templates Next | Pow ered by WordPress

open in browser PRO version

Are you a developer? Try out the HTML to PDF API

pdfcrowd.com

Das könnte Ihnen auch gefallen