Nmap Announce mailing list archives
nwrap -- nmap stealth wrapper (updated)
From: HD Moore <nlog () ings com>
Date: Thu, 15 Apr 1999 20:46:31 -0500
Hi,
This is an update to the original nwrap prototype script I posted
earlier. Nwrap takes a list of addresses and port numbers to scan, adds
each host/port combination to a list and randomly shuffles it. Then it
launches a specified amount of parallel nmap processes until it empties
the list. Currently, the output from each nmap process is just added
into a filename hardcoded into the executable (/tmp/nwrap.log) and the
scan types/source ports/etc has to be changed by editing the script.
The final version is expected to be released within a week or so, with
the output being in the nlog-style flat-file database format. To test
this script try something like the following:
# host -l example.com | grep "has address" | awk '{print $4}' | sort -u
| uniq | sort -u | grep -v 127.0.0.1> host.list
# ./nwrap -i host.list -p 21-25,79-80,110-113,139
check out /tmp/nwrap.log for results...
Remember that this script is NOT even beta-quality yet, use a your own
risk and please let me know about any problems you have or features you
want.
-HD
http://nlog.ings.com#!/usr/bin/perl
#
#
#
# Usage: # echo <ip address> | nwrap -i - -p <port list>
#
#
use Getopt::Long;
use POSIX ":sys_wait_h";
sub exitclean {
my ($msg) = @_;
print "$msg\n";
exit 2;
}
sub debugprint {
my ($msg) = @_;
print STDERR "[debug] $msg\n" unless (!$OPTdebug);
}
sub sig_catch {
my $signame = shift;
print "\nRecieved a SIG$signame, exiting...\n";
exit 2;
}
###############################################################################
#
# Function: main
# Purpose: read in our host configuration file and start the scans
# To-Do: Done
# Status: Under Development
#
# Date: 04/15/99
#
###############################################################################
# variables...
$nmap = "/usr/local/bin/nmap";
$scantype = "-sS";
$sport = "20";
$syncscans = "15";
$logfile = "/tmp/nwrap.log";
# clear the screen...
$cls = `clear`;
# unbuffer STDOUT & STDERR
select(STDERR);
$| = 1;
select(STDOUT);
$| = 1;
# install signal handler for each signal we want to trap
@SIGNALS = ("INT", "HUP", "KILL", "TERM", "QUIT");
foreach $SIGNAL (@SIGNALS)
{
$SIG{$SIGNAL}=\&sig_catch;
}
# read our command line options
&GetOptions("debug", \$OPTdebug,
"p:s", \$OPTports,
"i:s", \$OPTinput);
# open our input files
open (INPUT,"<".$OPTinput) || exitclean("Could not open host input file: $!");
@targets = (<INPUT>);
close(INPUT) || debugprint("close() failed on INPUT: $!");
# create a host/port list and shuffle it
@targets = shuffle(\@targets);
@ports = parse_ports($OPTports);
@ports = shuffle(\@ports);
foreach $host (@targets)
{
chomp($host);
@ports = shuffle(\@ports);
foreach $port (@ports)
{
push @output, "$host $port";
}
}
@output = shuffle(\@output);
debugprint("My PID = $$");
# now do something with that host/port list
$counter = 0;
$lastindex = $#output;
$startfork = 0;
$endfork = $syncscans;
$forkcount = 0;
$stop = 0;
%pids = ();
%read_buf = ();
#initialize bitmask
$rin = '';
$timeout = 60;
$start = time();
open (LOG, ">>" . $logfile) || die "Could not open log file: $!";
while ($stop == 0)
{
debugprint("Starting spawning loop: $startfork -> $endfork");
for ($forkcount = $startfork; $forkcount <= $endfork; $forkcount++)
{
if ($forkcount >= ($lastindex + 1))
{
$stop = 1;
} else {
($nmaptarget,$nmapport) = split(/\s+/,$output[$forkcount]);
$FD = "NMAP" . $forkcount;
die "Could not fork nmap: $!" unless defined ($pid = open($FD, "$nmap $scantype -g $sport -m - -P0 -p
$nmapport $nmaptarget|"));
$pids{$pid} = $FD;
select($FD) || debugprint("Could not select $FD: $!");
$| = 1; # unbuffer
debugprint("New FD = $FD PID = $pid");
vec($rin,fileno($FD),1) = 1;
if (!$OPTdebug)
{
select STDOUT;
print $cls;
($ctime,$junk) = split(/\./, (int(time - $start) / 60));
print "Scanning Host $forkcount of " . ($lastindex + 1) . "\n";
print "Host:\t$nmaptarget\n";
print "Port:\t$nmapport\n";
print "Time:\t$ctime minutes.\n";
}
}
}
if (!$OPTdebug)
{
$pcount = scalar(keys(%pids));
print "\n\nLaunched $pcount nmap processes, waiting for them to exit: ";
}
$startfork = $startfork + $syncscans;
$endfork = $endfork + $syncscans;
$forkcount = $startfork;
debugprint("Completed spawning loop...");
$n = select($rout = $rin,undef,undef,$timeout);
########################################
# S
while ($n != -1)
{
$n = select($rout = $rin,undef,undef,$timeout);
@deleteQ = ();
foreach $npid (keys(%pids))
{
$n = select($rout = $rin,undef,undef,$timeout);
# hold the pid's of the items to delete from our hash.
debugprint("select = $n");
$FileNo = fileno($pids{$npid});
debugprint("FileNo: $FileNo");
debugprint("Doing if vec()");
if ($FileNo >=0 && vec($rout, $FileNo,1) == 1)
{
# we have new data
debugprint("Trying to read data from $pids{$npid}");
$FH = $pids{$npid};
my $data = <$FH>;
if (length($data) > 0)
{
print LOG $data;
}
}
debugprint("Testing PID $npid for repsonse...");
if (!kill $npid => 0)
{
debugprint("Process $npid has exited with handle: $pids{$npid}");
close($pids{$npid}); # seems to work better if we close this...
push @deleteQ, $npid;
if (!$OPTdebug)
{
print "x ";
}
}
}
foreach $deadpid (@deleteQ)
{
debugprint("Removing $deadpid from pid hash");
delete $pids{$deadpid};
}
}
debugprint("Finished select()");
if (!$OPTdebug)
{
print " Done!\n";
sleep 1;
}
# E
########################################
}
close(LOG);
exit(0);
#
# Functions
#
###############################################################################
#
# Function: getpppip
# Purpose: crude function to get our current ppp device's ip address
# To-Do: Done
# Date: 04/09/99
#
###############################################################################
sub getpppip {
my $DATA=`ifconfig | grep P-t-P | awk \'\{ print \$2 \}\'`;
my $crap;
my $ip;
chomp($DATA);
($crap,$ip) = split(/\:/,$DATA);
return $ip;
}
###############################################################################
#
# Function: rdecoys
# Purpose: generate 6 random ip address in the same subnet as the input address
# To-Do: Done
# Date: 04/09/99
#
###############################################################################
sub rdecoys {
my ($ip) = @_;
my @octets = split(/\./,$ip);
my $count;
my @decoys = ();
my $decoy;
my $output;
for ($count = 0; $count < 6 ; $count++)
{ $decoys[$count] = int(rand()*255); }
foreach $decoy (@decoys)
{
$output .= "$octets[0].$octets[1].$octets[2].$decoy,";
}
$output .="ME";
return $output;
}
###############################################################################
#
# Function: shuffle
# Purpose: Randomize an array
# To-Do: Done
# Date: 04/09/99
#
# Comments: This routine was pretty much ripped from 'Perl Cookbook' pg 121-122
#
###############################################################################
sub shuffle {
my $array = shift;
my $i = scalar(@$array);
my $j;
foreach $item (@$array )
{
--$i;
$j = int rand ($i+1);
next if $i == $j;
@$array [$i,$j] = @$array[$j,$i];
}
return @$array;
}
###############################################################################
#
# Function: parse_ports
# Purpose: Take in an nmap style port list and return an array
# To-Do: Add a check to make sure all the ports added are numeric
# Date: 04/09/99
#
###############################################################################
sub parse_ports {
my ($portstring) = @_;
my $splitter = ",";
my @portlist = ();
my @portsplit = ();
my $port;
@portsplit = split($splitter,$portstring);
foreach $port (@portsplit)
{
@range = split(/\-/,$port);
if (scalar(@range) > 1)
{
if ($range[0] > $range[1] || $range[0] < 0 || $range[0] > 65535 || $range[1] < 0 || $range[1] > 65535)
{
print "Your range of $range[0] -> $range[1] is invalid!\n";
exit(1);
}
for ($i = $range[0]; $i < $range[1] + 1; $i++)
{
if ($i > 0 && $i < 65536)
{
push @portlist, $i;
}
}
} else {
push @portlist, $port;
}
}
return @portlist;
}
# EOF
Current thread:
- nwrap -- nmap stealth wrapper (updated) HD Moore (Apr 15)
