Date: Mon, 12 Apr 1999 12:43:55 -0500
From: HD Moore
To: nmap-hackers@insecure.org
Subject: nwrap -- nmap stealth wrapper
Parts/Attachments:
1 Shown 34 lines Text
2 Shown 171 lines Text
----------------------------------------
I started working on some scripts to 'wrap' nmap and allow for
stealthier scanning routines. The goals for this script include:
Creating a host/port table and then randomizing it.
Scanning each host/port combination in a random sequence.
Easy creation of decoy addresses.
Parallel scanning with child process management.
Consolidation of log files into a nlog-style db or MySQL.
There are still a number of issues I am working on, if you have any
suggestions/complaints email me:
Delay between scans should be a random number within a user-defined range.
Decoy addresses should remain the same during each scan to eliminate chance
of detection by coordinating traffic logs from each scanned host and finding
the real address in each.
Log file consolidation (maybe use -m - and read it all from an open pipe?)
Better option set for the nwrap script.
Attached is the protoype perl script, I wanted to get some feedback
about what stealth options/techniques people wanted to see implemented
in a nmap wrapper script.
-HD aka spinux
http://nlog.ings.com
http://www.trinux.org
[ Part 2: "Attached Text" ]
#!/usr/bin/perl
use Getopt::Long;
sub exitclean {
my ($msg) = @_;
print "$msg\n";
exit 2;
}
$SIG{INT}=\&sig_catch;
&GetOptions("debug", \$OPTdebug,
"p:s", \$OPTports,
"i:s", \$OPTinput);
open (INPUT,"<".$OPTinput) || exitclean("Could not open host input file: $!");
@targets = ();
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);
# now do something with that host/port list
foreach $out (@output)
{
($nmaptarget,$nmapport) = split(/\s+/,$out);
$logfile = "$nmaptarget.$nmapport.log";
print "Scanning port $nmapport on $nmaptarget...\n";
system ("nmap -sS -m $logfile -P0 $nmaptarget -p$nmapport -D" . rdecoys(getpppip()))
|| print "Could not launch nmap: $!\n";
}
exit(0);
#
# Functions
#
sub getpppip {
my $DATA=`ifconfig | grep P-t-P | awk \'\{ print \$2 \}\'`;
my $crap;
my $ip;
chomp($DATA);
($crap,$ip) = split(/\:/,$DATA);
return $ip;
}
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;
}
sub debugprint {
($msg) = @_;
print "[debug] $msg\n" unless (!$OPTdebug);
}
sub sig_catch {
my $signame = shift;
print "\nRecieved SIG$signame, exiting...\n";
exit 2;
}
###############################################################################
#
# 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;
}