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)