TUTORIAL
AUTODAFE
A FUZZING FRAMEWORK
© Copyright 2004-2006 Martin Vuagnoux
autodafe@vuagnoux.com
VERSION 0.1
TABLE OF CONTENT
1. INTRODUCTION
2. INSTALLATION
3. FUZZING
4. FIRST EXAMPLE: A DUMMY PROTOCOL
5. REAL CASE 1: GHOSTVIEW-3.5.8
INTRODUCTION
Welcome to the Autodafé's Tutorial. Here, you will learn how to
use the Autodafé framework. In particular we will see how to
analyse the security of network based and file based software
programs.
First of all We recommend you to read the paper "Autodafé: an
Act of Software Torture" which explains the core technique of this
fuzzer. You can download it on the web page http://autodafe.sourceforge.net/paper/autodafe.pdf
or read the pdf file located at:
/usr/local/autodafe-0.1/docs/autodafe.pdf
... But we know, most of the time people just want to understand how
to use a tool with clear and detailed examples. It is exactly what we
will do in this document. First of all we will install the tool and
play a little bit with a dummy example. Then we will attack real
software programs.
INSTALLATION
Autodafé needs tools and libraries:
Then the installation is the usual ./configure && make && make install
way:
#> cp autodafe-0.1.tar.gz /usr/local/src
#> cd /usr/local/src
#> tar zxvf autodafe-0.1.tar.gz
#> mv ./autodafe-0.1 /usr/local/
#> cd /usr/local/autodafe-0.1/
#> ./configure
#> make
#> make install
Because Autodafé needs to debug/trace targeted software programs, you
may need to use the root account.
Note that during the compilation, the fuzzing library is created and
needs approximately 50MB of free space. The fuzzing library is
installed by default in the directory:
If something goes wrong, see the FAQ or contact the authors.
FUZZING
If you don't know anything about fuzzing, please read the paper
"Autodafé: an Act of Software Torture" or look at the slides of the
presentation given at the 22C3 (22nd Chaos Computer Club Congress) on
the web page (http://autodafe.sourceforge.net). Yes,
we spend time to do something user friendly (it is a Macromedia Flash
animation) so please, read it ;-). If you are too lazy (we can
understand that) here is a very brief definition:
Fuzzing is used to send malformed data to programs software in order
to highlight vulnerabilities like buffer overflows.
You can easily understand that it is not a simple as it seems, because
software programs use protocols and do not accept random data. So
sending just plenty of "AAAA.." (you know, the trivial `perl -e 'print
"A"x303'`) is not always relevant to uncover buffer overflows. Let us
have a dummy example to understand why Autodafé can be useful.
FIRST EXAMPLE: A DUMMY PROTOCOL
In this section, we will attack a dummy protocol to understand how
Autodafé works. This protocol is inspired by a real one, which is used
to remotely access to a computer. Yes, the flaw still exists ;-P
Anyway, first of all you need to create the dummy server. The source
is in the directory: /usr/local/autodafe-0.1/docs/tutorials/dummy/
#> cd /usr/local/autodafe-0.1/docs/tutorials/dummy/
#> make
You don't really need to read the source code. Most of the time,
fuzzers are used against compiled software programs. Thus you normally
don't have access to the source code. What you really need is to
understand how the protocol works and that's the big deal with
fuzzers.
vuln2 is a server tool which uses a protocol. In most fuzzers you need
to describe the protocol, in order to send valid data (i.e. data
accepted by the server). Autodafé helps you in this boring task:
PDML2AD
The usual way to understand a protocol is to sniff the communication
between the server and a client. To do that, you can use for example
the sniffer ethereal (http://www.ethereal.com) or
wireshark (http://www.wireshark.org) which
uses its own protocol recognition engine called dissector. Ethereal
already recognizes 750 protocols (version 0.10.14)! But in this case
it's a dummy example so the protocol is obvioulsy not known by
ethereal.
Let have a look to the file vuln2.pdml:
It is the PDML export version of the sniffed communication between the
server and a client. In this case we consider that you sniffed the
data between the server and a client and you saved the dump in the
PDML format. It is a very useful format which is used by Autodafé to
describe protocols.
To do that, use the tool pdml2ad which converts a pdml document to the
Autodafé Protocol Description Script Langage. This script is very
similar to the script used by Spike, one of the best fuzzer (thanks
Dave Aitel). Let see how pdml2ad works:
#> pdml2ad --help
pdml2ad-v.0.1 - convert PDML file to Autodafe's script language
pdml2ad-v.0.1 - (c) 2004-2006 Martin Vuagnoux <autodafe@vuagnoux.com>
Usage: pdml2ad [OPTION...] <FILE.pdml> <FILE.ad>
-h, --help display this help and exit.
-V, --version output version information and exit.
-e, --no-ethereal-style not using the ethereal hexadecimal style.
-p --recover-protocol try to recover the used protocol.
-s, --recover-strings try to recover strings in packet.
-i, --invert-send-recv some servers speak first, some clients speak first.
-v, --verbose verbose output.
-d --debug use 2x or 3x for more debug info.
FILE is a PDML-XML file (Packet Details Markup Language) generally exported
by Ethereal.
A file <FILE.AD> is created.
We know that dissector, the ethereal protocol recognition engine will
not recognize this protocol, but we can use the option which tries to
recover strings. It is always good to test it if the protocol is ASCII
based.
#> pdml2ad -v -s ./vuln2.pdml ./myvuln2.ad
[*] parsing the file: ./vuln2.pdml
#> cat ./myvuln2.ad
/*--------------------------------------------------------------------------*
* xml autodafe's parser v.0.1 (c) Martin Vuagnoux - 2004-2006 *
* auto-generated script using PDML (Packet Details Markup Language) source *
*--------------------------------------------------------------------------*/
block_begin("packet_1");
hex(
51 55 45 53 00 00 00 03 41 41 41 45 4e 44 0a
);
block_end("packet_1");
recv("packet_1"); /* tcp */
block_begin("packet_2");
block_end("packet_2");
send("packet_2"); /* tcp */
We can see that it's not a string because there is values which do not
correspond to ASCII characters. But the \x0a at the end can suggest
that a part of the protocol is string based.
Because the protocol has not been recognized by ethereal we need to
understand a little bit how the Autodafe Protocol Description Script
Langage works. It is inspired by the Block-Based Description invented
by Dave Aitel: We define blocks of data and length fields binded to
blocks, which will be updated if more data are injected in a block.
The Autodafé Protocol Description Script Langage is defined by a few
function:
string("hello world"); /* just an ASCII string limited to 255 characters */
hex(fa); /* hexadecimal value with three possible notations */
hex(\xfa); /* fa == \xfa == 0xfa */
hex(0xfa); /* you can write up to 4GBytes of hex values */
block_begin("my block"); /* start a block */
block_end("my block"); /* close a block */
block_size_b32("my block"); /* 32-bit big endian size of the block "my block" */
block_crc32_b("my blcok"); /* 32-bit big endian crc32 of the block "my block" */
send("my block"); /* send the block "my block" */
/* when you want to fuzz a string, you replace the "string" with "fuzz_string"
* then, Autodafé will know which string you want to fuzz */
fuzz_string("hello world");
/* you can do the same thing with hexadecimal values */
fuzz_hex(0x00 00 \x00 ff);
For the complete description of the Autodafe Script Language, look at
the paper "Autodafé: an Act of Software Torture". This langage is very
limited to be as simple as possible.
Let's go back to our example: in this case, the dummy protocol can be
described by:
QUES<Size in big-endian 32 bit of block 1><block 1>END\n
The last block "packet_2" is useless because it is empty, we can
remove it. Then we can finally describe the protocol with the Autodafé
Script Language (see the file vuln2.ad or vuln2-orig.ad in the dummy
directory).
#> cat ./vuln2.ad
block_begin("packet_1");
string("QUES");
block_size_b32("string_1"); /* big endian 32 bits size */
block_begin("string_1");
fuzz_string("AAA");
block_end("string_1");
string("END");
hex(0a); /* \n */
block_end("packet_1");
send("packet_1"); /* tcp */
You can see that we decide to fuzz the string "AAA". That's why the
function "string" has been replaced by the function "fuzz_string". The
other strings or values will not be substituted by the fuzzer.
Of course, when the protocol is recognized by ethereal (750 protocols
with the version 0.10.14 of ethereal), the description is pratically
automated. Let see the example of a SSH packet (the first one)
recognized by ethereal and converted in the Autodafe Script Langage:
block_begin("packet_1");
// name: ssh.protocol
// showname: Protocol: SSH-1.99-OpenSSH_4.2\n
// show: SSH-1.99-OpenSSH_4.2\x0a
// size: 21
string("SSH-1.99-OpenSSH_4.2");
hex(0a); /* \n */
block_end("packet_1");
send("packet_1"); /* tcp */
We will see in another tutorial the power of pdml2ad with known
protocols. But for our first case, this description is largely enough.
ADC
When you are using a script langage, you can easily make mistakes
(especially syntax errors). To help you, the Autodafé Framework comes
with a "compiler" called adc. Adc will check if the syntax of the
Autodafé Script Langage is correct and convert the script (*.ad) into
a binary file (*.adc) the Checked Autodafe Description Protocol Script
Langage. Only binary checked files can be used by the fuzzer autodafe.
Let us compile the file vuln2.ad:
#> adc ./vuln2.ad
[!] block: "string_1" size: 3 (0x3)
[!] block: "packet_1" size: 15 (0xf)
Ok, everything is ok, you can see that a new file called "vuln2.adc"
has been created. Just as an example, try to compile the malformed
Autodafé Script Langage "bad-vuln2.ad" where the block "string_1" has
not been closed.
#> adc ./bad-vuln2.ad
[YY-ERROR] block: "string_1" has not been ended
[!] block: "string_1" size: 7 (0x7)
[!] block: "packet_1" size: 15 (0xf)
[YY-ERROR] at line[20]: See block(s) error(s) above
Anyway, forget the bad example and go back to the good one
"vuln2.adc". We have now a limited but enough description of the
protocol. It's time to launch the targeted software program using the
debugger/tracer adbg.
ADBG
This tool is very powerful. It uses gdb to trace the software program
in order to weight the attacks. It will check which vulnerable
functions are called by the targeted program and give weight to every
fuzzed variables like fuzz_string or fuzz_hex. Well, in our example we
choose to fuzz only one variable but it's a dummy example ;-). Let's
have a look of the adbg's help:
#> adbg --help
adbg-v.0.1 - debugger which listen the targeted software.
adbg-v.0.1 - (c) 2004-2006 Martin Vuagnoux <autodafe@vuagnoux.com>
Usage: adbg [OPTION...] [<program>] ["<args>"]
List of the basic functions:
-h, --help display this help and exit.
-V, --version output version information and exit.
-v, --verbose verbose output (use twice for more verbose info).
-d --debug debug output (use 2x or 3x for more debug info).
List of the internal's debugger' s functions:
-G --gdb-dump=FILE copy the gdb's output in a file.
-s --string-dump=FILE copy the vulnerables strings in a file.
List of the debugger's functions:
-p --port=NUM The listening TCP port of the debugger.
-P --pid=NUM the pid of the program you want to debug.
-i --input=FILE file which contains the strings used to break.
The standard output give the informations.
the targeted software program "vuln2" is quite simple, it just asks
for a listening port number:
#> ./vuln2
./vuln2 <listening_port>
The debugger adbg listen to a local port in order to communicate with
the fuzzer autodafe. Here is a example how to start adbg:
#> adbg -v -p 31337 ./vuln2 2000
[*]-+-> breakpoint on: "strcpy"
[*]-+-> breakpoint on: "strcat"
[*]-+-> breakpoint on: "gets"
...
[*] waiting for a connection on port: 31337
Here you can see what are the vulnerable function where the
debugger/tracer will break. Feel free to add more. The public version
of autodafe is intentionally limited to a few unsafe function :-) Now
the debugger is waiting for a connection on port 31337. This connection
will be initiated by the fuzzer autodafe, the fuzzer engine.
AUTODAFE
Autodafe is the fuzz core engine. It will parse the Checked Protocol
Description Script Langage (vuln2.adc) and will send the captured data
to the targeted software. Let us have a look to the exact procedure:
- A partial description of the audited protocol is given to the
fuzzer using a block-based protocol language. Every canonical element
is considered as a marker. In our example, the string "AAA" is a
marker.
- The fuzzer autodafe uses the description (contained in the file
vuln2.adc) to simulate a normal (previously captured) communication
with the targeted software program.
- The tracer adbg receives from the fuzzer autodafe a list of markers
and runs the targeted software program. The markers are typically the
string you want to test. In our example there is only one marker, the
string "AAA".
- The tracer analyses the execution of the targeted software program
in order to detect if unsafe functions use markers.
- If a marker is used by unsafe functions, the tracer gives a bigger
weight to the marker and communicates its results to the fuzzer
autodafe.
- According to the weight of markers, the fuzzer autodafe classify
which markers should be tested. Markers which do not use vulnerable
functions are not fuzzed during the first pass.
- If a fuzzed variable causes a buffer overflow, the tracer abbg
gives to the auditor additional information about this vulnerability.
Let's have a look to the autodafe's help:
autodafe --help
autodafe-v.0.1 - This is the Autodafe Fuzzer Engine
autodafe-v.0.1 (c) 2004-2006 Martin Vuagnoux <autodafe@vuagnoux.com>
Usage: autodafe [OPTION...] <file.adc>
List of the basic functions:
-h, --help display this help and exit.
-V, --version output version information and exit.
-v, --verbose verbose output. Use twice for more verbose.
-d --debug print debug info. Use 2x or 3x for more debug info.
List of the autodafe's functions:
-t --timeout=SEC if no response, wait SEC seconds before go on.
-u --udp use an udp connection - default is tcp.
-f --file=DIR create multiple fuzzed files in directory DIR.
-r --remote=HOST mode *client*: HOST = hostname/ip address.
-p --port=PORT mode *client*: PORT = port to connect to.
mode *server*: PORT = listening port [-r not defined].
-D --with-dbg=HOST debugger: HOST = hostname/ip of the debugger.
-P --dbg-port=PORT debugger: PORT = listening port of the debugger.
List of the internal's autodafe's functions:
-b --bruteforce fuzz every fields.
-i --invert send() becomes recv() and recv() becomes send().
-w --wait=SEC wait SEC seconds before opening connection.
<file.adc> is a type of file used by the fuzzer.
The standard output gives the results of the fuzzing.
In our case, we launch autodafe like this:
#> autodafe -v -p 2000 -r localhost -P 31337 -D localhost ./vuln2.adc
[*] Autodafe's debugger mode activated.
[*] mode *client* - connection to localhost on port: 2000 (tcp)
[*] parsing file: "./vuln2.adc"
[*] debugger connected: localhost on port 31337
[!] source: "/usr/local/etc/autodafe/string/string-1-x3" (3 bytes)
[!] source: "/usr/local/etc/autodafe/string/string-1-sp-x3" (4 bytes)
[!] source: "/usr/local/etc/autodafe/string/string-1-x4" (4 bytes)
[!] source: "/usr/local/etc/autodafe/string/string-1-sp-x4" (5 bytes)
[!] source: "/usr/local/etc/autodafe/string/string-1-x15" (15 bytes)
...
[1] waiting 1 seconds before opening connection...
[*] connected to: localhost on port: 2000
[!] this fuzz is *NOT* relevant, we don't fuzz id: 0
The debugger/tracer output is:
[*] connection from: 127.0.0.1
[*] fuzzer authenticated and connected. (v.0.1)
[+]-+-> add monitored string: "AAA"
[*] targeted software running... (analysis in progress)
[*]-+-> breakpoint on: "printf"
...
Hmmm... Ok, there was only one marker (id 0) which is the string
"AAA". The debugger/trace chooses to NOT fuzz the string because the
string is not used by an unsafe function. Believe me, there is a flaw
;-) so we will force autodafe to fuzz every marker by adding "-b" or
"--bruteforce". The command for adbg is:
#> adbg -v -p 31337 ./vuln2 2000
To have more verbose information, we add -vv. Thus, the new command
for autodafe is:
#> autodafe -b -vv -p 2000 -r localhost -P 31337 -D localhost ./vuln2.adc
[*] Autodafe's debugger mode activated.
[*] mode *client* - connection to localhost on port: 2000 (tcp)
[*] parsing file: "./vuln2.adc"
[*] debugger connected: localhost on port 305
[!] source: "/usr/local/etc/autodafe/string/string-1-x3" (3 bytes)
[!] source: "/usr/local/etc/autodafe/string/string-1-sp-x3" (4 bytes)
[!] source: "/usr/local/etc/autodafe/string/string-1-x4" (4 bytes)
[!] source: "/usr/local/etc/autodafe/string/string-1-sp-x4" (5 bytes)
[!] source: "/usr/local/etc/autodafe/string/string-1-x15" (15 bytes)
[!] source: "/usr/local/etc/autodafe/string/string-1-sp-x15" (16 bytes)
[!] source: "/usr/local/etc/autodafe/string/string-1-x16" (16 bytes)
...
[*] computing the block's length.
[1] waiting 1 seconds before opening connection...
[*] connected to: localhost on port: 2000
+------------[send buffer (size: 00015)]----------+----------------+
51 55 45 53 00 00 00 03 41 41 41 45 4e 44 0a QUES....AAAEND.
+------------[send buffer (size: 00015)]----------+----------------+
At this step, the fuzzer autodafe has just sent the original packet in
order to let the debugger/tracer adbg to analyse the behavior of the
targeted software program. You can recognize the protocol:
QUES<size of the string "AAA" in 32-bit big-endian>"AAA"END
[*] computing the block's length.
[*] connected to: localhost on port: 2000
+------------[send buffer (size: 00015)]----------+----------------+
51 55 45 53 00 00 00 03 41 41 41 45 4e 44 0a QUES....AAAEND.
+------------[send buffer (size: 00015)]----------+----------------+
You have probably remarked the strings above:
[!] source: "/usr/local/etc/autodafe/string/string-1-x3" (3 bytes)
...
[!] source: "/usr/local/etc/autodafe/string/string-1-x16" (16 bytes)
These files constitute the substituted fuzz library. Each fuzzed
string (in our example "AAA") is successively replaced by the content
of these files. The first file is called "string-1-x3" and contains
the 3-byte string "AAA". I know, it's the same as the orginal, quite
useless in this case.
After a while, the string "AAA" is substituted by the 16-byte string
"AAAAAAAAAAAAAAAA". You can see that the length value (5th byte to 9th
byte) has correctly been modified. It takes the size 00 00 00 10, which
is 16 in 32-bit big endian.
[*] computing the block's length.
[*] connected to: localhost on port: 2000
+------------[send buffer (size: 00028)]----------+----------------+
51 55 45 53 00 00 00 10 41 41 41 41 41 41 41 41 QUES....AAAAAAAA
41 41 41 41 41 41 41 41 45 4e 44 0a AAAAAAAAEND.
+------------[send buffer (size: 00028)]----------+----------------+
The interesting part come here. When the string is replaced by a
255-byte string, the debugger is sending a message.
[*] the debugger has something to say!
[*] the debugger says: [***] Segmentation fault - signal [***]
+------------[send buffer (size: 00267)]----------+----------------+
51 55 45 53 00 00 00 ff 41 41 41 41 41 41 41 41 QUES....AAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA
41 41 41 41 41 41 41 45 4e 44 0a AAAAAAAEND.
+------------[send buffer (size: 00267)]----------+----------------+
Yepah!, you can confirm the message by looking at the adbg's output:
[***] SEGMENTATION FAULT!
[***] EIP: 0x41414141
Hohooo.. a basic stack-based overflow! Well, this is the end of the
first tutorial. I hope you understand much better how autodafe works
now. But dummy examples are not very funny... Next, a real case ;^P
REAL CASE 1: GHOSTVIEW-3.5.8
Autodafe is not only able to fuzz network protocols, it can fuzz
files. For example it can be useful to test the security of the PDF,
MS-Word, Postscript, JPEG, GIF TIFF, whatever readers. For this
tutorial, we will concentrate our attack on a famous Postscript
reader, installed by default in some current Linux distributions: gv
version 3.5.8.
A format file is a protocol. For example, Postscript is an ASCII-based
protocol. Let's have a look on it. All the files are in the directory:
/usr/local/autodafe-0.1/docs/tutorials/gv-3.5.8/
First of all, install the last version (3.5.8) of gv. You can find it
here: http://wwwthep.physik.uni-mainz.de/~plass/gv/.
A local version of the vulnerable software program is present in the
directory gv-3.5.8. To understand how Postscript works, let us
generate a Postscript file:
#> cd /usr/local/autodafe-0.1/docs/tutorials/gv-3.5.8/
#> cat hello.txt
Hello World!
Now, we convert this text file into a Postscript file:
#> a2ps hello.txt -o hello.ps
[hello.txt (plain): 1 page on 1 sheet]
[Total: 1 page on 1 sheet] saved into the file `hello.ps'
#> cat ./hello.ps
%!PS-Adobe-3.0
%%Title: hello.txt
%%For:
%%Creator: a2ps version 4.13
%%CreationDate: Mon Apr 24 13:31:07 2006
%%BoundingBox: 24 24 588 768
%%DocumentData: Clean7Bit
%%Orientation: Landscape
%%Pages: 1
...
%%Trailer
end
%%EOF
If you don't have the tool a2ps, a Postscript version called
hello-orig.ps is present in the gv-3.5.8 directory.
TXT2AD.SH
As you can see, Postscript is ASCII-based, perfect for Autodafé. First
of all we need to convert this file in the Autodafe Protocol
Description Script Langage. Obviously we cannot use ethereal here, so
we will use a simple bash-script called "txt2ad.sh". This script is
located in the directory /usr/local/autodafe-0.1/tools/
#> cp /usr/local/autodafe-0.1/tools/txt2ad.sh ./
#> ./txt2ad.sh ./hello.ps > hello.ad
#> cat ./hello.ad
block_begin("1");
string("%!PS-Adobe-3.0"); hex(0a);
string("%%Title: hello.txt"); hex(0a);
string("%%For: "); hex(0a);
string("%%Creator: a2ps version 4.13"); hex(0a);
string("%%CreationDate: Mon Apr 24 13:31:07 2006"); hex(0a);
string("%%BoundingBox: 24 24 588 768"); hex(0a);
string("%%DocumentData: Clean7Bit"); hex(0a);
string("%%Orientation: Landscape"); hex(0a);
string("%%Pages: 1"); hex(0a);
...
string("%%Trailer"); hex(0a);
string("end"); hex(0a);
string("%%EOF"); hex(0a);
block_end("1");
send("1");
The script just add the string function for each line and convert the
'\n' to hex(0a);. Now we need to isolate the markers able to be called
by unsafe functions. But we don't know which strings are relevant to
test. We can replace every "string" by "fuzz_string" and let the
debugger/tracer adbg give weight to each markers. Another solution is
to ask to the debugger/tracer adbg to give us the strings called by
unsafe functions.
ADBG
To do that, the debugger/tracer will analyse the targeted software
program and give us all the strings used by these vulnerable
functions:
#> adbg -v -s vulnerable.txt ./gv ./hello.ps
Close the application (X-window is needed in this case) and look at
the strcpy calls:
#> cat ./vulnerable.txt |grep strcpy
strcpy:C
strcpy:\e(B
strcpy:\e-A
strcpy:\e-B
strcpy:\e-C
strcpy:\e-D
strcpy:\e-L
...
strcpy:shutdown
Hmmm.. lof of calls ;-) Just for fun:
#> cat ./vulnerable.txt |grep strcpy |wc -l
685
Now we will choose a marker which is controlled by the Postscript
file. Let us check the markers in the hello.ad file. For example, the
number of page given by the Postscript function "Pages:" at line 10:
string("%%Pages: 1"); hex(0a);
The string "1" seems to be a good candidate, because the string "1" is used by the function "strcpy":
#> cat ./vulnerable.txt |grep "strcpy:1"
strcpy:1
strcpy:1
strcpy:1
...
let us edit the hello.ad file and replace the line 10 with the line:
string("%%Pages: "); fuzz_string("1"); hex(0a);
Now the string "1" will be fuzzed by autodafe. This change is
done in the file fuzz_hello.ad.
ADC
The next step is to compile the new file fuzz_hello.ad:
#> adc ./fuzz_hello.ad
[!] block: "1" size: 14077 (0x36fd)
AUTODAFE
Remember that we are fuzzing files, it's not possible to create a
connection to a server in this case. Autodafe will be used to create
plenty of malformed Postscript files in a special directory. Then,
these files will be opened successively with the targeted software
program. Let us generate these files with autodafe:
#> mkdir ./fuzz
#> autodafe -v -f ./fuzz ./fuzz_hello.adc
[!] created file: "./fuzz/00000000"
...
[!] created file: "./fuzz/00001740"
As you can see, 1741 files were created by the fuzzer autodafe. To
test them, try to open each file with the targeted software program
gv. I will give you a hint, start directly with the file "00000034":
#> cd ./fuzz
#> head ./00000034
%!PS-Adobe-3.0
%%Title: hello.txt
%%For:
%%Creator: a2ps version 4.13
%%CreationDate: Mon Apr 24 13:31:07 2006
%%BoundingBox: 24 24 588 768
%%DocumentData: Clean7Bit
%%Orientation: Landscape
%%Pages: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[...]aaaaaaaaaaaaaa
%%PageOrder: Ascend
Here you can see the string substituted by autodafe. Quite easy isn't
it? Now prepare for a Segmentation Fault :-)
#> ulimit -c unlimited
#> gv ./00000034
Segmentation fault (core dumped)
Hohooo... Now check exactly what is the state of the registers to know
what kind of buffer overflow we uncovered:
#> gdb -q -c ./core
(no debugging symbols found)
Using host libthread_db library "/lib/tls/libthread_db.so.1".
Core was generated by `gv 00000034'.
Program terminated with signal 11, Segmentation fault.
#0 0x61616161 in ?? ()
(gdb) p $eip
$1 = (void (*)()) 0x61616161
(gdb)
The register EIP has been replaces by 0x61616161 which is "aaaa".
It's a basic Stack based buffer overflow. As an exercise, try to
uncover other buffer overflows with different markers. There is
hundreds of Heap based, Stack based and Format String based buffer
overflows. Next time you will open a Postscript file, be careful ;-)
This conclude the second tutorial.
[EOF]