#!/usr/bin/perl5.8.4
# smb-sspg.sara (standalone stealth password guesser) examines specified
# SARA database (-d <database>), collects a list of users associated
# with a machine (target, Netbios Name/Domain, uses rules/smbpasswords
# to guess passwords for found accounts.  smb-sspg uses the -s <time>
# to delay time seconds between passwords for a particular target/user.
#
# This program does not update the database files!
#
# Usage bin/smb-sspg.sara [-R] [-v] -s <time in seconds> -d database directory
#      -R: same as sara
#      -v  same as sara
#      -s  time to wait between guesses for target/user
#      -d  same as sara
#
# Ignores smb_passwords and smb_spasswords_delay in sara.cf)

require 'perllib/getopts.pl';
require 'config/paths.pl';
require 'perl/misc.pl';
require 'perl/status.pl';
&Getopts("d:Rs:v");
$timing = 1 if $opt_R;
if (! $opt_d) {
  print "USAGE $0 [-R] [-v] -s delay (sec) -d database\n\n";
  exit;
}
if (! $opt_s || $opt_s <= -1 || $opt_s >=36000) {
  print "USAGE $0 [-R] [-v] -s delay (sec) -d database\n";
  print "  delay must be greater than 0 and less than 36000\n\n";
  exit;
}

if (! -f "results/$opt_d/facts") {
  print "Database not found in results/$opt_d\n"; 
  exit;
}
if (! -f "rules/smbpasswords") {
  print "rules/smbpasswords file not found\n";
  exit;
}
&delay_sara;
if (! -e $SMBCLIENT) {
  print "Cannot find $SMBCLIENT\n";
  exit;
}
$facts   = "results/$opt_d/facts";
@domains = "";
@names   = "";
@users   = "";
@queries = "";
@pws     = "";
$domain  = 0;
$name    = 0;
$user    = 0;
$query   = 0;
$pw      = 0;
$SMB_TIMEOUT = 4;
$SIG{ALRM} = sub {$dum0 = $dum0};
#
#  Get facts entries with Netbios Name and Netbios Domain
#
open(PWD, "rules/smbpasswords");
while(<PWD>) {
  chomp;
  $pws[$pw++] = $_;
}
  
open(FACTS, "$facts");
while (<FACTS>) {
  chomp;
#print "$_\n";
  ($host, $svc, $dum, $dum, $dum, $dum, $output, $txt) = split(/\|/);
  if ($svc =~ /users/) {
     $users[$user]     =  "$host|$txt";
     $users[$user++]   =~ s/\n//g;
  }
  elsif ($output =~ /Netbios Name/) {
     $names[$name++]     = "$host|$txt";
  } elsif ($output =~ /Netbios Domain/) {
     $domains[$domain++] = "$host|$txt";
  }
}
close(FACTS);
# 
# Correlate
#
for (@names) {
  $queries[$query] = "$_|";
  ($_host,$dum) = split(/\|/);
  for (@domains) {
    ($__host,$_domain) = split(/\|/);
    if ($_host eq $__host) {
      $queries[$query] .= "$_domain|";
      last;
    }
  }
  $users_found = 0;
  for (@users) {
    ($__host,$_users) = split(/\|/);
    if ($_host eq $__host) {
      $queries[$query] .= "$_users";
      $users_found = 1;
      last;
    }
  }
  $queries[$query] .= "Administrator,Guest" if $users_found == 0;;
  $query++;
}
for (@pws) {
alarm $opt_s;
   next if (/^#/);
   $_pw = $_;
   for(@queries) {
     ($_host,$_name, $_domain, $_user) = split(/\|/);
     (@users) = split(/\,/,$_user);
      for (@users) {
      next if (/\&/);
      $_user = $_;
      $passwd = $_pw;
      $passwd =~ s/\%USER/$_user/;
      if ($passwd =~ /\%NETBIOS/) {
        $passwd =~ s/\%NETBIOS/$_name/;
        $passwd = lc($passwd);
      }
     do_delays();
     $guessed_account = 0;
     print "Testing account $_user with password '$passwd'\n" if $opt_v;
     $smb_args = "-a $_user -p '$passwd' -v $_host";
     open (IN, "$TIMEOUT $SMB_TIMEOUT bin/smb.sara $smb_args|");
     while (<IN>) {
       $guessed_account = 1 if(/blocks of size/);;
     }
     close(IN);
     print "@list\n" if $opt_v;
     if ($guessed_account == 1) {
       print "Password Guessed: $_host (\\\\$_domain\\\\$_name) at \"$_user\%$passwd\"\n";
     }
    }
  }
  $t = alarm 0;
  if ($t != 0) {
    print "Sleeping for $t\n";
    sleep $t;
  }
}
  
