In Part 1 of Tutorial 2 we covered how to change the output format of nodes from XML to something appropriate for the data format. However most data formats have another requirement, and that is they contain data that depends on another part of the format, for instance a byte length of the file, or a count of a data block. So in Part 2 we are going to show how Fuzzware updates data values in the data format. Fuzzware updates values via XML Processing Instructions (PI). XML PI are special nodes inside the XML file that are completely ignored by the software reading the XML, unless the PI is targeted specifically at the software reading the XML. They have the form: <?ApplicationName Value?>
Fuzzware uses an executable called Schemer to fuzz data, so an example of a PI that Schemer would try to process would be: <?Schemer ByteLength="mdat2"?>
For Fuzzware the PI applies to the XML node immediately following the PI.
So how does the PI help us update data values in the data format? Well Fuzzware uses PI in pairs, it uses one PI to give a node an Id, e.g. <?Schemer Id="mdat2"?> <c2x:mdat> …
It uses the second PI to specify how a node should be updated given the Id of another node, e.g. <?Schemer ByteLength="mdat2"?> <c2x:mdatLength>9122</c2x:mdatLength> …
Fuzzware takes the value of the PI, ByteLength="mdat2", and reads this as Function="Id", it will then process this value as "Update the value of next XML node using Function with input the node with Id". So our example above would translate to "Update the node c2x:mdatLength using the function ByteLength with input the node with Id mdat2". Or to put it another may, update c2x:mdatLength with the ByteLength of node c2x:mdat. Note for the ByteLength function, Fuzzware will create the output byte array for c2x:mdat internally (obeying whatever schema attribute commands that were specified) and use this length to update c2x:mdatLength. It's important to note that adding XML PI to an XML file will (or at least should) not affect any other XML processor that reads this XML file as it should ignore any PI that is not targeted at it or that it does not understand. So what functions inside the PI does Fuzzware understand? These are listed in Schemas\XMLProcInstCommands.xsd or in the References section here. By far the most common function you will use is ByteLength. Actually Fuzzware understands multiple functions for the Value part of the PI (separated by space), e.g. <?Schemer ByteLength="FileHeader1" Order="10" ?> <rar:Size>43</rar:Size>
This introduces another PI command, Order. Sometimes it is important the order in which the PI functions are evaluated, consider the following from the WinRAR example: <?Schemer Id="FileHeader1" ?> <rar:FileHeader> <?Schemer CRC32="CRCBlock1" KeepStartBytes="2"?> <rar:FH_CRC>0000</rar:FH_CRC> <?Schemer Id="CRCBlock1"?> <rar:FH_CRCBlock> <rar:FileHeaderBlock> <rar:Type>74</rar:Type> <rar:Flags>4080</rar:Flags> <?Schemer ByteLength="FileHeader1" Order="10" ?> <rar:Size>43</rar:Size> </rar:FileHeaderBlock> …
From this we see that rar:FH_CRC will be updated with the CRC value of the rar:FH_CRCBlock XML, however rar:FH_CRCBlock has a child node rar:Size that also needs to be updated. The important point is that we need to update rar:Size before we update rar:FH_CRC otherwise our CRC value will be calculated on the wrong data. This is where specifying Order solves the problem. The default Order for all Fuzzware PI is 100, and a lower value ensures that PI gets processed before a PI with a higher Order. So in this example rar:Size has a PI with an Order of 10 which is lower than the Order of the PI for FH_CRC (defaults to 100), so the PI for rar:Size will be processed first.
Really the most common scenario in which Fuzzware PI are used is in updating lengths, and then the most common scenario is the file length. This can be achived quite easily by adding an Id PI above the root node of the XML and then adding a ByteLength PI above the node that holds the file length, e.g. <?Schemer Id="RootNode"?> <eg:RootNode> … <?Schemer ByteLength="RootNode"?> <eg:FileSize>0</eg:FileSize> … </eg:RootNode>
Lastly, should your format have some particularily complicated requirement to update a node in a special way, there are some Fuzzware PI values that allow the node with the given Id to be passed to custom .Net code, and the result used to populate the node assocaiated with the PI (see References section Custom Code).
Tasks 1. Update the BMP XML file from Tutorial 2 Part 1 so that its bmp:FileSize XML node gets updated automatically. 2. Review the other Fuzzware Processing Instructions.
|