NMAP
This is a perl script that shows what perl does well. It takes a couple of programs which provide useful output -- nmap and nbtstat -- and combines them into a single daily archive showing what's on your network. Key features are:
- The input is a list of named IP ranges.
- The output is written to hosts.txt and yyyy-mm-dd.hosts.txt automatically building an archive of what's up in the networks you care about.
- Install nmap and make sure it's in the path. nbtstat is part of any Windows installation.
- Install Perl, which means Active State.
- Create a range file that's just a text file with a few lines like these: (Obviously with your network ranges. You can use any range specification that nmap will accept.)
# my range.txt servers 192.168.10.0/24 perimeter 192.168.12.0/24
- Make sure your reverse DNS is working, or you won't get any DNS names.
- Run it with a command like
c:\perl\bin\perl nmap.pl range.txt
- check the output in hosts.txt to see server names, and, for windows servers, domain and server names.
# Start of nmap.pl by umacf24
# This program takes a single parameter -- a file containing pairs.
# Example (but leave off the #)
# servers 192.168.10.0/24
# perimeter 192.168.12.0/24
#
use strict;
use warnings;
# NBTSTAT codes from Jim Halfpenny
my %group = ( hex("00"), "00 Dom",
hex("01"), "01 M Browser",
hex("1C"), "1C Domain Controller",
hex("1E"), "1E S Browser", # Browser Elections
);
my %unique = ( hex("00"), "00 WS", # Workstation service
hex("01"), "01 Msgr", # Messenger Service
hex("03"), "03 Msgr", # Messenger Service
hex("06"), "06 RAS Server Service",
hex("1B"), "1B Domain Master Browser",
hex("1D"), "1D Master Browser",
hex("1F"), "1F NetDDE Service",
hex("20"), "20 SVR", # File Server Service
hex("21"), "21 RAS Client Service",
hex("22"), "22 MS EXC Interchange(MSMail Connector)",
hex("23"), "23 MS EXC Store",
hex("24"), "24 MS EXC Directory",
hex("30"), "30 Modem Sharing Server Service",
hex("31"), "31 Modem Sharing Client Service",
hex("43"), "43 SMS Clients Remote Control",
hex("44"), "44 SMS Administrators Remote Control Tool",
hex("45"), "45 SMS Clients Remote Chat",
hex("46"), "46 SMS Clients Remote Transfer",
hex("4C"), "4C DEC Pathworks TCPIP service on Windows NT",
hex("42"), "42 McAfee AV",
hex("52"), "52 DEC Pathworks TCPIP service on Windows NT",
hex("87"), "87 MS EXC MTA",
hex("6A"), "6A MS EXC IMC",
hex("BE"), "BE Netmon Agent",
hex("BF"), "BF Netmon Application",
);
# results stored in an array for re-use
my @nmapout;
my $ofn='hosts.txt';
my $opath='.\\ip\\';
my $header = "Key\t++ Up but unnamed, \n\t** Named but not responding to ping.\n\t?? Improper NBT names\n";
$header .= "Ping scan run between ".localtime(time())." ";
my $ipall; my $ipup; my $ipdown; # Address counters
# Process the file of network names. Run NMAP against the network spec (iprange).
while (<>)
{
next if (/^\s*#/) ;
my @line = split /\s+/;
if (2==@line)
{
my $ipname = sprintf "%-15.15s ", $line[0]; # Fixed width
my $iprange = $line[1];
my $cmd = ".\\bin\\nmap -sP -R -oG - $iprange |"; # local nmap
print STDERR "$cmd\n";
open (NMAP, $cmd);
while ()
{
chomp;
next if /Smurf/;
if (/^Host: /)
{
$ipall++;
my $hostline=$_;
$ipdown++ if ($hostline =~ /Status: Down$/);
$ipup++ if ($hostline =~ /Status: Up$/);
my $flag =' ';
$flag = '++ ' if ($hostline =~ /\(\)\tStatus: Up/) ;# Un-named
$flag = '** ' if ($hostline =~ /\([^)]+\)\tStatus: Down/) ;# Named, but not responding
my $hostip = $1 if ($hostline =~ /^Host: ([0-9\.]+) .+ Up$/);
my $prefix=$ipname . $flag;
my $postfix=nbtstat($hostip) if ($hostip);
$hostline =~ s/^Host: /$prefix/;
$hostline =~ s/Status: Up$/NBT: $postfix/ if ($postfix);
# print STDERR "Host Line $hostline | $postfix | $hostip\n";
push @nmapout, $hostline;
}
}
}
}
$header .= "and ".localtime(time())."\n";
if ($ipall)
{ # Some addresses seen
$header .= "$ipall addressses pinged:- Up: $ipup, Down: $ipdown\n";
}
else
{
$header .= "No addresses scanned. NMAP in path?\n";
}
# Preserve an archive Version
my ($sec, $min, $hr, $day, $mon, $yr, $wday, $yday, $isdst) = localtime(time());
$yr = $yr + 1900;
$mon = $mon + 1;
my $prefix = sprintf "%04d-%02d-%02d.", $yr, $mon, $day ;
my $afn="$opath$prefix$ofn";
my $hfn="$opath$ofn";
#Don't overwrite existing hosts file until we have finished scanning.
open (AHOSTS, ">$afn") or die "could not open $afn $!";
open (HOSTS, ">$hfn") or die "could not open $hfn $!";
print AHOSTS $header; print HOSTS $header;
foreach my $hostline (@nmapout)
{
print HOSTS "$hostline\n";print AHOSTS "$hostline\n";
}
close HOSTS; close AHOSTS;
sub nbtstat
{
my ($hostip) = @_;
my $cmd = "nbtstat -a $hostip |";
my %survey; my $ret;
my $domain; my $server;
# print STDERR "survey $cmd\n";
open (NBTSTAT, $cmd) or die "can't run $cmd $!";
while ()
{
# print STDERR;
# The meat of the NBTNAME command is in this format: name type
if (/^\s+(\S+)\s*<([0-9A-F]{2})>\s+(GROUP|UNIQUE)/i )
{
my $nbtname = $1;
my $nbtclass = $2;
my $nbttype = $3;
if ('00' eq $nbtclass)
{
$domain = $nbtname if ('GROUP' eq $nbttype);
$server = $nbtname if (('UNIQUE' eq $nbttype) && ($nbtname !~ /(\~)|(MSBROWSE)/));
}
my $desc = ('GROUP' eq $nbttype)? $group{hex($nbtclass)} : $unique{hex($nbtclass)};
$desc = "$nbtclass $nbttype Unknown" unless $desc;
# print STDERR "$nbtname $nbtclass $nbttype $desc \n";
push (@{$survey{$nbtname}}, $desc);
}
}
close NBTSTAT;
# We should have a good domain name and a good server if we have anything
if (%survey)
{
$ret = ($domain and $server) ? "$domain\\$server" : '??';
}
foreach my $nbtname (keys %survey)
{
$ret .= " $nbtname: (" . join (', ', @{$survey{$nbtname}} ). ")" unless ($nbtname =~ /(\~)|(MSBROWSE)/) ;
}
return $ret;
}
# End of nmap.pl
No comments:
Post a Comment