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:

/usr/local/etc/autodafe/

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:

#> cat ./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:
  1. 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.
  2. The fuzzer autodafe uses the description (contained in the file vuln2.adc) to simulate a normal (previously captured) communication with the targeted software program.
  3. 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".
  4. The tracer analyses the execution of the targeted software program in order to detect if unsafe functions use markers.
  5. 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.
  6. 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.
  7. 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]