|
#!/usr/bin/perl -w
|
|
use Capture::Tiny 'capture';
|
|
use Devel::GDB;
|
|
use File::Find;
|
|
use Getopt::Long;
|
|
my %config;
|
|
Getopt::Long::Configure("prefix_pattern=(-|--)");
|
|
GetOptions( \%config, qw(f=s n=s r=s c=s e=s h help) );
|
|
|
|
&parseopts();
|
|
|
|
#Parse the options
|
|
sub parseopts {
|
|
|
|
#display help if asked
|
|
if ( $config{h} || $config{help} ) {
|
|
&printhelp();
|
|
}
|
|
|
|
#filemaks do we have a path to pcaps?
|
|
if ( $config{f} ) {
|
|
@files = <$config{f}>;
|
|
}
|
|
else {
|
|
print("filemask not specified or doesn't exist\n");
|
|
&printhelp();
|
|
}
|
|
|
|
#number of times to loop
|
|
if ( $config{n} ) {
|
|
$loopnum = $config{n};
|
|
print( "looping " . $loopnum . " times or until we have an error\n" );
|
|
}
|
|
else {
|
|
print("looping forever or until we have an error\n");
|
|
$loopnum = "infinity";
|
|
}
|
|
|
|
#rules file do we have a path and does it exist
|
|
if ( $config{r} && -e $config{r} ) {
|
|
$rules = $config{r};
|
|
print "rules file $rules\n";
|
|
}
|
|
else {
|
|
print("rules file not specified or doesn't exist\n");
|
|
&printhelp();
|
|
}
|
|
|
|
#config file do we have a path and does it exist
|
|
if ( $config{c} && -e $config{c} ) {
|
|
$configfile = $config{c};
|
|
print "rules file $rules\n";
|
|
}
|
|
else {
|
|
print("config file not specified or doesn't exist\n");
|
|
&printhelp();
|
|
}
|
|
|
|
#error ratio to introduce TODO validate between 0.00 and 1.0
|
|
if ( $config{e} ) {
|
|
$editeratio = $config{e};
|
|
print "using error ratio" . $editeratio . "\n";
|
|
}
|
|
else {
|
|
print("not fuzzing pcap(s)\n");
|
|
}
|
|
|
|
}
|
|
|
|
sub printhelp {
|
|
print(
|
|
"-f=<filemask for pcaps>\n-n=<number of iterations or if not specified will run until error>\n-r=<path to ids rules file>\n-e=<editcap error ratio to introduce if not specified will not fuzz>\n"
|
|
);
|
|
exit;
|
|
}
|
|
$successcnt = 0;
|
|
while ($successcnt <= $loopnum ) {
|
|
|
|
#@files = </home/coz/downloads/pcaps/*/*.pcap>;
|
|
foreach $file (@files) {
|
|
print $file . "\n";
|
|
$file =~ s/\(/\\(/g;
|
|
$file =~ s/\)/\\)/g;
|
|
( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
|
|
localtime(time);
|
|
$timestamp = sprintf "%4d-%02d-%02d-%02d-%02d-%02d", $year + 1900,
|
|
$mon + 1, $mday, $hour, $min, $sec;
|
|
|
|
if ( defined $editeratio ) {
|
|
$fuzzedfile = $file . "-fuzz-" . $timestamp;
|
|
$editcapcmd = "editcap -E 0.02 " . $file . " " . $fuzzedfile;
|
|
print( "running " . $editcapcmd . "\n" );
|
|
system("$editcapcmd");
|
|
}
|
|
else {
|
|
$fuzzedfile = $file;
|
|
}
|
|
|
|
#$fuzzedfile = $file;
|
|
$fullcmd =
|
|
"ulimit -c unlimited; src/suricata -c "
|
|
. $configfile . " -r "
|
|
. $fuzzedfile
|
|
. " -l ./ -s "
|
|
. $rules;
|
|
print "running $fullcmd \n";
|
|
( $out, $err ) = capture {
|
|
system $fullcmd;
|
|
$exit = $? >> 8;
|
|
};
|
|
|
|
#print "out:$out\n";
|
|
#print "err:$err\n";
|
|
print "exit value $exit\n";
|
|
if ( $exit ne 0 ) {
|
|
|
|
$report = $fuzzedfile . "ERR.txt";
|
|
open( REPORT, ">$report" )
|
|
|| ( print "Could not open report file! $report\n" );
|
|
|
|
#print REPORT "$0\n";
|
|
print REPORT "COMMAND:$fullcmd\n";
|
|
print REPORT "STDERR:$err\n";
|
|
print REPORT "EXITVAL:$exit\n";
|
|
print REPORT "STDOUT:$out\n";
|
|
|
|
&core_dump();
|
|
if ($core_dump) {
|
|
print REPORT $core_dump;
|
|
print "core dump \n $core_dump";
|
|
system( "mv /home/coz/downloads/oisfnew/core "
|
|
. $fuzzedfile
|
|
. ".core" );
|
|
}
|
|
close(REPORT);
|
|
exit;
|
|
}
|
|
else {
|
|
$successcnt++;
|
|
print( "we have run with success " . $successcnt . " times\n" );
|
|
if ( defined $editeratio ) {
|
|
$rmcmd = "rm -f " . $fuzzedfile;
|
|
print( "running " . $rmcmd . "\n" );
|
|
system("$rmcmd");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub core_dump {
|
|
my $self = shift;
|
|
$core_dump = "";
|
|
|
|
if ( eval { require Devel::GDB } ) {
|
|
find( \&dump_core_file, "/home/coz/downloads/oisfnew/" );
|
|
}
|
|
|
|
$core_dump || ' [CORE TRACE COMES HERE]';
|
|
}
|
|
|
|
sub dump_core_file {
|
|
return unless /^core(\.\d+)?$/;
|
|
|
|
my $core = $_;
|
|
print "core dump found $core processesing \n";
|
|
my $gdb = new Devel::GDB();
|
|
$core_dump .= join '',
|
|
$gdb->get("file /home/coz/downloads/oisfnew/src/suricata"),
|
|
$gdb->get('sharedlibrary'), $gdb->get("core $core"),
|
|
|
|
#$gdb->get('info threads'),
|
|
#$gdb->get('thread apply all bt full');
|
|
$gdb->get('bt full');
|
|
print "core dump \n $core_dump";
|
|
|
|
}
|