# --------------------------------------------------------------------------
# Main Program
# --------------------------------------------------------------------------
print "\nNTScan - NT scanning and enumeration script\n";
print "Written by Stuart McClure for Windows NT only.\n";
print "Sept. 19, 1999\n\n";
print "Copyright by Stuart McClure, Sept. 1999\n\n";
print "This program is written AS-IS and will not be supported.\n";
print "In addition, the author is not responsible for the program's
misuse.\n\n";
print "Look for updates at http://www.hackingexposed.com and send comments
to:\n\n";
print "\tstu\@hackingexposed.com.\n\n";
print "WARNING: the programs used in this script are run without explicit
paths.\n";
print " This means that it will search your path to run a particular\n";
print " program (i.e. netdom). This also means that if a trojan
of the same\n";
print " name has already been planted on your system that it
will run it instead.\n";
print " Your best solution to this is to modify NTSCAN and hardcode\n";
print " your program's paths.\n";
print " WE ARE NOT RESPONSIBLE FOR ANY DAMAGE RESULTING FROM
THIS SCRIPT.\n\n";
initialize();
parms();
create_menu_head();
run_core();
create_menu_tail();
print "Scan completed.\n";
print "Point your browser to the \"scanresults.html\" file for the
results.\n";
# --------------------------------------------------------------------------
# Initialize() resets up the variables for the program.
# --------------------------------------------------------------------------
sub initialize {
$rvar = 0;
$tvar = 0;
$dvar = 0;
$fvar = 0;
$pvar = 0;
$divar = 0;
$evar = 0;
$cavar = 0;
$help = 0;
$nvar = 0;
$foundit = 0;
}
# --------------------------------------------------------------------------
# Syntax() displays the proper syntax for the program.
# --------------------------------------------------------------------------
sub syntax {
print " ------------------------------------------------------------------------------\n";
print " All of the host range options below are mutually
exclusive.\n";
print " ------------------------------------------------------------------------------\n";
print " -i 192.168.10.3 Specify
a single IP or range of addresses.\n";
print " -f <hosts.txt>
Read the hosts from a file.\n";
print " -d <domains.txt> Read the
domains from a file.\n";
print "
-s domain Enumerates a single domain.\n";
print "
-w Enumerates all domains on the wire.\n\n";
print " ------------------------------------------------------------------------------\n";
print " The remaining options are not.\n";
print " ------------------------------------------------------------------------------\n";
print " -p ports.txt
Read the ports to be scanned from a file (banners too).\n";
print "
-snmp Pull SNMP information (or at least try to).\n";
print "
-n Do not determine if system is up (no pinging).\n";
print "
-r Randomize the systems scanned.\n";
print "
-v Verbose messages.\n";
print "
-h Help.\n\n";
print " In addition to the standard NetBios and TCP\/IP utilities
on Windows NT,\n";
print " you'll also need the following NTRK and external programs
to fully utilize \n";
print " the script:\n\n";
print " netcat, snmputil, epdump, getmac, netviewx,
local, global\n";
print " user2sid, sid2user, netdom, dumpacl. \n\n";
print " Check out \"Hacking Exposed\" for references to the above
utilities.\n\n";
print " Some examples...\n";
print " To scan all the domains on the wire:\n";
print " ntscan.pl -w \n";
print "\n";
print " To scan a range of IP's, randomize them,
and scan certain ports verbosely:\n";
print " ntscan.pl -i 172.29.11.100-200
-r -p ports.txt -v\n";
print "\n";
exit(1);
}
# --------------------------------------------------------------------------
# Parms() function parses the command line and sets variables
# and runs the necessary commands to setup the program.
# --------------------------------------------------------------------------
sub parms {
if ($#ARGV < 0) {
syntax();
}
@parmar = @ARGV;
# Loop through the flags until exhausted.
while (@parmar) {
$arg = shift(@parmar);
if ($arg eq "-i") {
# IP address range.
if (($dvar == 1) || ($fvar == 1) || ($svar == 1)) {
print "Error: -i and -f are mutally exclusive.\n\n";
syntax();
}
$rrange = shift(@parmar);
if (!($rrange)) {
syntax();
}
if ($rrange=~/-/) {
@tmp = split/-/, $rrange;
if (!($tmp[1])) {
syntax();
}
}
} elsif ($arg eq "-v") { # Verbose output
$vvar = 1;
} elsif ($arg eq "-r") { # Randomize
the IP array
$rvar = 1;
} elsif ($arg eq "-h") { # Help
syntax();
} elsif ($arg eq "-n") { # No pinging
$nvar = 1;
} elsif ($arg eq "-w") { # Enumerate
domains on the wire.
$wvar = 1;
} elsif ($arg eq "-d") { # Read domains
from a file.
if (($ivar == 1) || ($fvar == 1) || ($svar
== 1)) {
print "Error: -i, -f, and -d are mutually
exclusive.\n";
syntax();
}
$dvar = 1;
$domfile = shift(@parmar);
if (!($domfile)) {
syntax();
}
if ($domfile=~/-/) {
syntax();
}
open (DOMFILE, "<$domfile") or die "Cannot
open domain file: $domfile\n";
close DOMFILE;
} elsif ($arg eq "-f") { # Read hosts
from a file.
if (($dvar == 1) || ($ivar == 1) || ($svar
== 1)) {
print "Error: -i and -f are mutally
exclusive.\n\n";
syntax();
}
$fvar = 1;
$hostfile = shift(@parmar);
if (!($hostfile)) {
syntax();
}
if ($hostfile=~/-/) {
syntax();
}
open (HOSTFILE, "<$hostfile") or die "Cannot
open host file: $hostfile\n";
close HOSTFILE;
} elsif ($arg eq "-s") { # Scan single
domain.
if (($dvar == 1) || ($ivar == 1) || ($fvar
== 1)) {
print "Error: -i, -f, -d, and -s are
mutally exclusive.\n\n";
syntax();
}
$svar = 1;
$domain = shift(@parmar);
if (!($domain)) {
syntax();
}
if ($domain=~/-/) {
syntax();
}
} elsif ($arg eq "-p") { # Port scan.
$pvar = 1;
$portfile = shift(@parmar);
if (!($portfile)) {
syntax();
}
if ($portfile=~/-/) {
syntax();
}
open (PORTFILE, "<$portfile") or die "Cannot
open ports file: $portfile";
while($ports=<PORTFILE>) {
chomp($ports);
if (!(($ports=~/#/) || ($ports eq "")))
{
push(@portsa, $ports);
}
}
close PORTFILE;
} elsif ($arg eq "-snmp") {
$snmpvar = 1;
} else {
print "One too many illegal parameters.\n\n";
syntax();
}
}
if ($dvar == 1) {
open (DOMFILE, "<$domfile");
while ($file=<DOMFILE>) {
chomp($file);
if (!(($file=~/#/) || ($file eq ""))) {
push (@dom1, $file);
}
}
close DOMFILE;
get_hosts_in_domains();
} elsif ($svar == 1) {
$domain = uc($domain);
chomp($domain);
if ($vvar == 1) { print "Scanning $domain
domain.\n"; }
open (DOM2, "netviewx -D $domain -On 2>&1
|");
while ($host=<DOM2>) {
chomp($host);
print "\tFound $host.\n";
push (@nbthosts, $host);
}
res_nbt_name();
close DOM2;
} elsif ($wvar == 1) {
run_wire();
} else {
build_hosts($rrange);
}
}
# --------------------------------------------------------------------------
# Run_wire() runs the functions necessary to enumerate domains and
then
# build the hosts file.
# --------------------------------------------------------------------------
sub run_wire {
get_domains();
get_hosts_in_domains();
print "\n";
}
# --------------------------------------------------------------------------
# Logit() logs everything it does. The output is to a file and is the
same
# as when you run NTScan in verbose mode (-v)
# --------------------------------------------------------------------------
sub logit {
$var = $_[0];
open(LOG, ">>$ARGV[2]\/$ARGV[2].log");
print LOG $var;
close LOG;
}
# --------------------------------------------------------------------------
# Build_hosts() reads the hosts or host ranges from a file into an
array.
# --------------------------------------------------------------------------
sub build_hosts {
$tmp = $_[0];
if ($vvar == 1) { print "Building hosts...\n"; }
if ($fvar == 1) {
open (HOSTFILE, "<$hostfile");
while ($test=<HOSTFILE>) {
chomp($test);
doit($test);
}
close HOSTFILE;
} else {
doit($tmp);
}
}
# --------------------------------------------------------------------------
# Check_end() is called by doit() to create the hosts array.
# --------------------------------------------------------------------------
sub check_end {
if (($a1==$a2) && ($b1==$b2) && ($c1==$c2))
{
$dend=$d2;
} else {
$dend=255;
}
if (($a1==$a2) && ($b1==$b2)) {
$cend=$c2;
} else {
$cend=255;
}
if ($a1==$a2) {
$bend=$b2;
} else {
$bend=255;
}
}
# --------------------------------------------------------------------------
# Class_c() returns the class of IP address for the purposes of directory
# structure.
# --------------------------------------------------------------------------
sub class_c {
my $tmp = $_[0];
@me = split/\./, $tmp;
my $dir = "$me[0].$me[1].$me[2]";
if (!(-e "$dir")) {
if ($vvar == 1) { print "Making directory: $dir\n"; }
system("mkdir $dir");
}
return("$dir");
}
# --------------------------------------------------------------------------
# Doit() builds the IP addresses from the command line or file and
# updates an array.
# --------------------------------------------------------------------------
sub doit {
$line = $_[0];
if ($line!=/#/) {
if ($line=~/-/) {
@tmp = split/-/, $line;
@bip = split/\./, $tmp[0];
@eip = split/\./, $tmp[1];
} else {
@bip = split/\./, $line;
@eip = split/\./, $line;
}
$a1 = $bip[0];
$b1 = $bip[1];
$c1 = $bip[2];
$d1 = $bip[3];
$num = @eip;
if ($num==1) {
$a2 = $bip[0];
$b2 = $bip[1];
$c2 = $bip[2];
$d2 = $eip[0];
} elsif ($num==2) {
$a2 = $bip[0];
$b2 = $bip[1];
$c2 = $eip[0];
$d2 = $eip[1];
} elsif ($num==3) {
$a2 = $bip[0];
$b2 = $eip[0];
$c2 = $eip[1];
$d2 = $eip[2];
} elsif ($num==4) {
$a2 = $eip[0];
$b2 = $eip[1];
$c2 = $eip[2];
$d2 = $eip[3];
}
# Based on the IP subnet (Class A, B, C) set the
# correct variables.
check_end();
$aend=$a2;
# Create the array.
while ($a1 <= $aend) {
while ($b1 <= $bend) {
while ($c1 <= $cend) {
while ($d1 <= $dend) {
push (@hosts, "$a1.$b1.$c1.$d1");
$d1+=1;
check_end();
}
$c1+=1;
$d1=0;
}
$b1+=1;
$c1=0;
}
$a1+=1;
$b1=0;
}
}
}
# --------------------------------------------------------------------------
# shuffle_array() is the Fisher Yates shuffle which randomizes an array
# inline - very cool.
# --------------------------------------------------------------------------
sub shuffle_array {
my $hosts = shift;
my $i;
for ($i = @$hosts; --$i; ) {
my $j = int rand ($i+1);
next if $i == $j;
@$hosts[$i,$j] = @$hosts[$j,$i];
}
}
# --------------------------------------------------------------------------
# Run_core() runs the main scanning engine, calling the various functions.
# --------------------------------------------------------------------------
sub run_core {
if ($vvar == 1) {
print "\nRunning core engine...\n";
}
@backup = @hosts;
if ($rvar == 1) {
shuffle_array ( \@hosts );
}
foreach $target (@hosts) {
if ($nvar == 0) { # If pinging
is on, then ping.
ping_host($target);
} else {
# Otherwise, assume it is up and continue.
$up = 1;
}
if ($up == 1) {
write_html_head($target);
check_for_nt($target);
if ($pvar == 1) {
portscan($target);
}
}
if ($wnt == 1) {
if ($snmpvar == 1) { # Run SNMP checks.
get_snmp($target);
}
$dir = class_c($target);
open(OUTFILE, ">>scanresults.html");
print OUTFILE "<A HREF=\"$dir\\$target.html\">$target<\/A><BR>";
close OUTFILE;
get_nbtstat($target);
if ((set_netuse($target))==1) {
get_local_administrators($target);
get_orig_admin($target);
if ($restrictanon == 1) {
# RestrictAnonymous key set.
get_allusers($target);
} else {
get_global_admins($target);
get_users($target);
get_groups($target);
get_shares($target);
get_allshares($target);
}
get_mac($target);
get_netdom($target);
get_epdump($target);
del_netuse($target);
}
# reinitialize used variables.
$up = 0;
$wnt = 0;
}
}
write_html_tail($target);
}
sub portscan {
my $target = $_[0];
if ($vvar == 1) {
print "Port scanning $target.\n";
}
$dir = class_c($target);
open (OUTFILE, ">>$dir\\$target.html");
print OUTFILE "<H2>PORT information for $target<BR>";
print OUTFILE "--------------------------------------------</H2>";
foreach $item (@portsa) {
chomp($item);
local $/;
open(SCAN, "nc -vzn -w 2 $target $item 2>&1 |");
# Port open
$result = <SCAN>;
if ($result=~/open/) {
if ($vvar == 1) {
print "\tPort $item on $target found open.\n";
}
print OUTFILE "$item open<BR>";
if (($item eq "80") || ($item eq "81") || ($item eq "8000"))
{
open (HTTP, ">http.tmp");
print HTTP "HEAD / HTTP/1.0\n\n";
close HTTP;
open(SCAN2, "type http.tmp | nc -nvv -w 2 $target
$item 2>&1 |"); # Banners
$result2 = <SCAN2>;
if ($result2) {
if ($result2=~/Microsoft-IIS/) {
$msyes = 1;
}
$result2=~s/\n/<BR>/g;
print OUTFILE "$result2";
}
print OUTFILE "<h3>MDAC results</h3>";
open (HTTP, ">http.tmp");
print HTTP "GET /msadc/msadcs.dll HTTP/1.0\n\n";
close HTTP;
open(SCAN2, "type http.tmp | nc -nvv -w 2 $target
$item 2>&1 |"); # Banners
$result2 = <SCAN2>;
if ($result2) {
if (($msyes == 1) && ($result2=~/x-varg/))
{
print OUTFILE "The system IS vulnerable
to MDAC attack.<BR><BR>";
}
$result2=~s/\n/<BR>/g;
print OUTFILE "$result2";
}
}
}
close SCAN;
} # foreach
close OUTFILE;
}
# --------------------------------------------------------------------------
# Check_for_nt() port scans a system for port 135 and 139,
# --------------------------------------------------------------------------
sub check_for_nt {
my ($host) = @_;
if ($vvar == 1) { print "Checking for a Windows NT system...";
}
local $/;
open(SCAN1, "nc -vzn -w 1 $host 135 2>&1 |");
$result1 = <SCAN1>;
open(SCAN2, "nc -vzn -w 1 $host 139 2>&1 |");
$result2 = <SCAN2>;
if (($result1=~/open/) && ($result2=~/open/)) {
$wnt = 1;
print "NT found.\n";
} elsif ($result2=~/open/) {
if ($vvar == 1) {
print "\n$host: 95/98 or Unix samba client - dumping
shares and then skipping.\n";
}
# Windows 95 system? Record it and try a one thing.
get_shares($host);
print "\n";
$dir = class_c($host);
open(OUTFILE, ">>scanresults.html");
print OUTFILE "<A HREF=\"$dir\\$host.html\">$host<\/A><BR>";
close OUTFILE;
} else {
if ($vvar == 1) { print "\nNeither 95 or NT - skipping $host.\n\n";
}
return;
}
}
# --------------------------------------------------------------------------
# Ping_host() pings a host and if it is up sets a variable.
# --------------------------------------------------------------------------
sub ping_host {
my ($host) = @_;
if ($vvar == 1) { print "Pinging host $host.\n"; }
local $/;
open (PING, "ping -n 2 $host 2>&1 |");
$ping = <PING>;
if ($ping=~/Reply from/) {
if (!($ping=~/unreachable/)) {
$up = 1;
if ($vvar == 1) { print "Host $host is alive!\n"; }
}
} else {
$up = 0;
if ($vvar == 1) {
print "Host is dead - skipping $host.\n\n";
}
}
}
# --------------------------------------------------------------------------
# Get_domains() pulls the domains off the wire and puts them into an
array..
# --------------------------------------------------------------------------
sub get_domains {
if ($vvar == 1) { print "Retrieving domains...\n"; }
open (DOM1, "net view /domain 2>&1 |");
while ($dom1=<DOM1>) {
if (!($dom1=~/---|Domain|successfully./)) {
if ($dom1=~tr/ / /s) {
chomp($dom1);
chop($dom1);
if ($vvar == 1) { print "\tFound $dom1 domain\n";
}
push (@dom1, $dom1);
}
}
}
close DOM1;
}
# --------------------------------------------------------------------------
# Get_hosts_in_domains() enumerates the hosts from get_domains() and
# builds an array.
# --------------------------------------------------------------------------
sub get_hosts_in_domains {
if ($vvar == 1) { print "Retrieving hosts from domains...\n";
}
foreach $domitem (@dom1) {
$domitem = uc($domitem);
chomp($domitem);
if ($vvar == 1) { print "Scanning $domitem domain.\n";
}
open (DOM2, "netviewx -D $domitem -On 2>&1 |");
while ($tmp=<DOM2>) {
chomp($tmp);
print "\tFound $tmp.\n";
push (@nbthosts, $tmp);
}
}
res_nbt_name();
close DOM2;
}
# --------------------------------------------------------------------------
# Res_nbt_name() resolves a netbios name by using the ping -a option.
# --------------------------------------------------------------------------
sub res_nbt_name {
foreach $item (@nbthosts) {
if ($vvar == 1) { print "Resolving Netbios host: $item"; }
open (PING, "ping -n 1 -a $item 2>&1 |");
while ($ping=<PING>) {
if ($ping=~/Reply from/) {
@ping = split/ /, $ping;
$hostip = $ping[2];
chop $hostip;
print " - Resolved to $hostip.\n";
push (@hosts, $hostip);
}
}
close PING;
}
return;
}
# --------------------------------------------------------------------------
# Set_netuse() creates a null session using "net use".
# --------------------------------------------------------------------------
sub set_netuse {
my ($host) = @_;
if ($vvar == 1) { print "Establishing null session.\n"; }
open (NETUSE, "net use \\\\$host\\ipc\$ \"\" /u:\"\" 2>&1
|");
$netuse = <NETUSE>;
if ($netuse=~/successfully./) {
if ($vvar == 1) {
print "Initial IPC successful to $host...\n";
}
} else {
if ($vvar == 1) {
print "Initial IPC unsuccessful to $host...Exiting.\n\n";
}
return(0);
# Without IPC you can still get nbtstat, getusers?,
epdump, whoisadm.
}
close NETUSE;
}
# --------------------------------------------------------------------------
# Del_netuse() delete the null session.
# --------------------------------------------------------------------------
sub del_netuse {
my ($host) = @_;
local $/;
open (NETDEL, "net use \\\\$host\\ipc\$ \/del 2>&1 |");
$netdel = <NETDEL>;
if ($netdel=~/successfully./) {
if ($vvar == 1) { print "Removing IPC successful to $host...\n";
}
}
close NETDEL;
}
# --------------------------------------------------------------------------
# Get_nbtstat() runs nbtstat() and directs output to a file.
# --------------------------------------------------------------------------
sub get_nbtstat {
my ($host) = @_;
if ($vvar == 1) { print "Retrieving NetBIOS information for $host\n";
}
$dir = class_c($target);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>NBTSTAT information for $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
open (NBT, "nbtstat -A $host 2>&1 |");
while ($nbt=<NBT>) {
if ($nbt=~/<|MAC/) {
$nbt=~s/\n/<BR>/g;
print OUTFILE $nbt;
}
}
print OUTFILE "<BR>";
close OUTFILE;
close NBT;
}
# --------------------------------------------------------------------------
# Get_local_administrators() uses the NTRK "local" command to enumerate
# the local administrators on the box.
# --------------------------------------------------------------------------
sub get_local_administrators {
my ($host) = @_;
if ($vvar == 1) { print "Retrieving LOCAL ADMINISTRATORS for
$host\n"; }
local $/;
open (LOCAL, "local Administrators \\\\$host 2>&1 |");
$local=<LOCAL>;
if ($local=~/Error/) {
} elsif ($local=~/Access Denied/) {
$restrictanon = 1;
} else {
@tmp = split/\n/, $local;
foreach $item (@tmp) {
if (!($item=~/Domain Admins/)) {
$dir = class_c($host);
open (OUTFILE2, ">>$dir\\$host.admins.txt");
print OUTFILE2 "$item\n";
close OUTFILE2;
chomp ($item);
push (@admins, $item);
}
}
$dir = class_c($host);
$local =~ s/\n/<BR>/g;
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>Local Administrators
on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
print OUTFILE "<A HREF=\"$host.admins.txt\">ADMINS
file<\/A><BR><BR>";
print OUTFILE "$local<BR>";
close OUTFILE;
}
close LOCAL;
}
# --------------------------------------------------------------------------
# Get_orig_admin() pulls the original administrator using user2sid/sid2user
# in the case where they renamed it.
# --------------------------------------------------------------------------
sub get_orig_admin {
my ($host) = @_;
if ($vvar == 1) { print "Retrieving ORIGINAL ADMINISTRATOR for
$host\n"; }
$dir = class_c($target);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>ORIGINAL ADMIN information on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
open (USER2SID, "user2sid \\\\$host Guest 2>&1 |");
while ($user2sid=<USER2SID>) {
if ($user2sid=~/S-1-5-/) {
chomp $user2sid;
$sidtmp = $user2sid;
@sid = split/\-/, $sidtmp;
open (SID2USER, "sid2user \\\\$host $sid[2] $sid[3] $sid[4]
$sid[5] $sid[6] 500 2>&1 |");
while ($sid2user=<SID2USER>) {
if ($sid2user=~/Name is/) {
@sid2tmp = split/ /, $sid2user;
if (!($sid2tmp[2] eq "Domain")) {
if ($restrictanon == 1) {
print OUTFILE "<A HREF=\"$host.admins.txt\">ADMINS
file.<\/A><BR><BR>";
$dir = class_c($host);
open (OUTFILE2, ">>$dir\\$host.admins.txt");
print OUTFILE2 "$sid2tmp[2]\n";
close OUTFILE2;
chomp ($sid2tmp[2]);
push (@admins, $item);
} else {
print OUTFILE "$sid2tmp[2]<BR>";
}
}
}
}
$i+=1;
}
close SID2USER;
}
print OUTFILE "<BR>";
close USER2SID;
close OUTFILE;
}
# --------------------------------------------------------------------------
# Get_global_admins() uses the NTRK "global" command to retrieve the
# members of the "Domain Admins" group from an NT machine.
# --------------------------------------------------------------------------
sub get_global_admins {
my ($host) = @_;
if ($vvar == 1) { print "Retrieving GLOBAL ADMINISTRATORS for
$host\n"; }
local $/;
open (GLOBAL, "global \"Domain Admins\" \\\\$host 2>&1 |");
$global = <GLOBAL>;
if (!($global=~/group not found/)) {
$global=~s/\n/<BR>/g;
$dir = class_c($target);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>Global Administrators on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
print OUTFILE "$global<BR>";
}
close GLOBAL;
close OUTFILE;
}
# --------------------------------------------------------------------------
# Get_mac() uses the NTRK "getmac" command to retrieve the MAC information
# from an NT machine.
# --------------------------------------------------------------------------
sub get_mac {
my ($host) = @_;
if ($vvar == 1) { print "Retrieving MAC information for $host\n";
}
local $/;
open (GETMAC, "getmac \\\\$host 2>&1 |");
$getmac = <GETMAC>;
if ($getmac) {
$getmac=~s/\n//;
$getmac=~s/\n/<BR>/g;
$dir = class_c($target);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>MAC information on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
print OUTFILE "$getmac";
}
close GETMAC;
close OUTFILE;
}
# --------------------------------------------------------------------------
# Get_netdom() uses "netdom" to retrieve more information from an NT
# box.
# --------------------------------------------------------------------------
sub get_netdom {
my ($host) = @_;
if ($vvar == 1) { print "Retrieving NETDOM information for $host\n";
}
local $/;
open (NETDOM, "netdom query \\\\$host 2>&1 |");
$netdom = <NETDOM>;
if ($netdom) {
$netdom=~s/\n/<BR>/g;
$dir = class_c($target);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>NETDOM information on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
print OUTFILE "$netdom<BR>";
}
close NETDOM;
close OUTFILE;
}
# --------------------------------------------------------------------------
# Get_users() uses "dumpacl" to retrieve user information from an NT
box.
# --------------------------------------------------------------------------
sub get_users {
my ($host) = @_;
@realusers = "";
@userarray = "";
@bdown = "";
if ($vvar == 1) { print "Retrieving USERS for $host\n"; }
$dir = class_c($host);
open (GETUSERS, "dumpacl \/computer=\\\\$host \/rpt=users \/saveas=csv
\/outfile=$dir\\$host.users.tmp 2>&1 |");
close GETUSERS;
open (FILE, "<$dir\\$host.users.tmp") or print "Cannot open
$dir\\$host.users.tmp\n";
while ($getusers=<FILE>) {
chomp $getusers;
if (!(($getusers=~/Somarsoft DumpAcl/) || ($getusers=~/UserName/)
|| ($getusers=~/rc\=6/) || ($getusers=~/rc\=5/))) {
@getusers = split/,/, $getusers;
if (!($getusers eq "")) {
push (@userarray, "$getusers[0]\t$getusers[1]\t$getusers[3]\t$getusers[10]\t$getusers[12]\t$getusers[14]\t$getusers[15]\t$getusers[16]\t$getusers[17]");
}
}
}
if (@userarray) {
$dir = class_c($host);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>GETUSERS information on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
print OUTFILE "<A HREF=\"$host.users.txt\">USERS file<\/A><BR><BR>";
foreach $item (@userarray) {
if ($item) {
@bdown = split/\t/, $item;
}
$foundit = 0;
foreach $me (@admins) {
# Check if the user is an administrator.
if ($me eq $bdown[0]) {
# If yes, then tag it.
$foundit = 1;
}
}
if ($foundit == 0) {
push (@realusers, $bdown[0]);
}
}
foreach $user (@realusers) {
if ($user) {
print OUTFILE "$user<BR>";
}
}
foreach $item (@userarray) {
if ($item) {
@bdown = split/\t/, $item;
}
print OUTFILE "<H4>Username:\t\t$bdown[0]</H4>";
# Username
print OUTFILE "Fullname:\t\t$bdown[1]<BR>";
# Fullname
print OUTFILE "Comment:\t\t$bdown[2]<BR>";
# Comment
print OUTFILE "PasswordLastSet:\t$bdown[3]<BR>";
# Password Last Set time
print OUTFILE "PasswordExpires:\t$bdown[4]<BR>";
# Password expires
print OUTFILE "AccountDisabled:\t$bdown[5]<BR>";
# Account Disabled
print OUTFILE "AccountLockedOut:\t$bdown[6]<BR>"; #
Account locked out
print OUTFILE "AccountExpires:\t$bdown[7]<BR>"; # Account
expires time
print OUTFILE "LastLogon:\t$bdown[8]<BR><BR>"; #
Last logon time
}
print OUTFILE "<BR>";
close FILE;
close OUTFILE;
open (USRFILE, ">>$dir\\$host.users.txt");
foreach $user (@realusers) {
if ($user) {
print USRFILE "$user\n";
}
}
close USRFILE;
}
unlink("$dir\\$host.users.tmp");
}
# --------------------------------------------------------------------------
# Get_allusers() uses "user2sid" and "sid2user" to retrieve all users
# from an NT box.
# --------------------------------------------------------------------------
sub get_allusers {
my ($host) = @_;
if ($vvar == 1) { print "RestrictAnonymous: retrieving GETALLUSERS
information for $host\n"; }
$dir = class_c($host);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>GETALLUSERS information on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
print OUTFILE "<A HREF=\"$host.users.txt\">USERS file.<\/A><BR><BR>";
open (USER2SID, "user2sid \\\\$host Guest 2>&1 |");
while ($user2sid=<USER2SID>) {
if ($user2sid=~/S-1-5-/) {
chomp $user2sid;
$sidtmp = $user2sid;
@sid = split/\-/, $sidtmp;
$i = 1000;
while ($i < 1500) {
local $/;
open (SID2USER, "sid2user \\\\$host $sid[2] $sid[3]
$sid[4] $sid[5] $sid[6] $i 2>&1 |");
$sid2user=<SID2USER>;
if ($sid2user=~/SidTypeUser/) {
@sidstuff = split/\n/, $sid2user;
foreach $item (@sidstuff) {
if ($item=~/Name is/) {
@sid2tmp = split/ /, $item;
if (!($sid2tmp[2] eq "Domain"))
{
chomp $sid2tmp[2];
push (@alluser, $sid2tmp[2]);
}
}
}
}
$i+=1;
}
close SID2USER;
}
}
close USER2SID;
foreach $item (@alluser) {
foreach $me (@admins) {
# Check if the user is an administrator.
if ($me eq $item) {
# If yes, then tag it.
$foundit = 1;
}
}
if ($foundit == 0) {
push (@realusers, $item);
}
$foundit = 0;
}
open (USRFILE, ">>$dir\\$host.users.txt");
foreach $user (@realusers) {
print OUTFILE "$user<BR>";
print USRFILE "$user\n";
}
print OUTFILE "<BR>";
close OUTFILE;
close USRFILE;
}
# --------------------------------------------------------------------------
# Get_groups() uses "dumpacl" to retrieve group information from an
NT box.
# --------------------------------------------------------------------------
sub get_groups {
my ($host) = @_;
if ($vvar == 1) { print "Retrieving GROUPS for $host\n"; }
$dir = class_c($host);
open (GETGROUPS, "dumpacl \/computer=\\\\$host \/rpt=groups \/saveas=csv
\/outfile=$dir\\$host.groups.tmp 2>&1 |");
close GETGROUPS;
open (FILE, "<$dir\\$host.groups.tmp") or print "Cannot open
$dir\\$host.groups.tmp\n";
while ($getgroups=<FILE>) {
chomp $getgroups;
if (!(($getgroups=~/Somarsoft DumpAcl/) || ($getgroups=~/Group,Comment/)
|| ($getgroups=~/rc=5/))) {
@getgroup = split/,/, $getgroups;
if (!($getgroups eq "")) {
push (@groupsarray, "$getgroup[0]\t$getgroup[1]\t$getgroup[2]\t$getgroup[3]\t$getgroup[4]");
}
}
}
if (@groupsarray) {
$dir = class_c($host);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>GETGROUPS information on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
foreach $item (@groupsarray) {
if ($item) {
@bdown = split/\t/, $item;
}
print OUTFILE "<H4>Group:\t\t$bdown[0]</H4>";
# Group
print OUTFILE "Comment:\t\t$bdown[1]<BR>"; #
Comment
print OUTFILE "GroupType:\t\t$bdown[2]<BR>";
# GroupType
print OUTFILE "GroupMember:\t$bdown[3]<BR>";
# GroupMember
print OUTFILE "MemberType:\t$bdown[4]<BR><BR>";
# MemberType
}
print OUTFILE "<BR>";
close FILE;
close OUTFILE;
}
unlink("$dir\\$host.groups.tmp");
}
# --------------------------------------------------------------------------
# Get_epdump() uses "epdump" to retrieve user information from an NT
box.
# --------------------------------------------------------------------------
sub get_epdump {
my ($host) = @_;
if ($vvar == 1) { print "Retrieving EPDUMP information for $host\n";
}
local $/;
open (EPDUMP, "epdump $host 2>&1 |");
$epdump = <EPDUMP>;
if ($epdump) {
$dir = class_c($target);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>EPDUMP information on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
print OUTFILE "$epdump<BR>";
}
close EPDUMP;
close OUTFILE;
}
# --------------------------------------------------------------------------
# Get_shares() uses "net view" to retrieve share information from an
NT
# or 9x box.
# --------------------------------------------------------------------------
sub get_shares {
my $host = $_[0];
if ($vvar == 1) { print "Retrieving SHARES on $host\n"; }
$dir = class_c($host);
open (GETSHARES, "net view \\\\$host 2>&1 |");
$getshares=<GETSHARES>;
close GETSHARES;
if (!(($getshares=~/\n/) || ($getshares=~/ /))) {
@shares = split/\n/, $getshares;
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>GETSHARES information on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
$go = 0;
foreach $item (@shares) {
if ($go == 1) {
if (!(($item eq "\n") || ($item=~/The command/)
|| ($item eq ""))) {
print OUTFILE "$item<BR>";
}
}
if ($item=~/------/) {
$go = 1;
}
}
print OUTFILE "<BR>";
close OUTFILE;
}
}
# --------------------------------------------------------------------------
# Get_allshares() uses "dumpacl" to retrieve share information from
an NT
# box.
# --------------------------------------------------------------------------
sub get_allshares {
my ($host) = @_;
if ($vvar == 1) { print "Retrieving ALLSHARES for $host\n"; }
$dir = class_c($host);
open (GETALL, "dumpacl \/computer=\\\\$host \/rpt=shares \/saveas=csv
\/outfile=$dir\\$host.shares.tmp 2>&1 |");
$check=<GETALL>;
close GETALL;
if ($check) {
open (FILE, "<$dir\\$host.shares.tmp");
while ($getall=<FILE>) {
chomp $getall;
if (!(($getall=~/Somarsoft DumpAcl/) || ($getall=~/Share
and path/))) {
@getallshares = split/,/, $getall;
if (!($getall eq "")) {
push (@sharearray, "$getallshares[0]");
}
}
}
$dir = class_c($host);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>GETALLSHARES information on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
print OUTFILE "<A HREF=\"$host.shares.txt\">More SHARES information.<\/A><BR><BR>";
open (SHAREFILE, ">>$dir\\$host.shares.txt");
foreach $item (@sharearray) {
print SHAREFILE "$item\n";
print OUTFILE "$item<BR>";
}
print OUTFILE "<BR>";
close FILE;
close OUTFILE;
close SHAREFILE;
}
unlink("$dir\\$host.shares.tmp");
}
# --------------------------------------------------------------------------
# Get_snmp() uses "snmputil" from the NTRK to retrieve gobs of information
# from an NT box.
# --------------------------------------------------------------------------
sub get_snmp {
my ($host) = @_;
if ($vvar == 1) { print "Retrieving SNMP information for $host\n";
}
local $/;
open (SNMPUTIL, "snmputil walk $host public .1.3.6.1.4.1.77 2>&1
|");
$snmp = <SNMPUTIL>;
if (!($snmp=~/error on SnmpMgrRequest 40/)) {
$dir = class_c($host);
open (SNMPFILE, ">>$dir\\$host.snmp.txt");
print SNMPFILE "SNMP information on $host\n";
print SNMPFILE "--------------------------------------------\n";
print SNMPFILE "$snmp\n";
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<H2>SNMP information on $host<BR>";
print OUTFILE "--------------------------------------------</H2>";
print OUTFILE "<A HREF=\"$host.snmp.txt\">SNMP information
with public community name<\/A><BR><BR>";
}
close SNMPUTIL;
close SNMPFILE;
close OUTFILE;
}
# --------------------------------------------------------------------------
# Write_html_head() writes the requisite HTML header tags to the beginning
# of each results file.
# --------------------------------------------------------------------------
sub write_html_head {
my ($host) = $_[0];
$mydate = localtime;
$dir = class_c($host);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<HTML>";
print OUTFILE "<HEAD>";
print OUTFILE "<TITLE>NTScan results for $host on $mydate<\/TITLE>";
print OUTFILE "<\/HEAD>";
print OUTFILE "<BODY>";
print OUTFILE "<H1>NTScan results for $host on $mydate</H1>";
print OUTFILE "<H4>Written for \"Hacking Exposed\" by Stuart
McClure (July, 1999)</H4><BR>";
close OUTFILE;
}
# --------------------------------------------------------------------------
# Write_html_tail() writes the requisite HTML header tags to the end
# of each results file.
# --------------------------------------------------------------------------
sub write_html_tail {
my ($host) = $_[0];
$dir = class_c($host);
open (OUTFILE, ">>$dir\\$host.html");
print OUTFILE "<\/BODY>";
print OUTFILE "<\/HTML>";
close OUTFILE;
}
# --------------------------------------------------------------------------
# Create_menu() builds the big menu file of all the IP addresses.
# --------------------------------------------------------------------------
sub create_menu_head {
open(OUTFILE, ">>scanresults.html");
$mydate = localtime;
print OUTFILE "<HTML>";
print OUTFILE "<HEAD>";
print OUTFILE "<TITLE>NTScan results on $mydate<\/TITLE>";
print OUTFILE "<\/HEAD>";
print OUTFILE "<BODY>";
print OUTFILE "<H1>NTScan results for $host on $mydate</H1>";
print OUTFILE "<H4>Written for \"Hacking Exposed\" by Stuart
McClure (July, 1999)</H4><BR>";
close OUTFILE;
}
sub create_menu_tail {
open(OUTFILE, ">>scanresults.html");
print OUTFILE "<\/BODY>";
print OUTFILE "<\/HTML>";
close OUTFILE;
}