Le fuzzing est une technique de recherche de vulnérabilités dans un programme. Elle consiste à introduire, de manière automatisée, des données plus ou moins aléatoires, dans l'une des entrées de l'application cible. Par exemple, il est possible de fuzzer un antivirus en lui demandant d'analyser un grand nombre de fichiers .doc ou .exe modifiés.
Le fuzzing présente deux difficultés:
- les données envoyées en entrée du programme doivent être formatées pour être lisibles par la cible. Il y a donc autant de fuzzers que de protocoles d'entrée de données. Par exemple, un fuzzer de fichiers devra respecter le format Portable Executable (PE). Un fuzzer d'application Web utilisant http devra respecter ce protocole.
- le fuzzing utilisant des données aléatoires n'est pas optimal. Il est possible d'accélérer la recherche de vulnérabilités par l'analyse des données devant normalement être envoyées à l'application cible. Le framework Spike propose des outils pour cela.
Pour comprendre le fuzzing de fichiers, nous vous conseillons la lecture de la présentation faite à BlackHat 2005 par iDefenseLabs (référence n°3). Dans cet article, vous découvrirez le format PDF, l'utilisation de l'outil FileFuzz proposé par iDefenseLabs, ainsi que le codage d'un fuzzer de fichiers pdf: RubyPdfFuzzer.
plan
outils
- sumatra PDF: http://blog.kowalczyk.info/software/sumatrapdf/index.html
logiciel de lecture de PDF, distribué sous licence GPL. Nous l'utiliserons pour tester notre fuzzer.
- File Fuzz http://labs.idefense.com/software/fuzzing.php
FileFuzz est un fuzzer de fichiers, créé par iDefense Labs, fonctionnant sous Windows. Il est distribué sous licence GPL.
- Ruby http://www.ruby-lang.org/fr/
Vous aurez également besoin du plugin pdf-writer.
Pour l'installer sous Windows, télécharger d'abord RubyGems sur RubyForge: http://rubyforge.org/frs/?group_id=126 . Installez d'abord RubyGems: Placez vous dans le répertoire de RubyGems et tapez dans un terminal C:\ruby\bin ruby setup.rb . Installez ensuite pdf-writer: dans un Terminal, placez vous dans le répertoire C:\Ruby\bin puis tapez gem install pdf-writer.
Remarque: Vous pouvez ajouter C:\ruby\bin dans vos variables d'environnement (clic droit sur poste de travail, avancé, variables d'environnement, PATH, modifier).
Sous Ubuntu, tapez sudo apt-get install rubygems, puis exportez le chemin de gems: export PATH=/var/lib/gems/1.8/bin:$PATH puis tapez sudo gem install pdf-writer.
Remarque: Si vous souhaitez programmer en Ruby et que vous aimez Eclipse, vous pouvez utiliser le plugin de Aptana.
Pour cela, dans Eclipse, allez dans Help -> Install new software -> Add -> Location: http://update.aptana.com/update/rdt/3.2/site.xml
- RubyPdfFuzzer
RubyPdfFuzzer (code source en annexe 1) est un générateur de fichiers PDF écrit en Ruby. Il approfondit la méthode créée par Jeremy Brown dans PDFuzzer (référence n°6. Code source en annexe 2).
- Notepad++ http://notepad-plus.sourceforge.net/fr/site.htm
Le format Portable Document Format (PDF) a été créé par Adobe. Il permet à un document d'être affiché avec la même mise en page, quelque soit la plateforme utilisée (Linux, Mac, Windows).
Un PDF est structuré avec un(e) :
- en-tête (header),
- corps (body),
- table des références (cross référence),
- pied de page (trailer).
Chaque objet a :
- un numéro,
- une position fixe dans le document,
- un contenu (content).
Le premier objet de l'arbre s'appelle l'objet racine (root).
L'objet root a une référence vers l'objet /Pages.
Cet objet /Pages contient un tableau d'objets /Kids. Ce tableau contient les numéros des objets dans la page.
Chaque page commence avec un objet /Page qui contient les attributs de la page et un tableau de /Contents.
Voici un exemple d'objet /Page:
17 0 obj
<<
/Type /Page
/Parent 11 0 R
/MediaBox [0 0 600 810]
/Resources
<<
/Font << /F1 1 0 R /F2 2 0 R >>
/ProcSet 10 0 R
>>
/Contents [16 0 R 15 0 R ]
>>
endobj
La mise en forme du texte est assurée grâce à des opérateurs (operators):
Tf sets the font and the font size
Tj shows the text (enclosed in "(" and ")")
Tm defines the text matrix (the coordinates)
l the lineto operator
m moves the cursor
w defines the line width
S strokes the path
Par exemple:
6 0 obj
<< /Length 88 >>
stream
BT
/F1 11 Tf
1 0 0 1 25 798 Tm (kopfzeile - 1 -) Tj
2 w
12 792 m
550 792 l S
ET
endstream
endobj
Cette table ressemble à:
xref
0 20
0000000000 65535 f
0000000009 00000 n
0000000116 00000 n
...
- cross reference
- numéro de l'objet racine (root),
- numéro de l'objet info (qui contient un certain nombre de meta informations).
Il ressemble à:
trailer
<<
/Size 20
/Root 19 0 R
/Info 18 0 R
>>
startxref
2354
%%EOF
La syntaxe PDF n'est pas naturelle (!). Heureusement, il existe des API qui permettent de construire facilement les pdf.
Ruby met à disposition un module pour créer des PDF: PDF-writer. Grâce à lui, la création, l'ajout d'objet, la sauvegarde du PDF sont grandement facilités.
fuzzer bruteforce de fichiers Windows FileFuzz
FileFuzz possède un fonctionnement interne très simple: il crée des fichiers de mêmes taille et extension (.doc, .pdf, etc.) qu'un fichier modèle fourni par l'utilisateur. Il y injecte bloc par bloc des octets aléatoires.
Ensuite, il lance le logiciel cible, pour chacun de ces fichiers créés, dans un nouveau processus. Il capture alors quelques exceptions.
L'aspect remarquable du logiciel est dans les informations qu'il fournit en retour à l'utilisateur en cas de crash de l'application testée. Il ne nécessite pas un débugger (Ollydbg, dbg, Windbg ou Ida pro) complémentaire.
FileFuzz n'est pas un outil optimal quand le logiciel cible teste le formatage du fichier avant de l'ouvrir. Par exemple, SumatraPDF étudie la structure du fichier PDF qu'il doit ouvrir. S'il ne la reconnait pas, il se contente de refuser le fichier. C'est ce que nous allons illustrer dans cette partie du tutoriel.
Vous pouvez vous référer à la présentation powerpoint créée par l'un des auteurs du logiciel (référence n°2).

1. Onglet Create: permet de créer les fichiers qui seront ensuite injectés,
2. Source file: fichier à partir duquel seront générés les fichiers à injecter, choisissez un fichier pdf existant
3. Target directory: répertoire dans lequels seront placés les fichiers à injecter, tapez c:\fuzz\pdf
4. All Bytes: afin d'écrire des caractères aléatoires dans tout le fichier à injecter,
5. Nombre de fichiers à générer, choisissez 4 pour commencer.
6. Bouton Create: lance la création de fichiers.

1. Select Application : choisir l'application cible, "C:\Program Files\SumatraPDF\SumatraPDF.exe" (ne pas oublier les guillemets).
2. Arguments: "{0}"
3. Finish File: entrer le nombre de fichiers que vous avez générés. Utilisez seulement quelques fichiers pour commencer (10 par défaut),
4. Milliseconds: délai entre deux lancements du logiciel cible. Vous pouvez choisir 2000 ms.
5. Execute lance l'injection.
Dans certains cas, l'argument "{0}" ne convient pas.
Il faut trouver alors la façon dont l'adresse du fichier est fournie en entrée au logiciel:
Explorateur Windows -> Outils -> Options des dossiers

Onglet Types de fichiers -> PDF -> Avancé

open -> modifier


Ici, nous trouvons le paramètre %1. Mais dans le cas de SumatraPDF, l'argument 0 fonctionne...
En cas d'erreur de débuggage, il affiche un grand nombre de données permettant l'exploitation ultérieure du bug.
En effet, voici les principales fonctions de ce programme:
- CreateProcess(... DEBUG_PROCESS,...) : création d'un processus pour chaque injection, en mode debug.
- WaitForDebugEvent : permet d'attraper les erreurs renvoyées par le processus,
- if (dbg.dwDebugEventCode != EXCEPTION_DEBUG_EVENT) : parmi ces erreurs, nous ne retenons que celles liées au débuggage.
ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE); continue; : sinon le programme continue...
- OpenThread(THREAD_ALL_ACCESS, FALSE, dbg.dwThreadId) : accès au thread ayant entrainé l'erreur,
- context.ContextFlags = CONTEXT_FULL; : nous récupérons le contexte du débuggage
- switch (dbg.u.Exception.ExceptionRecord.ExceptionCode) : renvoie le type de l'exception levée:
case EXCEPTION_ACCESS_VIOLATION
case EXCEPTION_INT_DIVIDE_BY_ZERO
case EXCEPTION_STACK_OVERFLOW
- if (exception) : renvoie une image de la pile, des registres et du code source afin d'aider à l'exploitation de la faille.
ReadProcessMemory
get_instruction
get_instruction_string
Ces trois fonctions fournissent des données sur le contexte du crash. Elles sont définies dans libdasm.c . C'est d'ailleurs la partie remarquable de ce logiciel, car elle évite l'utilisation d'un débugger comme Ollydbg ou Ida Pro.
Ensuite il injecte bloc par bloc des tableaux d'octets aléatoires.
Voici les principales fonctions de cette classe :
public Write(byte [] sourceArrayInput, ...) C'est le constructeur de la classe. Il prend entre autre en arguments sourceArray qui est un tableau d'octets: par exemple 00 à FF. Ce sont les octets qui seront injectés.
writeByte() est la fonction qui écrit dans le fichier
for(...createLoop...) : parcourt le fichier
for (...byteLoop...) : met à jour le tableau d'octets à injecter sourceArray.
BinaryWriter bwTargetFile.Write(sourceArray); : écrit le tableau d'octets dans le fichier.
- Ce programme crée des fichiers PDF et les place dans un répertoire.
scale est un tableau contenant des nombres. Le programme va effectuer les opérations suivantes 100 fois, puis 200 fois, puis 500 fois, etc.
threads << Thread.new {
création d'un Thread. Ainsi Les créations de fichiers se feront en parallèle. Cette astuce n'accélère pas la création des fichiers. Elle donne juste la priorité aux créations de fichiers les moins longues: La création de fichier qui prend le moins de temps termine en premier.
pdf = PDF::Writer.new()
création du fichier pdf
pdf.save_as('pdf/' + nbFile.to_s + '.pdf')
sauvegarde du fichier avec son numéro suivi de .pdf
t.join(3)
Chaque thread travaille 3 secondes puis passe la main au suivant.
Ainsi le fuzzer fait parallèlement:
pdf.insert_page(:last)
insertion d'un page. Cette opération est répétée le nombre de fois défini dans l'étape du scale (100,200,500,...).
pdf.add_object(PDF::Writer::Object.new(pdf))
ajout d'objets au PDF
pdf.text c*n, :font_size => 72
ajout de la chaine de caractère prise successivement dans le tableau charOverflow multiplité par le nombre défini dans scale
pdf.image "./pinguin.jpg"
ajout d'images
case(r % 6)
when 0: pdf.rectangle(r,r,r).fill
when 1: pdf.rounded_rectangle(r,r,r,r,r).close_fill_stroke
when 2: pdf.circle_at(r,r,r).fill_stroke
when 3: pdf.ecurve_to(r,r,2*r,2*r).fill_stroke
when 4: pdf.ellipse_at(r,r,r).fill_stroke
when 5: pdf.line(r,r,2*r,2*r).close_fill_stroke
Ajout aléatoire d'une figure géométrique
Pour injecter les pdf créés, nous utilisons FileFuzz. Enjoy!
références
1) article de Anthony Muller - génération PDF avec Ruby - http://blog.developpez.com/index.php?blog=67&title=generation_pdf
2) iDefense Labs - présentation de FileFuzz - http://www.recon.cx/en/f/msutton-fuzzing.ppt
3) iDefense Labs - the art of file format fuzzing - http://www.blackhat.com/presentations/bh-jp-05/bh-jp-05-sutton-greene.pdf
4) article de Edgar Huckert - PDF essentials - http://www.planetpdf.com/mainpage.asp?WebPageID=63
5) Adobe - PDF Reference - http://partners.adobe.com/public/developer/en/pdf/PDFReference16.pdf
6) logiciel en Perl créé par Jeremy Brown - PDFuzzer http://www.derkeiler.com/Mailing-Lists/Securiteam/2008-11/msg00018.html ou http://www.packetstormsecurity.org/fuzzer/pdf-fuzzer.txt
7) rubyforge - documentation de pdf-writer - http://ruby-pdf.rubyforge.org/pdf-writer/doc/index.html
8) Austin Ziegler - ruby pdfwriter manual - http://www.scribd.com/doc/232915/Ruby-PDFWriter-manual-pdf
annexe 1
code source de RubyPDFuzzer
# RubyPdfFuzzer Tool 1.01
# created by t0ka7a 2009
# this program generates pdf files
# inspired from PDFuzzer perl Tool written by Jeremy Brown
# ***********************************
# * *
# Ruby Pdf Fuzzer Tool by t0ka7a
# * *
# ***********************************"
# License GNU 3.0
# please read http://www.gnu.org/licenses/gpl.html
# How to use:
# install ruby from http://www.ruby-lang.org/
# install Rubygems
# install pdf-writer plugin: C:\ruby\bin\gem install pdf-writer
# Start: ruby RubyPdfFuzzer
# Stop: CTRL-C
# to inject the files generated, you can use FileFuzz from iDefenseLab (Windows).
# Enjoy!
# corrections
# v1.01
# add table and info fuzzing
# thread optimization
require 'rubygems'
require 'pdf/writer'
require 'pdf/SimpleTable'
charOverflow = ['A', "\0x99", "//AAAA", "\\AAAA" ]
numbers = ['0', '-0', '1', '-1', '32767', '-32768', '2147483647', '-2147483647', '2147483648', '-2147483648', '4294967294', '4294967295', '4294967296', '357913942', '-357913942', '536870912', '-536870912', '1.79769313486231E+308', '3.39519326559384E-313', '99999999999', '-99999999999', '0x100', '0x1000', '0x3fffffff', '0x7ffffffe', '0x7fffffff', '0x80000000', '0xffff', '0xfffffffe', '0xfffffff', '0xffffffff', '0x10000', '0x100000', '0x99999999', '65535', '65536', '65537', '16777215', '16777216', '16777217', '-268435455']
scale = [ 100, 200, 500, 1000, 1500, 3000, 10000, 100000, 500000, 750000, 1000000]
threads = []
nbMaxObjects = 0
# not used for the moment...:
# miscbugs = ["test|touch /tmp/ZfZ-PWNED|test", "test`touch /tmp/ZfZ-PWNED`test", "test'touch /tmp/ZfZ-PWNED'test", "test;touch /tmp/ZfZ-PWNED;test", "test&&touch /tmp/ZfZ-PWNED&&test", "test|C:/WINDOWS/system32/calc.exe|test", "test`C:/WINDOWS/system32/calc.exe`test", "test'C:/WINDOWS/system32/calc.exe'test", "test;C:/WINDOWS/system32/calc.exe;test", "/bin/sh", "C:/WINDOWS/system32/calc.exe", "%0xa", "%u000" ]
# fmtstring = ["%n%n%n%n%n", "%p%p%p%p%p", "%s%s%s%s%s", "%d%d%d%d%d", "%x%x%x%x%x", "%s%p%x%d", "%.1024d", "%.1025d", "%.2048d", "%.2049d", "%.4096d", "%.4097d", "%99999999999s", "%08x", "%%20n", "%%20p", "%%20s", "%%20d", "%%20x", "%#0123456x%08x%x%s%p%d%n%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%%", "\0xCD" * 50, "\0xCB" * 50 ]
# page = ['4A0', '2A0', 'A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10', 'B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'B10', 'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'C10', 'RA0', 'RA1', 'RA2', 'RA3', 'RA4', 'SRA0', 'SRA1', 'SRA2', 'SRA3', 'SRA4', 'LETTER', 'LEGAL', 'FOLIO', 'EXECUTIVE' ]
# version = [ '1.3', '1.4', '1.5', '1.6' ]
#-----------show help-------------------------------
puts " RubyPdfFuzzer Tool 1.01
created by t0ka7a 2009
this program generates pdf files
inspired from PDFuzzer perl Tool written by Jeremy Brown
***********************************
* *
Ruby Pdf Fuzzer Tool by t0ka7a
* *
***********************************
License GNU 3.0
please read http://www.gnu.org/licenses/gpl.html
Stop: CTRL-C
to inject the files generated, you can use FileFuzz from iDefenseLab (Windows).
Enjoy!
"
#--------------generate pdf files-------------------
begin
Dir::mkdir("pdf", 0777)
rescue
end
nbFile = 0
mutex = Mutex.new #semaphore to synchronize access to nbFile by threads
# fuzz pdf info
threads << Thread.new {
n= scale.last
charOverflow.each do |c|
(0..8).each do |i|
nbF=0
st=""
pdf = PDF::Writer.new()
case(i)
when 0: st='creator='
when 1: st='creationdate='
when 2: st='title='
when 3: st='Author='
when 4: st='Subject='
when 5: st='keywords='
when 6: st='moddate='
when 7: st='trapped='
when 8: st='producer='
end
pdf.add_info(st,c*n)
mutex.synchronize do
nbFile+=1
nbF=nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + st + ' ' + c + ' x ' + n.to_s
end
end
}
# fuzz nb pages
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new()
(1..n).each do
pdf.insert_page(:last)
end
mutex.synchronize do
nbFile+=1
nbF=nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' pages'
end
}
# fuzz nb objects
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new()
(1..n).each do
pdf.add_object(PDF::Writer::Object.new(pdf))
end
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' objects'
end
}
# fuzz text overflow
charOverflow.each do |c|
threads << Thread.new {
nbF=0
scale.each do |n|
pdf = PDF::Writer.new()
pdf.select_font "Times-Roman"
pdf.text c*n, :font_size => 72
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with text= ' + c + ' * ' + n.to_s
end
}
end
# fuzz nb images
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new()
(1..n).each do
pdf.image "./infond32x32.jpg"
end
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' images'
end
}
# fuzz nb graphics
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new()
pdf.fill_color Color::RGB::Black
(1..n).each do
r = ( rand(n) % [pdf.page_width,pdf.page_height].min ) / 2
case(r % 6)
when 0: pdf.rectangle(r,r,r).fill
when 1: pdf.rounded_rectangle(r,r,r,r,r).close_fill_stroke
when 2: pdf.circle_at(r,r,r).fill_stroke
when 3: pdf.ecurve_to(r,r,2*r,2*r).fill_stroke
when 4: pdf.ellipse_at(r,r,r).fill_stroke
when 5: pdf.line(r,r,2*r,2*r).close_fill_stroke
end
end
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' graphics'
end
}
# fuzz tab title
threads << Thread.new {
scale.each do |n|
charOverflow.each do |c|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = "title"
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
tab = PDF::SimpleTable.new
tab.title = c * n
tab.data << "data"
tab.column_order.push(head.title)
tab.show_lines = :all
tab.show_headings = true
tab.render_on(pdf)
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with table. col title = ' + c + ' * ' + n.to_s
end
end
}
# fuzz col title
threads << Thread.new {
scale.each do |n|
charOverflow.each do |c|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = c * n
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
tab = PDF::SimpleTable.new
tab.title = "title"
tab.data << "data"
tab.column_order.push(head.title)
tab.show_lines = :all
tab.show_headings = true
tab.render_on(pdf)
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with table. Col title = ' + c + ' * ' + n.to_s
end
end
}
# fuzz col data
threads << Thread.new {
scale.each do |n|
charOverflow.each do |c|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = "title"
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
tab = PDF::SimpleTable.new
tab.title = "title"
tab.data << {head.title => c*n}
tab.column_order.push(head.title)
tab.show_lines = :all
tab.show_headings = true
tab.render_on(pdf)
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with table. Col data = ' + c + ' * ' + n.to_s
end
end
}
# fuzz nb of tab
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = "title"
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
(0..n).each do
tab = PDF::SimpleTable.new
tab.title = "title"
tab.data << "data"
tab.column_order.push(head.title)
tab.show_lines = :all
tab.show_headings = true
tab.render_on(pdf)
end
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' tables'
end
}
# fuzz nb of col in tab
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = "title"
tab = PDF::SimpleTable.new
tab.title = "title"
tab.show_lines = :all
tab.show_headings = true
(0..n).each do |i|
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
tab.column_order.push(i)
tab.columns[i] = col
tab.data[i] = ""
end
tab.render_on(pdf)
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' cols in table'
end
}
# fuzz nb of rows in tab
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = "title"
tab = PDF::SimpleTable.new
tab.title = "title"
tab.show_lines = :all
tab.show_headings = true
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
tab.column_order.push(0)
tab.columns[0] = col
(0..n).each do
tab.data.push ( { 0.to_s => "" } )
end
tab.render_on(pdf)
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' rows in table'
end
}
threads.reverse.each do |t|
t.join(3)
end
mutex.lock
while(1) do end
#EOF
annexe 2
code source de PDFuzzerPDFuzzer - PDF File Standard Fuzzer
------------------------------------------------------------------------
SUMMARY
DETAILS
Tool source:
#!/usr/bin/perl
# Jeremy Brown [0xjbrown41@xxxxxxxxx/jbrownsec.blogspot.com]
# PDF FUZZER -- TAKE IT TO THE HEAD
# :) HAVE FUN :)
use PDF::Create;
use Getopt::Std;
@overflow = ('A' x 8200, 'A' x 11000, 'A' x 110000, 'A' x 550000, 'A' x
1100000, 'A' x 2200000, 'A' x 12000000, "\0x99" x 1200, "//AAAA" x 250,
"\\AAAA" x 250);
@fmtstring = ("%n%n%n%n%n", "%p%p%p%p%p", "%s%s%s%s%s", "%d%d%d%d%d",
"%x%x%x%x%x",
"%s%p%x%d", "%.1024d", "%.1025d", "%.2048d", "%.2049d",
"%.4096d", "%.4097d",
"%99999999999s", "%08x", "%%20n", "%%20p", "%%20s", "%%20d",
"%%20x",
"%#0123456x%08x%x%s%p%d%n%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%%",
"\0xCD" x 50, "\0xCB" x 50);
@numbers = ("0", "-0", "1", "-1", "32767", "-32768", "2147483647",
"-2147483647", "2147483648", "-2147483648",
"4294967294", "4294967295", "4294967296", "357913942",
"-357913942", "536870912", "-536870912",
"1.79769313486231E+308", "3.39519326559384E-313",
"99999999999", "-99999999999", "0x100", "0x1000",
"0x3fffffff", "0x7ffffffe", "0x7fffffff", "0x80000000",
"0xffff", "0xfffffffe", "0xfffffff", "0xffffffff",
"0x10000", "0x100000", "0x99999999", "65535", "65536",
"65537", "16777215", "16777216", "16777217", "-268435455");
@miscbugs = ("test|touch /tmp/ZfZ-PWNED|test", "test`touch
/tmp/ZfZ-PWNED`test", "test'touch /tmp/ZfZ-PWNED'test", "test;touch
/tmp/ZfZ-PWNED;test",
"test&&touch /tmp/ZfZ-PWNED&&test",
"test|C:/WINDOWS/system32/calc.exe|test",
"test`C:/WINDOWS/system32/calc.exe`test",
"test'C:/WINDOWS/system32/calc.exe'test",
"test;C:/WINDOWS/system32/calc.exe;test", "/bin/sh",
"C:/WINDOWS/system32/calc.exe", "%0xa", "%u000");
getopts('t:o:', \%opts);
$target = $opts{'t'};
$pdfdoc = $opts{'o'};
if(!defined($target) || !defined($pdfdoc))
{
print "\n pdfUZZ - PDF Fuzzer";
print "\nJeremy Brown
[0xjbrown41@xxxxxxxxx/http://jbrownsec.blogspot.com]";;
print "\n Usage: $0 -t -o \n\n";
exit(0);
}
print "\n pdfUZZ - PDF Fuzzer";
print "\nJeremy Brown
[0xjbrown41@xxxxxxxxx/http://jbrownsec.blogspot.com]\n";;
print "\nFUZZING '$target' with '$pdfdoc' [STAGE->1(Version)]";
print "\n";
foreach(@numbers) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => $fuzz,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->2(Author)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->3(Title)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => $fuzz,
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => $fuzz,
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => $fuzz,
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->4(page_size)]";
print "\n";
foreach(@numbers) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => [$fuzz, $fuzz, $fuzz, $fuzz]);
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->5(Subject)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => $fuzz,
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => $fuzz,
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => $fuzz,
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->6(Keywords)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => $fuzz);
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => $fuzz);
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => $fuzz);
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
print "\nFUZZING '$target' with '$pdfdoc' [STAGE->7(font/Subtype)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => $fuzz,
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => $fuzz,
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => $fuzz,
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->8(font/Encoding)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => $fuzz,
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => $fuzz,
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => $fuzz,
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->9(font/BaseFont)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => $fuzz);
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => $fuzz);
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => $fuzz);
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
print "\nFUZZING '$target' with '$pdfdoc' [STAGE->10(string/z+x+y)]";
print "\n";
foreach(@numbers) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, $fuzz, $fuzz, $fuzz, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->11(string/text)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, $fuzz);
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, $fuzz);
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, $fuzz);
$pdf->close;
system $target $pdfdoc; }
exit;
#EOF
Le fuzzing présente deux difficultés:
- les données envoyées en entrée du programme doivent être formatées pour être lisibles par la cible. Il y a donc autant de fuzzers que de protocoles d'entrée de données. Par exemple, un fuzzer de fichiers devra respecter le format Portable Executable (PE). Un fuzzer d'application Web utilisant http devra respecter ce protocole.
- le fuzzing utilisant des données aléatoires n'est pas optimal. Il est possible d'accélérer la recherche de vulnérabilités par l'analyse des données devant normalement être envoyées à l'application cible. Le framework Spike propose des outils pour cela.
Pour comprendre le fuzzing de fichiers, nous vous conseillons la lecture de la présentation faite à BlackHat 2005 par iDefenseLabs (référence n°3). Dans cet article, vous découvrirez le format PDF, l'utilisation de l'outil FileFuzz proposé par iDefenseLabs, ainsi que le codage d'un fuzzer de fichiers pdf: RubyPdfFuzzer.
plan
- le format PDF et Ruby
- header
- body
- cross reference
- trailer
- résumé
- fuzzer bruteforce de fichiers Windows FileFuzz
- utilisation de FileFuzz
- création des fichiers à injecter
- injection
- Arguments pour l'injection
- analyse de l'injection: crash.c
- analyse de la création: write.cs
- résumé sur FileFuzz
- utilisation de FileFuzz
- fuzzing de .pdf avec RubyPdfFuzzer
- Analyse du programme
- Résumé
- conclusion
outils
- sumatra PDF: http://blog.kowalczyk.info/software/sumatrapdf/index.html
logiciel de lecture de PDF, distribué sous licence GPL. Nous l'utiliserons pour tester notre fuzzer.
- File Fuzz http://labs.idefense.com/software/fuzzing.php
FileFuzz est un fuzzer de fichiers, créé par iDefense Labs, fonctionnant sous Windows. Il est distribué sous licence GPL.
- Ruby http://www.ruby-lang.org/fr/
Vous aurez également besoin du plugin pdf-writer.
Pour l'installer sous Windows, télécharger d'abord RubyGems sur RubyForge: http://rubyforge.org/frs/?group_id=126 . Installez d'abord RubyGems: Placez vous dans le répertoire de RubyGems et tapez dans un terminal C:\ruby\bin ruby setup.rb . Installez ensuite pdf-writer: dans un Terminal, placez vous dans le répertoire C:\Ruby\bin puis tapez gem install pdf-writer.
Remarque: Vous pouvez ajouter C:\ruby\bin dans vos variables d'environnement (clic droit sur poste de travail, avancé, variables d'environnement, PATH, modifier).
Sous Ubuntu, tapez sudo apt-get install rubygems, puis exportez le chemin de gems: export PATH=/var/lib/gems/1.8/bin:$PATH puis tapez sudo gem install pdf-writer.
Remarque: Si vous souhaitez programmer en Ruby et que vous aimez Eclipse, vous pouvez utiliser le plugin de Aptana.
Pour cela, dans Eclipse, allez dans Help -> Install new software -> Add -> Location: http://update.aptana.com/update/rdt/3.2/site.xml
- RubyPdfFuzzer
RubyPdfFuzzer (code source en annexe 1) est un générateur de fichiers PDF écrit en Ruby. Il approfondit la méthode créée par Jeremy Brown dans PDFuzzer (référence n°6. Code source en annexe 2).
- Notepad++ http://notepad-plus.sourceforge.net/fr/site.htm
le format PDF et Ruby
Cette partie est tirée de l'article de Edgar Huckert - PDF essentials (référence n°4)Le format Portable Document Format (PDF) a été créé par Adobe. Il permet à un document d'être affiché avec la même mise en page, quelque soit la plateforme utilisée (Linux, Mac, Windows).
Un PDF est structuré avec un(e) :
- en-tête (header),
- corps (body),
- table des références (cross référence),
- pied de page (trailer).
header
Il identifie le type du document et la version pdf utilisée: "%PDF-1.1"body
Le body est une collection d'objets, organisés en arbre, qui décrivent la structure de la page, les éléments (graphiques, images, texte,...).Chaque objet a :
- un numéro,
- une position fixe dans le document,
- un contenu (content).
Le premier objet de l'arbre s'appelle l'objet racine (root).
L'objet root a une référence vers l'objet /Pages.
Cet objet /Pages contient un tableau d'objets /Kids. Ce tableau contient les numéros des objets dans la page.
Chaque page commence avec un objet /Page qui contient les attributs de la page et un tableau de /Contents.
Voici un exemple d'objet /Page:
17 0 obj
<<
/Type /Page
/Parent 11 0 R
/MediaBox [0 0 600 810]
/Resources
<<
/Font << /F1 1 0 R /F2 2 0 R >>
/ProcSet 10 0 R
>>
/Contents [16 0 R 15 0 R ]
>>
endobj
La mise en forme du texte est assurée grâce à des opérateurs (operators):
Tf sets the font and the font size
Tj shows the text (enclosed in "(" and ")")
Tm defines the text matrix (the coordinates)
l the lineto operator
m moves the cursor
w defines the line width
S strokes the path
Par exemple:
6 0 obj
<< /Length 88 >>
stream
BT
/F1 11 Tf
1 0 0 1 25 798 Tm (kopfzeile - 1 -) Tj
2 w
12 792 m
550 792 l S
ET
endstream
endobj
cross reference
Cette table permet d'accéder rapidement aux objets. Elle commence avec le mot clé xref. Une entrée de cette table est constituée d'un pointeur (offset) vers l'objet et d'un drapeau (flag) qui indique si l'objet est libre ou occupé.Cette table ressemble à:
xref
0 20
0000000000 65535 f
0000000009 00000 n
0000000116 00000 n
...
trailer
le trailer donne un accès rapide aux éléments essentiels du document:- cross reference
- numéro de l'objet racine (root),
- numéro de l'objet info (qui contient un certain nombre de meta informations).
Il ressemble à:
trailer
<<
/Size 20
/Root 19 0 R
/Info 18 0 R
>>
startxref
2354
%%EOF
résumé
Le PDF est un document structuré. Notre fuzzer devra donc y injecter des objets divers et variés. Si la structure n'est pas respectée, un logiciel d'affichage de PDF rejettera simplement notre fichier.La syntaxe PDF n'est pas naturelle (!). Heureusement, il existe des API qui permettent de construire facilement les pdf.
Ruby met à disposition un module pour créer des PDF: PDF-writer. Grâce à lui, la création, l'ajout d'objet, la sauvegarde du PDF sont grandement facilités.
fuzzer bruteforce de fichiers Windows FileFuzz
FileFuzz possède un fonctionnement interne très simple: il crée des fichiers de mêmes taille et extension (.doc, .pdf, etc.) qu'un fichier modèle fourni par l'utilisateur. Il y injecte bloc par bloc des octets aléatoires.Ensuite, il lance le logiciel cible, pour chacun de ces fichiers créés, dans un nouveau processus. Il capture alors quelques exceptions.
L'aspect remarquable du logiciel est dans les informations qu'il fournit en retour à l'utilisateur en cas de crash de l'application testée. Il ne nécessite pas un débugger (Ollydbg, dbg, Windbg ou Ida pro) complémentaire.
FileFuzz n'est pas un outil optimal quand le logiciel cible teste le formatage du fichier avant de l'ouvrir. Par exemple, SumatraPDF étudie la structure du fichier PDF qu'il doit ouvrir. S'il ne la reconnait pas, il se contente de refuser le fichier. C'est ce que nous allons illustrer dans cette partie du tutoriel.
utilisation de FileFuzz
Nous allons tester FileFuzz sur le logiciel SumatraPDF.Vous pouvez vous référer à la présentation powerpoint créée par l'un des auteurs du logiciel (référence n°2).
création des fichiers à injecter
1. Onglet Create: permet de créer les fichiers qui seront ensuite injectés,
2. Source file: fichier à partir duquel seront générés les fichiers à injecter, choisissez un fichier pdf existant
3. Target directory: répertoire dans lequels seront placés les fichiers à injecter, tapez c:\fuzz\pdf
4. All Bytes: afin d'écrire des caractères aléatoires dans tout le fichier à injecter,
5. Nombre de fichiers à générer, choisissez 4 pour commencer.
6. Bouton Create: lance la création de fichiers.
injection
1. Select Application : choisir l'application cible, "C:\Program Files\SumatraPDF\SumatraPDF.exe" (ne pas oublier les guillemets).
2. Arguments: "{0}"
3. Finish File: entrer le nombre de fichiers que vous avez générés. Utilisez seulement quelques fichiers pour commencer (10 par défaut),
4. Milliseconds: délai entre deux lancements du logiciel cible. Vous pouvez choisir 2000 ms.
5. Execute lance l'injection.
Arguments pour l'injection
Dans certains cas, l'argument "{0}" ne convient pas.
Il faut trouver alors la façon dont l'adresse du fichier est fournie en entrée au logiciel:
Explorateur Windows -> Outils -> Options des dossiers
Onglet Types de fichiers -> PDF -> Avancé
open -> modifier
Ici, nous trouvons le paramètre %1. Mais dans le cas de SumatraPDF, l'argument 0 fonctionne...
analyse de l'injection: crash.c
FileFuzz crée un processus, en mode débuggage, pour chaque fichier à injecter et lance le programme cible comme thread de ce processus. Il continue tant qu'aucune erreur n'est détectée.En cas d'erreur de débuggage, il affiche un grand nombre de données permettant l'exploitation ultérieure du bug.
En effet, voici les principales fonctions de ce programme:
- CreateProcess(... DEBUG_PROCESS,...) : création d'un processus pour chaque injection, en mode debug.
- WaitForDebugEvent : permet d'attraper les erreurs renvoyées par le processus,
- if (dbg.dwDebugEventCode != EXCEPTION_DEBUG_EVENT) : parmi ces erreurs, nous ne retenons que celles liées au débuggage.
ContinueDebugEvent(dbg.dwProcessId, dbg.dwThreadId, DBG_CONTINUE); continue; : sinon le programme continue...
- OpenThread(THREAD_ALL_ACCESS, FALSE, dbg.dwThreadId) : accès au thread ayant entrainé l'erreur,
- context.ContextFlags = CONTEXT_FULL; : nous récupérons le contexte du débuggage
- switch (dbg.u.Exception.ExceptionRecord.ExceptionCode) : renvoie le type de l'exception levée:
case EXCEPTION_ACCESS_VIOLATION
case EXCEPTION_INT_DIVIDE_BY_ZERO
case EXCEPTION_STACK_OVERFLOW
- if (exception) : renvoie une image de la pile, des registres et du code source afin d'aider à l'exploitation de la faille.
ReadProcessMemory
get_instruction
get_instruction_string
Ces trois fonctions fournissent des données sur le contexte du crash. Elles sont définies dans libdasm.c . C'est d'ailleurs la partie remarquable de ce logiciel, car elle évite l'utilisation d'un débugger comme Ollydbg ou Ida Pro.
analyse de la création: write.cs
FileFuzz crée de nouveaux fichiers vierges auxquels il donne les mêmes tailles et extension (.doc, .pdf,...) que le fichier indiqué par l'utilisateur comme modèle.Ensuite il injecte bloc par bloc des tableaux d'octets aléatoires.
Voici les principales fonctions de cette classe :
public Write(byte [] sourceArrayInput, ...) C'est le constructeur de la classe. Il prend entre autre en arguments sourceArray qui est un tableau d'octets: par exemple 00 à FF. Ce sont les octets qui seront injectés.
writeByte() est la fonction qui écrit dans le fichier
for(...createLoop...) : parcourt le fichier
for (...byteLoop...) : met à jour le tableau d'octets à injecter sourceArray.
BinaryWriter bwTargetFile.Write(sourceArray); : écrit le tableau d'octets dans le fichier.
résumé sur FileFuzz
Fuzzer SumatraPDF avec FileFuzz en mode AllBytes n'est pas efficace, car SumatraPDF teste le format du fichier avant de l'ouvrir. Nous allons donc utiliser un autre outil de fuzzing pour générer nos fichiers: RubyPdfFuzzer. Nous pourrons ensuite utiliser FileFuzz pour lancer le fuzzing. C'est ce que nous allons voir dans la partie suivante.fuzzing de .pdf avec RubyPdfFuzzer
- Copiez le code source dans un fichier RubyPdfFuzzer.rb et cliquez dessus.- Ce programme crée des fichiers PDF et les place dans un répertoire.
Analyse du programme
scale.each do |n|scale est un tableau contenant des nombres. Le programme va effectuer les opérations suivantes 100 fois, puis 200 fois, puis 500 fois, etc.
threads << Thread.new {
création d'un Thread. Ainsi Les créations de fichiers se feront en parallèle. Cette astuce n'accélère pas la création des fichiers. Elle donne juste la priorité aux créations de fichiers les moins longues: La création de fichier qui prend le moins de temps termine en premier.
pdf = PDF::Writer.new()
création du fichier pdf
pdf.save_as('pdf/' + nbFile.to_s + '.pdf')
sauvegarde du fichier avec son numéro suivi de .pdf
t.join(3)
Chaque thread travaille 3 secondes puis passe la main au suivant.
Ainsi le fuzzer fait parallèlement:
pdf.insert_page(:last)
insertion d'un page. Cette opération est répétée le nombre de fois défini dans l'étape du scale (100,200,500,...).
pdf.add_object(PDF::Writer::Object.new(pdf))
ajout d'objets au PDF
pdf.text c*n, :font_size => 72
ajout de la chaine de caractère prise successivement dans le tableau charOverflow multiplité par le nombre défini dans scale
pdf.image "./pinguin.jpg"
ajout d'images
case(r % 6)
when 0: pdf.rectangle(r,r,r).fill
when 1: pdf.rounded_rectangle(r,r,r,r,r).close_fill_stroke
when 2: pdf.circle_at(r,r,r).fill_stroke
when 3: pdf.ecurve_to(r,r,2*r,2*r).fill_stroke
when 4: pdf.ellipse_at(r,r,r).fill_stroke
when 5: pdf.line(r,r,2*r,2*r).close_fill_stroke
Ajout aléatoire d'une figure géométrique
Résumé
RubyPdfFuzzer se contente de créer des fichiers à fuzzer selon 5 méthodes différentes: nombre de pages, d'objets, d'images, de grahismes et overflow d'un objet.Pour injecter les pdf créés, nous utilisons FileFuzz. Enjoy!
conclusion
Dans cet article, nous avons étudié un fuzzer de fichiers et avons démontré ses limitations: il est nécessaire de créer des objets en respectant le protocole de lecture du logiciel cible. Ruby nous a permis de remédier facilement à cette création.références
1) article de Anthony Muller - génération PDF avec Ruby - http://blog.developpez.com/index.php?blog=67&title=generation_pdf
2) iDefense Labs - présentation de FileFuzz - http://www.recon.cx/en/f/msutton-fuzzing.ppt
3) iDefense Labs - the art of file format fuzzing - http://www.blackhat.com/presentations/bh-jp-05/bh-jp-05-sutton-greene.pdf
4) article de Edgar Huckert - PDF essentials - http://www.planetpdf.com/mainpage.asp?WebPageID=63
5) Adobe - PDF Reference - http://partners.adobe.com/public/developer/en/pdf/PDFReference16.pdf
6) logiciel en Perl créé par Jeremy Brown - PDFuzzer http://www.derkeiler.com/Mailing-Lists/Securiteam/2008-11/msg00018.html ou http://www.packetstormsecurity.org/fuzzer/pdf-fuzzer.txt
7) rubyforge - documentation de pdf-writer - http://ruby-pdf.rubyforge.org/pdf-writer/doc/index.html
8) Austin Ziegler - ruby pdfwriter manual - http://www.scribd.com/doc/232915/Ruby-PDFWriter-manual-pdf
annexe 1
code source de RubyPDFuzzer
# RubyPdfFuzzer Tool 1.01
# created by t0ka7a 2009
# this program generates pdf files
# inspired from PDFuzzer perl Tool written by Jeremy Brown
# ***********************************
# * *
# Ruby Pdf Fuzzer Tool by t0ka7a
# * *
# ***********************************"
# License GNU 3.0
# please read http://www.gnu.org/licenses/gpl.html
# How to use:
# install ruby from http://www.ruby-lang.org/
# install Rubygems
# install pdf-writer plugin: C:\ruby\bin\gem install pdf-writer
# Start: ruby RubyPdfFuzzer
# Stop: CTRL-C
# to inject the files generated, you can use FileFuzz from iDefenseLab (Windows).
# Enjoy!
# corrections
# v1.01
# add table and info fuzzing
# thread optimization
require 'rubygems'
require 'pdf/writer'
require 'pdf/SimpleTable'
charOverflow = ['A', "\0x99", "//AAAA", "\\AAAA" ]
numbers = ['0', '-0', '1', '-1', '32767', '-32768', '2147483647', '-2147483647', '2147483648', '-2147483648', '4294967294', '4294967295', '4294967296', '357913942', '-357913942', '536870912', '-536870912', '1.79769313486231E+308', '3.39519326559384E-313', '99999999999', '-99999999999', '0x100', '0x1000', '0x3fffffff', '0x7ffffffe', '0x7fffffff', '0x80000000', '0xffff', '0xfffffffe', '0xfffffff', '0xffffffff', '0x10000', '0x100000', '0x99999999', '65535', '65536', '65537', '16777215', '16777216', '16777217', '-268435455']
scale = [ 100, 200, 500, 1000, 1500, 3000, 10000, 100000, 500000, 750000, 1000000]
threads = []
nbMaxObjects = 0
# not used for the moment...:
# miscbugs = ["test|touch /tmp/ZfZ-PWNED|test", "test`touch /tmp/ZfZ-PWNED`test", "test'touch /tmp/ZfZ-PWNED'test", "test;touch /tmp/ZfZ-PWNED;test", "test&&touch /tmp/ZfZ-PWNED&&test", "test|C:/WINDOWS/system32/calc.exe|test", "test`C:/WINDOWS/system32/calc.exe`test", "test'C:/WINDOWS/system32/calc.exe'test", "test;C:/WINDOWS/system32/calc.exe;test", "/bin/sh", "C:/WINDOWS/system32/calc.exe", "%0xa", "%u000" ]
# fmtstring = ["%n%n%n%n%n", "%p%p%p%p%p", "%s%s%s%s%s", "%d%d%d%d%d", "%x%x%x%x%x", "%s%p%x%d", "%.1024d", "%.1025d", "%.2048d", "%.2049d", "%.4096d", "%.4097d", "%99999999999s", "%08x", "%%20n", "%%20p", "%%20s", "%%20d", "%%20x", "%#0123456x%08x%x%s%p%d%n%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%%", "\0xCD" * 50, "\0xCB" * 50 ]
# page = ['4A0', '2A0', 'A0', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10', 'B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'B10', 'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', 'C10', 'RA0', 'RA1', 'RA2', 'RA3', 'RA4', 'SRA0', 'SRA1', 'SRA2', 'SRA3', 'SRA4', 'LETTER', 'LEGAL', 'FOLIO', 'EXECUTIVE' ]
# version = [ '1.3', '1.4', '1.5', '1.6' ]
#-----------show help-------------------------------
puts " RubyPdfFuzzer Tool 1.01
created by t0ka7a 2009
this program generates pdf files
inspired from PDFuzzer perl Tool written by Jeremy Brown
***********************************
* *
Ruby Pdf Fuzzer Tool by t0ka7a
* *
***********************************
License GNU 3.0
please read http://www.gnu.org/licenses/gpl.html
Stop: CTRL-C
to inject the files generated, you can use FileFuzz from iDefenseLab (Windows).
Enjoy!
"
#--------------generate pdf files-------------------
begin
Dir::mkdir("pdf", 0777)
rescue
end
nbFile = 0
mutex = Mutex.new #semaphore to synchronize access to nbFile by threads
# fuzz pdf info
threads << Thread.new {
n= scale.last
charOverflow.each do |c|
(0..8).each do |i|
nbF=0
st=""
pdf = PDF::Writer.new()
case(i)
when 0: st='creator='
when 1: st='creationdate='
when 2: st='title='
when 3: st='Author='
when 4: st='Subject='
when 5: st='keywords='
when 6: st='moddate='
when 7: st='trapped='
when 8: st='producer='
end
pdf.add_info(st,c*n)
mutex.synchronize do
nbFile+=1
nbF=nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + st + ' ' + c + ' x ' + n.to_s
end
end
}
# fuzz nb pages
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new()
(1..n).each do
pdf.insert_page(:last)
end
mutex.synchronize do
nbFile+=1
nbF=nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' pages'
end
}
# fuzz nb objects
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new()
(1..n).each do
pdf.add_object(PDF::Writer::Object.new(pdf))
end
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' objects'
end
}
# fuzz text overflow
charOverflow.each do |c|
threads << Thread.new {
nbF=0
scale.each do |n|
pdf = PDF::Writer.new()
pdf.select_font "Times-Roman"
pdf.text c*n, :font_size => 72
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with text= ' + c + ' * ' + n.to_s
end
}
end
# fuzz nb images
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new()
(1..n).each do
pdf.image "./infond32x32.jpg"
end
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' images'
end
}
# fuzz nb graphics
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new()
pdf.fill_color Color::RGB::Black
(1..n).each do
r = ( rand(n) % [pdf.page_width,pdf.page_height].min ) / 2
case(r % 6)
when 0: pdf.rectangle(r,r,r).fill
when 1: pdf.rounded_rectangle(r,r,r,r,r).close_fill_stroke
when 2: pdf.circle_at(r,r,r).fill_stroke
when 3: pdf.ecurve_to(r,r,2*r,2*r).fill_stroke
when 4: pdf.ellipse_at(r,r,r).fill_stroke
when 5: pdf.line(r,r,2*r,2*r).close_fill_stroke
end
end
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' graphics'
end
}
# fuzz tab title
threads << Thread.new {
scale.each do |n|
charOverflow.each do |c|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = "title"
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
tab = PDF::SimpleTable.new
tab.title = c * n
tab.data << "data"
tab.column_order.push(head.title)
tab.show_lines = :all
tab.show_headings = true
tab.render_on(pdf)
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with table. col title = ' + c + ' * ' + n.to_s
end
end
}
# fuzz col title
threads << Thread.new {
scale.each do |n|
charOverflow.each do |c|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = c * n
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
tab = PDF::SimpleTable.new
tab.title = "title"
tab.data << "data"
tab.column_order.push(head.title)
tab.show_lines = :all
tab.show_headings = true
tab.render_on(pdf)
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with table. Col title = ' + c + ' * ' + n.to_s
end
end
}
# fuzz col data
threads << Thread.new {
scale.each do |n|
charOverflow.each do |c|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = "title"
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
tab = PDF::SimpleTable.new
tab.title = "title"
tab.data << {head.title => c*n}
tab.column_order.push(head.title)
tab.show_lines = :all
tab.show_headings = true
tab.render_on(pdf)
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with table. Col data = ' + c + ' * ' + n.to_s
end
end
}
# fuzz nb of tab
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = "title"
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
(0..n).each do
tab = PDF::SimpleTable.new
tab.title = "title"
tab.data << "data"
tab.column_order.push(head.title)
tab.show_lines = :all
tab.show_headings = true
tab.render_on(pdf)
end
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' tables'
end
}
# fuzz nb of col in tab
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = "title"
tab = PDF::SimpleTable.new
tab.title = "title"
tab.show_lines = :all
tab.show_headings = true
(0..n).each do |i|
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
tab.column_order.push(i)
tab.columns[i] = col
tab.data[i] = ""
end
tab.render_on(pdf)
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' cols in table'
end
}
# fuzz nb of rows in tab
threads << Thread.new {
scale.each do |n|
nbF=0
pdf = PDF::Writer.new
head = PDF::SimpleTable::Column::Heading.new
head.title = "title"
tab = PDF::SimpleTable.new
tab.title = "title"
tab.show_lines = :all
tab.show_headings = true
col = PDF::SimpleTable::Column.new(head.title)
col.heading = head
tab.column_order.push(0)
tab.columns[0] = col
(0..n).each do
tab.data.push ( { 0.to_s => "" } )
end
tab.render_on(pdf)
mutex.synchronize do
nbFile+=1
nbF = nbFile
end
pdf.save_as('pdf/' + nbF.to_s + '.pdf')
puts 'file ' + nbF.to_s + ' created with ' + n.to_s + ' rows in table'
end
}
threads.reverse.each do |t|
t.join(3)
end
mutex.lock
while(1) do end
#EOF
annexe 2
code source de PDFuzzerPDFuzzer - PDF File Standard Fuzzer
------------------------------------------------------------------------
SUMMARY
DETAILS
Tool source:
#!/usr/bin/perl
# Jeremy Brown [0xjbrown41@xxxxxxxxx/jbrownsec.blogspot.com]
# PDF FUZZER -- TAKE IT TO THE HEAD
# :) HAVE FUN :)
use PDF::Create;
use Getopt::Std;
@overflow = ('A' x 8200, 'A' x 11000, 'A' x 110000, 'A' x 550000, 'A' x
1100000, 'A' x 2200000, 'A' x 12000000, "\0x99" x 1200, "//AAAA" x 250,
"\\AAAA" x 250);
@fmtstring = ("%n%n%n%n%n", "%p%p%p%p%p", "%s%s%s%s%s", "%d%d%d%d%d",
"%x%x%x%x%x",
"%s%p%x%d", "%.1024d", "%.1025d", "%.2048d", "%.2049d",
"%.4096d", "%.4097d",
"%99999999999s", "%08x", "%%20n", "%%20p", "%%20s", "%%20d",
"%%20x",
"%#0123456x%08x%x%s%p%d%n%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%%",
"\0xCD" x 50, "\0xCB" x 50);
@numbers = ("0", "-0", "1", "-1", "32767", "-32768", "2147483647",
"-2147483647", "2147483648", "-2147483648",
"4294967294", "4294967295", "4294967296", "357913942",
"-357913942", "536870912", "-536870912",
"1.79769313486231E+308", "3.39519326559384E-313",
"99999999999", "-99999999999", "0x100", "0x1000",
"0x3fffffff", "0x7ffffffe", "0x7fffffff", "0x80000000",
"0xffff", "0xfffffffe", "0xfffffff", "0xffffffff",
"0x10000", "0x100000", "0x99999999", "65535", "65536",
"65537", "16777215", "16777216", "16777217", "-268435455");
@miscbugs = ("test|touch /tmp/ZfZ-PWNED|test", "test`touch
/tmp/ZfZ-PWNED`test", "test'touch /tmp/ZfZ-PWNED'test", "test;touch
/tmp/ZfZ-PWNED;test",
"test&&touch /tmp/ZfZ-PWNED&&test",
"test|C:/WINDOWS/system32/calc.exe|test",
"test`C:/WINDOWS/system32/calc.exe`test",
"test'C:/WINDOWS/system32/calc.exe'test",
"test;C:/WINDOWS/system32/calc.exe;test", "/bin/sh",
"C:/WINDOWS/system32/calc.exe", "%0xa", "%u000");
getopts('t:o:', \%opts);
$target = $opts{'t'};
$pdfdoc = $opts{'o'};
if(!defined($target) || !defined($pdfdoc))
{
print "\n pdfUZZ - PDF Fuzzer";
print "\nJeremy Brown
[0xjbrown41@xxxxxxxxx/http://jbrownsec.blogspot.com]";;
print "\n Usage: $0 -t
exit(0);
}
print "\n pdfUZZ - PDF Fuzzer";
print "\nJeremy Brown
[0xjbrown41@xxxxxxxxx/http://jbrownsec.blogspot.com]\n";;
print "\nFUZZING '$target' with '$pdfdoc' [STAGE->1(Version)]";
print "\n";
foreach(@numbers) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => $fuzz,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->2(Author)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->3(Title)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => $fuzz,
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => $fuzz,
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => $fuzz,
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->4(page_size)]";
print "\n";
foreach(@numbers) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => [$fuzz, $fuzz, $fuzz, $fuzz]);
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->5(Subject)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => $fuzz,
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => $fuzz,
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => $fuzz,
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->6(Keywords)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => $fuzz);
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => $fuzz);
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => $fuzz,
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => $fuzz);
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$pdf->close;
system $target $pdfdoc; }
print "\nFUZZING '$target' with '$pdfdoc' [STAGE->7(font/Subtype)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => $fuzz,
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => $fuzz,
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => $fuzz,
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->8(font/Encoding)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => $fuzz,
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => $fuzz,
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => $fuzz,
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->9(font/BaseFont)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => $fuzz);
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => $fuzz);
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => $fuzz);
$page->string($ffont, 20, 300, 300, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
print "\nFUZZING '$target' with '$pdfdoc' [STAGE->10(string/z+x+y)]";
print "\n";
foreach(@numbers) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, $fuzz, $fuzz, $fuzz, "pdfUZZ");
$pdf->close;
system $target $pdfdoc; }
print "FUZZING '$target' with '$pdfdoc' [STAGE->11(string/text)]";
print "\n";
foreach(@overflow) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, $fuzz);
$pdf->close;
system $target $pdfdoc; }
foreach(@fmtstring) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, $fuzz);
$pdf->close;
system $target $pdfdoc; }
foreach(@miscbugs) { $fuzz = $_;
$pdf = new PDF::Create('filename' => $pdfdoc,
'Version' => 1.2,
'Author' => 'pdfUZZ',
'Title' => 'pdfUZZ',
'CreationDate' => [localtime],
'Subject' => 'pdfUZZ',
'Keywords' => 'pdfUZZ');
$main = $pdf->new_page('MediaBox' => $pdf->get_page_size('A4'));
$page = $main->new_page;
$ffont = $pdf->font('Subtype' => 'Type1',
'Encoding' => 'WinAnsiEncoding',
'BaseFont' => 'Times-Roman');
$page->string($ffont, 20, 300, 300, $fuzz);
$pdf->close;
system $target $pdfdoc; }
exit;
#EOF
Aucun commentaire:
Enregistrer un commentaire