Simple Bitmap File Fuzzer

On our previous post we studied a dump fuzzer where we prepared malformed input pdf files by using bit flipping technique. Let’s get into a little deeper and prepare the malformed input files based on the file structure for bitmap files.

What is a bitmap file? On its wiki site we can see header information of a sample bitmap file:

Offset Size Hex Value Value Description
BMP Header
0h 2 42 4D “BM” ID field (42h, 4Dh)
2h 4 46 00 00 00 70 bytes (54+16) Size of the BMP file
6h 2 00 00 Unused Application specific
8h 2 00 00 Unused Application specific
Ah 4 36 00 00 00 54 bytes (14+40) Offset where the pixel array (bitmap data) can be found
DIB Header
Eh 4 28 00 00 00 40 bytes Number of bytes in the DIB header (from this point)
12h 4 02 00 00 00 2 pixels (left to right order) Width of the bitmap in pixels
16h 4 02 00 00 00 2 pixels (bottom to top order) Height of the bitmap in pixels. Positive for bottom to top pixel order.
1Ah 2 01 00 1 plane Number of color planes being used
1Ch 2 18 00 24 bits Number of bits per pixel
1Eh 4 00 00 00 00 0 BI_RGB, no pixel array compression used
22h 4 10 00 00 00 16 bytes Size of the raw bitmap data (including padding)
26h 4 13 0B 00 00 2835 pixels/meter horizontal Print resolution of the image,
72 DPI × 39.3701 inches per meter yields 2834.6472
2Ah 4 13 0B 00 00 2835 pixels/meter vertical
2Eh 4 00 00 00 00 0 colors Number of colors in the palette
32h 4 00 00 00 00 0 important colors 0 means all colors are important
Start of pixel array (bitmap data)
36h 3 00 00 FF 0 0 255 Red, Pixel (0,1)
39h 3 FF FF FF 255 255 255 White, Pixel (1,1)
3Ch 2 00 00 0 0 Padding for 4 byte alignment (could be a value other than zero)
3Eh 3 FF 00 00 255 0 0 Blue, Pixel (0,0)
41h 3 00 FF 00 0 255 0 Green, Pixel (1,0)
44h 2 00 00 0 0 Padding for 4 byte alignment (could be a value other than zero)

If concatenate all these Hex values on an editor and save it in .bmp format:

Bitmap Hex Format

and then open it with an picture viewer program we can see the actual image:

Bitmap Image

It is like magic, isn’t it 🙂

With this knowledge in mind, now we can prepare our fuzzer of out of 3 files. First a protocol structure, secondly a fuzz input generator and finally the fuzzer python file itself.

By referencing the header structure above, let’s build our class in python. (We could have built in nested order but for this study this must be sufficient):


 
class Structure:
'Structure for BMP Image File'
 
BMPStructure = [{'Name': 'bfType' , 'Type': 'C', 'Default': 'BM', 'Size': -1},
{'Name': 'bfSize' , 'Type': 'L', 'Default': '\x33\x33\x33\x33', 'Size': 4, 'Order': 'Reverse'},
{'Name': 'bfReserved1' , 'Type': 'C', 'Default': '\x00\x00', 'Size': -1},
{'Name': 'bfReserved2' , 'Type': 'C', 'Default': '\x00\x00', 'Size': -1},
{'Name': 'bfOffBits' , 'Type': 'C', 'Default': '\x36\x00\x00\x00', 'Size': -1},
 
{'Name': 'biSize' , 'Type': 'C', 'Default': '\x28\x00\x00\x00', 'Size': -1},
{'Name': 'biWidth' , 'Type': 'B', 'Default': '\x02\x00\x00\x00', 'Size': 4},
{'Name': 'biHeight' , 'Type': 'B', 'Default': '\x02\x00\x00\x00', 'Size': 4},
{'Name': 'biPlanes' , 'Type': 'B', 'Default': '\x01\x00', 'Size': 2},
{'Name': 'biBitCount' , 'Type': 'B', 'Default': '\x18\x00', 'Size': 2},
{'Name': 'biCompression' , 'Type': 'C', 'Default': '\x00\x00\x00\x00', 'Size': -1},
{'Name': 'biSizeImage' , 'Type': 'B', 'Default': '\x10\x00\x00\x00', 'Size': 4},
{'Name': 'biXPelsPerMeter' , 'Type': 'B', 'Default': '\x13\x0B\x00\x00', 'Size': 4},
{'Name': 'biYPelsPerMeter' , 'Type': 'B', 'Default': '\x13\x0B\x00\x00', 'Size': 4},
{'Name': 'biClrUsed' , 'Type': 'B', 'Default': '\x00\x00\x00\x00', 'Size': 4},
{'Name': 'biClrImportant' , 'Type': 'B', 'Default': '\x00\x00\x00\x00', 'Size': 4},
 
{'Name': 'aColors', 'Type': 'B', 'Default': '\xFF\x20', 'Size': 64},
 
{'Name': 'aBitmapBits', 'Type': 'B', 'Size': 64,
'Default': '\x00\x00\xFF\xFF\xFF\xFF\x00\x00\xFF\x00\x00\x00\xFF\x00\x00\x00'}]
 
def __init__(self):
print 'Structure Instance Created'
def returnStructure(self):
return self.BMPStructure


On this structure, we are going to be interested fuzzing only Type B (B is for Buffer, C is for Constant, and L is for Length). The generator class will provide us the input for fuzzing:



class Generator:
'Generator for Malformed Data'
 
MalformedValues = [
('RepeatedAx1','A'), ('RepeatedNULLx1','\x00'),
('Numeric -1','-1'), ('Numeric -2','-2'), ('Numeric 0','0'),
('Binary -1 (BYTE)','\xFF'), ('Binary -2 (BYTE)','\xFE'),
('Binary -2 (2 BYTES)','\xFF\xFE'), ('Binary -2 (2 BYTES Reverse)','\xFE\xFF'),
('Format String %sx1','%s'), ('Format String %xx1','%x')]
 
def __init__(self):
print 'Generator Created'
def returnCount(self):
return len(self.MalformedValues)
 
def returnValueAt(self, value):
return self.MalformedValues[value][1]
 
def returnNameAt(self, value):
return self.MalformedValues[value][0]


We can easily extend our list for fuzz input. Now finally we can construct our fuzzer class:



#!C:\Python27\python.exe
 
import string
 
from protocol import Protocol
from structure import Structure
from generator import Generator
 
##***************************************************************************
## This function iterates over the protocol structure and
## fuzzies input from generator data structure into available buffer
##***************************************************************************
def iteratefuzz(structure, fuzz):
  for insertpoint in range(0, len(structure)):
    fileinput = ''
    fuzzed = 'false'
    print 'FUZZING FOR VALUE: ', fuzzvalue
    for row in range(0, len(structure)):
      print structure[row]['Name']
      if row == insertpoint and structure[row]['Type'] == 'B':
            fuzzed = 'true'
            size = structure[row]['Size']
            fuzzer = fuzz
            while (len(fuzzer) < size):
              fuzzer = fuzzer + fuzz
            fileinput = fileinput + fuzzer
      else:
        fileinput = fileinput + structure[row]['Default']
 
    print fileinput.encode('hex')
 
    if fuzz == '\x00':
      fuzz = 'null'
 
    if fuzzed == 'true':
      # Open a file
      fo = open("images/test" + fuzz + str(insertpoint) + ".bmp", "wb")
      fo.write(fileinput);
 
      # Close opend file
      fo.close()
 
 
 
  
##****************************************************************************  
  
##refProtocol = Protocol()
##GlobalProtocol = refProtocol.returnStructure()
 
refStructure = Structure()
GlobalStructure = refStructure.returnStructure()
refGenerator = Generator()
CombinationCount = refGenerator.returnCount()
 
 
print 'Test cases:', CombinationCount , '\n'
 
iterate(GlobalStructure)
 
for x in range(0, CombinationCount):
  print refGenerator.returnNameAt(x)
  fuzzvalue = refGenerator.returnValueAt(x)
  iteratefuzz(GlobalStructure, fuzzvalue)


Before running fuzzer, create a folder with the name “images” and then run the fuzzer.py. Now, you should be able to see 122 sample images created based on our input.

Fuzzer Running

It’s possible now to monitor opening and closing these sample files with MS Paint program in order to catch a crash. We can use the python code from our previous study.

But now I want to switch from this simple study to a comprehensive fuzzer program: Peach Fuzzer. You can learn how to install and use Peach Fuzzer on its own website. Here let’s try to build a Peach PIT file (XML layout for input files of Peach Fuzzer). Let’s file the following code as bmp.xml:



<?xml version="1.0" encoding="utf-8"?>
<Peach xmlns="http://peachfuzzer.com/2012/Peach" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://peachfuzzer.com/2012/Peach /peach/peach.xsd">
 
<Defaults>
<Number signed="false" />
</Defaults>
<DataModel name="DIB">
 
    <Block name="Data">
        <Number name="biSize" size="32" value="40" />
        <Number name="biWidth" size="32" />
        <Number name="biHeight" size="32" />
        <Number name="biPlanes" size="16" />
        <Number name="biBitCount" size="16" />
        <Number name="biCompression" size="32" />
        <Number name="biSizeImage" size="32" />
        <Number name="biXPelsPerMeter" size="32" />
        <Number name="biYPelsPerMeter" size="32" />
        <Number name="biClrUsed" size="32" />
        <Number name="biClrImportant" size="32" />    
    </Block>
</DataModel>
<DataModel name="BMPData">
    <Block name="Data">
        <Blob name="ExtraData" />
    </Block>
</DataModel>
<!-- Defines the format of a BMP file -->
<DataModel name="BMP">
    <String name="ID" value="bmfh" token="false"/>
<String value="BM" token="true" />
<Number size="32" />
<Number size="16" />
<Number size="16" />
<Number size="32" value="54" />   
 
<Block ref="DIB"/>
<Number name="aColors" size="16" />
<Block ref="BMPData"/>    
 
</DataModel>
 
<!-- This is our simple BMP state model -->
<StateModel name="TheState" initialState="Initial">
<State name="Initial">
 
<!-- Write out our .bmp file -->
<Action type="output">
<DataModel ref="BMP"/>
<!-- This is our sample file to read in -->
<Data fileName="samples_bmp/*.bmp"/>
</Action>
 
<Action type="close"/>
 
<!-- Launch the target process -->
<Action type="call" method="LaunchViewer" publisher="Peach.Agent" />
</State>
</StateModel>
 
<!-- TODO: Configure Agent -->
<Agent name="WinAgent">
   <Monitor class="WindowsDebugger">
 
<!-- The command line to run.  Notice the filename provided matched up
to what is provided below in the Publisher configuration -->
<Param name="CommandLine" value="mspaint.exe fuzzed.bmp" />
 
<!-- This parameter will cause the debugger to wait for an action-call in
the state model with a method="StartMPlayer" before running
program.-->
<Param name="StartOnCall" value="LaunchViewer" />
 
<!-- This parameter will cause the monitor to terminate the process
once the CPU usage reaches zero.-->
<Param name="CpuKill" value="true"/>
 
</Monitor>
 
<!-- Enable heap debugging on our process as well. -->
<Monitor class="PageHeap">
<Param name="Executable" value="mspaint.exe"/>
</Monitor>
 
</Agent>
<Test name="Default">
<Agent ref="WinAgent" platform="windows"/>
 
<StateModel ref="TheState"/>
 
<Publisher class="File">
<Param name="FileName" value="fuzzed.bmp"/>
</Publisher>
 
<Strategy class="Random"/>
 
<Logger class="Filesystem">
<Param name="Path" value="logs" />
</Logger>
</Test>
 
</Peach>
<!-- end -->


When we prepare some sample files under samples_bmp directory and run peach, we can see the fuzzer in action:

Peach Fuzzer Running