Basit Bitmap Dosya Bulayıcısı

Bir önceki gönderimizde bit flipping tekniği ile hazırladığımız bozulmuş pdf dosyalarını hazırlayarak körleme usulü bulama konusu üzerinde çalışmıştık. Şimdi bir seviye daha dibe dalalım ve bitmap dosya yapısını bulayan bir fuzzer üzerinde çalışalım:

Bir bitmap dosyası nedir? Wiki sitesi incelediğimizde örnek bir bitmap dosya başlık (header) yapısını görmemiz mümkündür:

Offset Boyut Hex Değeri Değer Tanımlama
BMP Başlığı
0h 2 42 4D “BM” ID alanı (42h, 4Dh)
2h 4 46 00 00 00 70 bytes (54+16) BMP dosya boyutu
6h 2 00 00 Kullanılmayan alan Uygulamaya özel
8h 2 00 00 Kullanılmayan alan Uyglamaya özel
Ah 4 36 00 00 00 54 bytes (14+40) Pixel dizi ofseti
DIB Başlığı
Eh 4 28 00 00 00 40 bytes DIB başlık alanı
12h 4 02 00 00 00 2 pixels Bitmap’in pixel olarak genişliği
16h 4 02 00 00 00 2 pixels Bitmap’in pixel olarak yüksekliği
1Ah 2 01 00 1 düzlem değeri Kullanılan düzlem miktarı
1Ch 2 18 00 24 bit Piksel başına bit miktarı
1Eh 4 00 00 00 00 0 BI_RGB, Pixel dizi sıkıştırması yok
22h 4 10 00 00 00 16 bytes Arı bitmap verisinin boyutu
26h 4 13 0B 00 00 2835 pixels/meter horizontal Resmin yazıcı çözünürlük değeri
2Ah 4 13 0B 00 00 2835 pixels/meter vertical
2Eh 4 00 00 00 00 0 Paletteki renk miktarı
32h 4 00 00 00 00 0 0 tüm renklerin önem derecesini aynı tanımlar
Start of pixel array (bitmap data)
36h 3 00 00 FF 0 0 255 Kırmızı, Pixel (0,1)
39h 3 FF FF FF 255 255 255 Beyaz, Pixel (1,1)
3Ch 2 00 00 0 0 4 byte hizalama boşluğu
3Eh 3 FF 00 00 255 0 0 Mavi, Pixel (0,0)
41h 3 00 FF 00 0 255 0 Yeşil, Pixel (1,0)
44h 2 00 00 0 0 4 byte hizalama boşluğu

Örnekteki tüm bu Hex değerleri bir editörde artarda birleştirip .bmp formatında kaydedersek:

Bitmap Hex Format

ve ardından bir resim gösterim programı ile açarsak, gerçekten de bir resim göreceğiz:

Bitmap Image

Büyü gibi, değil mi?

Bu bilgiler ışığında şimdi 3 dosyadan oluşan bulama programımızı hazırlayalım. Öncelikle bir protokol yapı dosyası, ikinci olarak bir bulama girdi üreteci, son olarak da bulama kodunun kendisi.

Evet, öncelikle yukarıda çalıştığımız header başlık bilgilerinden istifadeyle, protokol sınıfımızı python dilinde oluşturalım:


 
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


Kurduğumuz bu yapıda, yalnızca B tipi alanları bulama ile ilgileneceğiz (B buffer alanı, C constant yani sabit değer, L ise length yani uzunluk anlamında).

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). Şimdi üreteç sınıfımızı oluşturabiliriz:



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]


Yukarıdaki dosyada rahatlıkla yeni bulama girdileri ekleyebiliriz. Son olarak artık bulama kodumuzu da hazırlayabiliriz:



#!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)


Fuzzer kodunu çalıştırmadan önce, aynı klasörde “images” isimli bir klasör oluşturun ve ardından fuzzer.py programını çalıştırın. Şimdi bu klasörde 122 adet örnek bozulmuş resim dosyası girdisi oluşturulduğunu göreceksiniz:

Fuzzer Running

Bu andan itibaren, bu örnek resim dosyalarını MS Paint gibi bir programla açıp kapayarak çökmesini takip eden bir takip kodu çalıştırabiliriz. Bu çalışmayı önceki çalışmamızda yapmıştık.

Dilerseniz şimdi bu basit örnekten çok daha kapsalı bir bulama programına geçelim: Peach Fuzzer. Söz konusu bulama programının nasıl çalıştığını kendi web sitesi üzerinden öğrenebilirsiniz. Burada bmp dosyaları için basit bir Peach PIT dosyası üretelim ve bunu çalıştıralım dilerseniz. Aşağıdaki kodu bmp.xml olarak kaydediniz:



<?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 -->


Ardından sample_bmp klasörü altında örnek .bmp uzantılı dosyalar hazırladıktan sonra Peach fuzzer programını çalıştırırsanız, bulama tekniğinin tadını çıkarabilirsiniz:

Peach Fuzzer Running