The following is a simple tool for tracking buffer overflows. It uses GDB calls to get register's addresses during the overflow.
Tool source:
#!/usr/bin/perl
# _____ _
# | ___| | _____ __
# | |_ | |/ _ \ \ /\ / /
# | _| | | (_) \ V V /
# |_| |_|\___/ \_/\_/
# Security group.
#
# fl0w-s33ker.pl v1.4
#
#
# I wrote no README or Changelog just
# becouse i have no patience at all.
# In doubt make me questions
# on irc.flowsecurity.org at #flowsecurity.
#
# Try: ./fl0w-s33ker.pl -h
#
# 1: Simple test. Ex. ./vulnerable "$buffer"
# 2: Adjacent mem test. Ex. ./vulnerable 512 "$buffer"
# 3: Environment test. Ex. export HACK="AAAA" ; ./vulnerable
# 4: Lame Integer test. Ex. ./vulnerable slot-number integer
#
# Enjoy
#
# Author: nuTshell -=nutshell@flowsecurity.org=-
#
# Greetz:
# Friends from irc.flowsecurity.org
# and friends from everywhere.
#
use strict;
use Switch;
use Devel::GDB;
use Term::ANSIColor;
my $version = "fl0w-s33ker.pl v1.4";
my $string = "\x41";
my $space = "\x20";
my $sigsegv = 35584;
my $barloop =0;
my $bar = 0;
my $simple = 0;
my $counter = 1;
my $debugeipcounter = 0;
my $buff = "$string";
my $intcounter = -1073746000;
my $intcounterend = 1073746000;
my $inteip = "0xbfffff*";
my $logfile2 = "LOG-s33ker.txt";
my $ret = "";
my $firstsigsegv = "";
my $gdb = "";
my $blimit = "";
my $bugfile = "";
my $logfile = "";
my $logname = "";
my $status = "";
my $adjstring = "";
my $adjlength = "";
my $output = "";
my $option = "";
my $errlog = "";
my $HACK = "";
my $CMD = "";
my $execargs = "";
my $debug = "";
my $debugeip = "";
my $debugeipcounterlmt = "";
my $debugeipinput = "";
my $counterlmt = "";
my $date = "";
sub info1() {
printf <<EOF
Limit is set: $blimit bytes
Filling up $bugfile`s buffer with 0x41 (A`s)
until we get SIGSEGV, if progress bar stop try ctrl+c.
Wait...
EOF
}
sub info2() {
printf <<EOF
Lame integer overflow test.
Starting from $intcounter to $intcounterend.
We must have $inteip as \$eip address.
Wait...Go get a coffee :]
EOF
}
sub log1 () {
open(LOGCOMOM, ">>$logfile2") or die "$!\n";
printf(LOGCOMOM "\n -= $date =- \n");
printf(LOGCOMOM " Tested file: $bugfile\n");
printf(LOGCOMOM "First SIGSEGV occurs at $firstsigsegv bytes.\n");
printf(LOGCOMOM "At $ret bytes:\n");
printf(LOGCOMOM "$output\n");
close(LOGCOMOM);
printf("Log saved!\n");
exit(0);
}
sub log2() {
open(LOGCOMOM, ">>$logfile2") or die "$!\n";
printf(LOGCOMOM "\n -= $date =- \n");
printf(LOGCOMOM " Tested file: $bugfile\n");
printf(LOGCOMOM "$debugeip");
printf(LOGCOMOM "Got \$esp address at value $intcounter\n");
close(LOGCOMOM);
printf("Log saved!\n");
exit(0);
}
sub log3() {
open(LOGCOMOM, ">>$logfile2") or die "$!\n";
printf(LOGCOMOM "\n -= $date =-\n");
printf(LOGCOMOM " Tested file: $bugfile\n");
printf(LOGCOMOM "SIGSEGV occurs at $ret bytes.\n");
close(LOGCOMOM);
printf("Log saved!\n");
}
sub menu () {
printf <<EOF
+-+-+-+-+-+-+-+-+-+-+-+-+-+- fl0w-s33ker +-+-+-+-+-+-+-+-+-+-+-+-+-+
Coded by nuTshell -= nuTshell\@flowsecurity.org =-
Usage: $0 <ENTER>
Filename [Vulnerable filename]
Options:
[1] simple test
[2] adjacent test
[3] environment test (no dubugging)
[4] integer overflow test
sub cmdarg () {
printf("Enter as many arguments as needed.\n");
printf("Each arg must be followed by <ENTER>\n");
printf("To finish just type \"quit\":\n");
$CMD = <STDIN> ; chop($CMD);
$CMD .= $space;
while ($CMD !~ /quit/) {
$CMD .= <STDIN> ;chop($CMD);
$CMD .= $space;
}
$CMD =~ s/quit//g;
}
if ("$ARGV[0]" eq "-h") {&menu and exit(0)}
if ("$ARGV[0]" eq "-v") {printf "$version\n" and exit(0)}
if ("$ARGV[0]" eq "-lw" || "$ARGV[0]" eq "-lall") {
$logfile = ">> LOG-s33ker.weird.txt 2>&1";
$logname = $logfile;
$logname =~ s/2>&1//g;
printf color("bold");
printf("\nWARNING");
printf color("reset");
printf(": \"-lw and -lall\" flags can be dangerous..well what isn`t??\n");
printf("Logging stderr can get big files depending on your test.\n");
printf("Ctrl+c...? \"Warned were you\" -yoda :)\n");
printf("Logname $logname\n");
} else {$logfile = ">/dev/null 2>&1"}
printf("\n-= $version =-\n-= Coded by nuTshell =-\n");
printf("\nFilename:\n");
printf("option> ");
$bugfile = <STDIN> ; chop($bugfile);
if (! -f $bugfile) {die "$bugfile $!\n"}
printf("Options:\n");
printf("[1] simple test\n");
printf("[2] adjacent test\n");
printf("[3] environment test (no dubugging)\n");
printf("[4] integer overflow test\n");
printf("option> ");
$option = <STDIN> ; chop($option);
if ($option <= 0 || $option >= 5) { die "Invalid option\n" }
switch($option) {
case "1" { printf("Command arguments? [y/N]:\n");
printf("option> ");
$execargs = <STDIN> ; chop($execargs);
if ("$execargs" eq "y") {&cmdarg}
}
$gdb = new Devel::GDB (-file => $bugfile ) ;
$debugeip = $gdb -> get ( "i r eip" );
if($status != $sigsegv) {exit(1)}
if($debugeip =~ /0x42424242/) {
printf("\n[!] Status at $ret bytes:\n\n");
}
$buff .= "\x42\x42\x42\x42";
$firstsigsegv = (length($buff) - 4);
$gdb -> get ( "r $CMD $buff" );
$debugeip = $gdb -> get ( "i r eip" );
if($debugeip !~ /0x42424242/) {
printf("\$eip wasn`t overwritten.");
printf("\n[!] Status at $ret bytes:\n\n");
printf("$debugeip\n");
printf("Shall i use brute force to get correct addresses? [n/Y]:\n");
printf("option> ");
$debugeipinput = <STDIN> ; chop($debugeipinput);
if("$debugeipinput" ne "n") {
printf("Max bytes number to increase on buffer [20]:\n");
printf("option> ");
$debugeipcounterlmt = <STDIN> ; chop($debugeipcounterlmt);
if(!$debugeipcounterlmt) {$counterlmt = 20} else {$counterlmt = $debugeipcounterlmt}
while($debugeipcounter <= $counterlmt) {
$buff .= "\x42";
$gdb -> get ( "r $CMD $buff" );
$debugeip = $gdb -> get ( "i r eip" );
$ret++;
$debugeipcounter++;
$debugeip !~ /0x42424242/ or last ;
}
}
printf("\n[!] Status at $ret bytes:\n\n");
}
$output = $gdb -> get ( "i r esp ebp esi edi eip" );
printf("$output\n");
}
case "2" {
if($status == $sigsegv) {printf("Debug? [n/Y]:\n"); printf("> ");
$debug = <STDIN> ; chop($debug);
if("$debug" eq "n") {exit(0)}}
$gdb = new Devel::GDB (-file => $bugfile ) ;
$debugeip = $gdb -> get ( "i r eip" );
if($status != $sigsegv) {exit(1)}
if($debugeip =~ /0x42424242/) {
printf("\n[!] Status at $ret bytes:\n\n");
}
$buff .= "\x42\x42\x42\x42";
$firstsigsegv = (length($buff) - 4);
$gdb -> get ( "r $CMD $adjstring $buff" );
$debugeip = $gdb -> get ( "i r eip" );
if($debugeip !~ /0x42424242/) {
printf("\$eip wasn`t overwritten.");
printf("\n[!] Status at $ret bytes:\n\n");
printf("$debugeip\n");
printf("Shall i use brute force to get correct address? [n/Y]:\n");
printf("option> ");
$debugeipinput = <STDIN> ; chop($debugeipinput);
if("$debugeipinput" ne "n") {
printf("Max bytes number to increase on buffer [20]:\n");
printf("option> ");
$debugeipcounterlmt = <STDIN> ; chop($debugeipcounterlmt);
if(!$debugeipcounterlmt) {$counterlmt = 19} else {$counterlmt = $debugeipcounterlmt}
while($debugeipcounter <= $counterlmt) {
$buff .= "\x42";
$gdb -> get ( "r $CMD $adjstring $buff" );
$debugeip = $gdb -> get ( "i r eip" );
$ret++;
$debugeipcounter++;
$debugeip !~ /0x42424242/ or last ;
}
}
printf("\n[!] Status at $ret bytes:\n\n");
}
$output = $gdb -> get ( "i r esp ebp esi edi eip" );
printf("$output\n");
}
case "3" {
printf("Warning: Gdb calling does not support env-method untill now.\n");
if ($status == $sigsegv) {
printf("With $ret bytes maybe is possible to control \$eip register.\n")
}
}