/examples/scanhost.pl
Perl | 336 lines | 123 code | 40 blank | 173 comment | 31 complexity | 872e2af712e77caa6cdf9267d50934ee MD5 | raw file
Possible License(s): GPL-2.0
- #!/usr/bin/perl
- #Anthony G. Persaud
- #port_info.pl
- #Description:
- # It takes in a nmap xml file and outputs onto STDOUT and a file the
- # all the ports that were scanned and found by nmap, their different
- # states and services -- all in a comma delimited output
- #
-
- #
- #This program is free software; you can redistribute it and/or modify it under
- #the terms of the GNU General Public License as published by the Free Software
- #Foundation; either version 2 of the License, or (at your option) any later
- #version.
- #
- #This program is distributed in the hope that it will be useful, but WITHOUT ANY
- #WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- #PARTICULAR PURPOSE. See the GNU General Public License for more details.
- #
- # Changelog:
- # APS 01/29/2004: Changed run_nmap_scan to use parsescan().
- # $nmap_exe is set to default 'nmap' if find_exe returns empty
- # APS 02/03/2004: Added ability to read IPs from a file
- #
- #
- #
- use strict;
- use Nmap::Parser::XML;
- use Getopt::Long;
- use File::Spec;
- use Pod::Usage;
- use vars qw(%G);
- use constant CMD1 => '-sV -O --randomize_hosts';
- use constant CMD2 => '-sV -O -F --randomize_hosts';
- use constant TEST_FILE => 'example.xml';
-
- Getopt::Long::Configure('bundling');
-
-
- my $p = new Nmap::Parser::XML;
-
- print "\nscan_host.pl - ( http://npx.sourceforge.net )\n",
- ('-'x50),"\n\n";
-
- GetOptions(
- 'help|h|?' => \$G{helpme},
- 'F' => \$G{fast},
- 'v+' => \$G{verbose},
- 'i=s' => \$G{usefile},
- 'L=s' => \$G{ipfile}
- ) or (pod2usage(-exitstatus => 0, -verbose => 2));
-
- if($G{helpme} || (!$G{usefile} && scalar @ARGV == 0 && !$G{ipfile}))
- {pod2usage(-exitstatus => 0, -verbose => 2)}
-
- #Setup parser callback
- $p->register_host_callback(\&host_handler);
-
-
-
- #If using input file, then don't run nmap and use file
- if($G{usefile} eq ''){$p = run_nmap_scan(@ARGV);
- }
- else {
- #use the input file
- print 'Using InputFile: '.$G{usefile}."\n" if($G{verbose} > 0);
- if(not -e $G{usefile})
- {print STDERR "ERROR: File $G{usefile} does not exists!\n"; exit;}
- $p->parsefile($G{usefile});
- }
-
- #This host handler will get call for every host that is scanned (or found in the
- #xml file)
-
- sub host_handler {
- my $host = shift;
- print ' > '.$host->addr."\n";
- print "\t[+] Status: (".uc($host->status).")\n";
- if($host->status ne 'up'){goto END;}
- tab_print("Hostname(s)",$host->hostnames());
- tab_print("Operation System(s)",$host->os_matches());
- port_service_print($host);
- END:
- print "\n\n";
- }
-
-
- #Quick function to print witht tabs
- sub tab_print {print "\t[+] $_[0] :\n";shift;for my $a (@_){print "\t\t$a\n";}}
-
- sub port_service_print {
- my $host = shift;
- print "\t[+] TCP Ports :\n";
- for my $port ($host->tcp_ports()){
- printf("\t\t%-6s %-20s %s\n",
- $port,
- $host->tcp_service_name($port),
- $host->tcp_service_product($port).' '.
- $host->tcp_service_version($port));
- }
-
- print "\t[+] UDP Ports :\n" if($host->udp_ports_count);
- for my $port ($host->udp_ports()){
- printf("\t\t%-6s %-20s %s\n",
- $port,
- $host->udp_service_name($port),
- $host->udp_service_product($port).' '.
- $host->udp_service_version($port));
- }
-
- }
-
-
- ################################################################################
- ## Utility Functions ##
- ################################################################################
-
- #quick function to find an executable in a given path
- sub find_exe {
-
-
- my $exe_to_find = shift;
- $exe_to_find =~ s/\.exe//;
- local($_);
- local(*DIR);
-
- for my $dir (File::Spec->path()) {
- opendir(DIR,$dir) || next;
- my @files = (readdir(DIR));
- closedir(DIR);
-
- my $path;
- for my $file (@files) {
- $file =~ s/\.exe$//;
- next unless($file eq $exe_to_find);
-
- $path = File::Spec->catfile($dir,$file);
- next unless -r $path && (-x _ || -l _);
-
- return $path;
- last DIR;
- }
- }
-
- }
-
- sub run_nmap_scan {
- my @ips = @_;
- my ($NMAP,$cmd);
-
- if($G{ipfile} && -e $G{ipfile})
- {push @ips ,read_ips_from_file($G{ipfile});
- if($G{verbose} > 0){
- print STDERR "\nIP file contains:\n";
- for(@ips){print STDERR "\t$_\n";}
- print "\n";}
- }
- elsif($G{ipfile} && !-e $G{ipfile})
- {warn "WARNING: IP file $G{ipfile} does not exist!\n";}
-
- if($G{fast}){
- print "FastScan enabled\n" if($G{verbose} > 0 && $G{fast});
- $cmd = join ' ', (CMD2, @ips);
- } else {
- $cmd = join ' ', (CMD1, @ips);
- }
-
-
- my $nmap_exe = find_exe('nmap');
- if($nmap_exe eq '')
- {warn "ERROR: nmap executable not found in \$PATH\n";$nmap_exe = 'nmap';}
-
- print 'Running: '.$nmap_exe.' '.$cmd."\n" if($G{verbose} > 0);
-
-
- $p->parsescan($nmap_exe,$cmd);
-
- return $p;
- }
-
- sub read_ips_from_file {
- my $filename = shift;
- my @ips;
- open FILE, "$filename" || die "ERROR: Could not open $filename! \nERROR: $!";
- for(<FILE>){
- chomp; # no newline
- s/#.*//; # no comments
- s/^\s+//; # no leading white
- s/\s+$//; # no trailing white
- next unless length; # anything left?
- push @ips , $_; #it might be a host name too, so don't expect only numbers
- }
- close FILE;
- return @ips;
-
- }
-
- __END__
- =pod
-
- =head1 NAME
-
- scan_host - a scanning script to gather port and OS information from hosts
-
- =head1 SYNOPSIS
-
- scan_host.pl [OPTS] <IP_ADDR> [<IP.ADDR> ...]
-
- =head1 DESCRIPTION
-
- This script uses the nmap security scanner with the Nmap::Parser::XML module
- in order to run quick scans against specific hosts, and gather all the
- information that is required to know about that specific host which nmap can
- figure out. This script can be used for quick audits against machines on the
- network and an educational use for learning how to write scripts using the
- Nmap::Parser::XML module. B<This script uses the -sV output to get version
- information of the services running on a machine. This requires nmap version
- 3.49+>
-
- =head1 OPTIONS
-
- These options are passed as command line parameters.
-
- =over 4
-
- =item B<-i nmapscan.xml>
-
- Runs the script using the given xml file (which is nmap xml scan data) instead
- of actually running a scan against the given set of hosts. This is useful if
- you only have the xml data on a given machine, and not nmap.
-
- =item B<--fast>
-
- Runs a fast (-F) nmap scan against the host.
-
- =item B<-h,--help,-?>
-
- Shows this help information.
-
- =item B<-L ips.txt>
-
- Reads IP addresses from filename.txt to run a scan against. The IP addresses
- should be in the target specification format explained below.
-
- =item B<-v>
-
- This runs the script in verbose mode. The more times used, the more verbose
- the script will be.
-
- =back 4
-
- =head1 TARGET SPECIFICATION
-
- This documentation was taken from the nmap man page. The IP address inputs
- to this scripts should be in the nmap target specification format.
-
- The simplest case is listing single hostnames or IP addresses onthe command
- line. If you want to scan a subnet of IP addresses, you can append '/mask' to
- the hostname or IP address. mask must be between 0 (scan the whole internet) and
- 32 (scan the single host specified). Use /24 to scan a class 'C' address and
- /16 for a class 'B'.
-
- You can use a more powerful notation which lets you specify an IP address
- using lists/ranges for each element. Thus you can scan the whole class 'B'
- network 128.210.*.* by specifying '128.210.*.*' or '128.210.0-255.0-255' or
- even use the mask notation: '128.210.0.0/16'. These are all equivalent.
- If you use asterisks ('*'), remember that most shells require you to escape
- them with back slashes or protect them with quotes.
-
- Another interesting thing to do is slice the Internet the other way.
-
- Examples:
-
- scan_host.pl 127.0.0.1
- scan_host.pl target.example.com
- scan_host.pl target.example.com/24
- scan_host.pl 10.210.*.1-127
- scan_host.pl *.*.2.3-5
- scan_host.pl 10.[10-15].10.[2-254]
-
-
- =head1 OUTPUT EXAMPLE
-
- These are ONLY examples of how the output would look like.
-
- Scan Host
- --------------------------------------------------
- [>] 127.0.0.1
- [+] Status: (UP)
- [+] Hostname(s) :
- localhost.localdomain
- [+] Operation System(s) :
- Linux Kernel 2.4.0 - 2.5.20
- [+] TCP Ports :
- 22 ssh OpenSSH 3.5p1
- 25 smtp
- 111 rpcbind
- 443 https
- 631 ipp
- [+] UDP Ports :
- 111 rpcbind
- 937 unknown
-
-
-
- =head1 BUG REPORTS
-
- Please submit any bugs to:
- L<http://sourceforge.net/tracker/?group_id=97509&atid=618345>
-
- =head1 SEE ALSO
-
- L<Nmap::Parser::XML>
-
- The Nmap::Parser::XML page can be found at: L<http://npx.sourceforge.net/>.
- It contains the latest developments on the module. The nmap security scanner
- homepage can be found at: L<http://www.insecure.org/nmap/>.
-
- =head1 AUTHOR
-
- Anthony G Persaud <ironstar@iastate.edu>
-
- =head1 COPYRIGHT
-
- This program is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free Software
- Foundation; either version 2 of the License, or (at your option) any later
- version.
-
- This program is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- L<http://www.opensource.org/licenses/gpl-license.php>
-
- =cut