Код:
#!/usr/bin/perl #--------------------------------------- # # Written by MadHat (madhat@unspecific.com) # http://www.unspecific.com/nmap/ # # Copyright (c) 2001-2002, MadHat (madhat@unspecific.com) # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the distribution. # * Neither the name of MadHat Productions nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #--------------------------------------- # where the nmap logs are stored $logdir = "/home/madhat/logs"; # sendmail $sendmail = "/usr/sbin/sendmail"; #--------------------------------------- # Don't change anything below here #--------------------------------------- $VERSION = '1.4'; ############################################################## # # use POSIX "strftime"; use Getopt::Std; getopts("hvd:s:i:b:l:m:"); # if ($opt_h) { &usage; } if ($opt_l) { $logdir = $opt_l; } # # $sdate = time - 86400; if ($opt_b > 2) { $bdate = time - $opt_b * 86400; } else { $bdate = time - 172800; } if ($opt_i =~ /^(\d{1,3}\.\d{1,3}\.\d{1,3})\.\d{1,3}/) { $opt_s = $1; } $basedate = strftime "%m%d%Y", localtime $bdate; $scandate = strftime "%m%d%Y", localtime $sdate; print "Compairing $basedate to $scandate\n" if ($opt_d); opendir(DIR, $logdir) or die "ERROR: Unable to open $logdir: $!\n"; @dir = readdir(DIR); close(DIR); if ($opt_m) { open(STDOUT,"| $sendmail -t") or die "Unable to open sendmail"; print "To: $opt_m\n"; print "Subject: Port Changes from $basedate to $scandate\n\n"; } FILE: for $file (@dir) { next FILE if ($file =~ /^\./); next FILE if ($opt_s and $file !~ /^\d{8}\.$opt_s/); if ($file =~ /^$basedate(\.\d{1,3}\.\d{1,3}\.\d{1,3}\.nmap)$/) { $exten = $1; print "compairing $basedate$exten to $scandate$exten\n" if ($opt_d); open (BASE, "$logdir/$basedate$exten"); @base = <BASE>; close (BASE); open (SCAN, "$logdir/$scandate$exten"); @scan = <SCAN>; close (SCAN); @base = grep(!/^#/, @base); @scan = grep(!/^#/, @scan); LINE: for $cur_scan (@scan) { my $data; chomp $cur_scan; ($host, $ports, $ignored, $OS) = split ("\t", $cur_scan); ($title, $ip, $dns) = split(' ', $host); next LINE if ($opt_i and $ip ne $opt_i); ($title, $port_info) = split(':', $ports); next LINE if ($title ne "Ports"); print "$cur_scan\n" if ($opt_d > 3); for $base_scan ( grep(/\s$ip\s/, @base) ) { chomp $base_scan; print "$ip found in both files\n" if ($opt_d); next LINE if ($cur_scan eq $base_scan); print "Base Scan and New Scan do not Match\n" if ($opt_d); print "$cur_scan\n$base_scan\n" if ($opt_d > 3); ($bhost, $bports, $bignored) = split ("\t", $base_scan); if ($ignored ne $bignored and ($opt_v and $opt_d)) { print "IGNORED entry changed: $bignored -> $ignored\n"; } next if ($bports eq $ports); ($btitle, $bip, $bdns) = split(' ', $host); ($btitle, $bport_info) = split(':', $bports); next if ($btitle ne "Ports"); @bports = split(',', $bport_info); if ($dns ne $bdns and ($opt_v or $opt_d)) { print "DNS entry changed: $bdns -> $dns\n"; } for $port_det (@bports) { $port_det =~ s/\s//g; ($port, $state, $proto, $info, $name) = split('/',$port_det); $base_port{$port} = $state; } @ports = split(',', $port_info); if ($#ports ne $#bports and $opt_d) { print "Number of ports changed: $#bports -> $#ports\n"; } for $port_det (@ports) { $port_det =~ s/\s//g; ($port, $state, $proto, $info, $name) = split('/',$port_det); print "Compairing $ip:$port - $base_port{$port} => $state\n" if ($opt_d > 1); if ($state) { if ( $base_port{$port} eq 'filtered' and $state eq 'open' ) { print "Filtered -> Open $ip:$port\n" if ($opt_d > 1); $data .= sprintf(" +%5u/tcp open %s\n", $port, $name) unless (($port == 80 or $port == 443 ) and !$opt_v); } elsif ( $base_port{$port} eq 'closed' and $state eq 'open' ) { print "Closed -> Open $ip:$port\n" if ($opt_d > 1); $data .= sprintf(" +%5u/tcp open %s\n", $port, $name) unless (($port == 80 or $port == 443 ) and !$opt_v); } elsif ( $base_port{$port} eq 'open' and $state eq 'filtered' and $opt_v ) { print "Opened -> Filtered $ip:$port\n" if ($opt_d > 1); $data .= sprintf(" -%5u/tcp open %s\n", $port, $name); } elsif ( $base_port{$port} eq 'open' and !$state ) { print "GONE $ip:$port\n" if ($opt_d > 1); $data .= sprintf(" -%5u/tcp open %s\n", $port, $name) unless ( ($port == 80 or $port == 443) and !$opt_v); } elsif ( !$base_port{$port} and $state eq 'open' ) { print "Opened from N/A $ip:$port\n" if ($opt_d > 1); $data .= sprintf(" +%5u/tcp open %s\n", $port, $name) unless ( ($port == 80 or $port == 443) and !$opt_v); } elsif ( $base_port{$port} eq 'open' and $state eq 'closed' and $opt_v ) { print "Opened -> Closed $ip:$port\n" if ($opt_d > 1); $data .= sprintf(" -%5u/tcp open %s\n", $port, $name); } elsif ( $base_port{$port} eq 'closed' and $state eq 'filtered' and $opt_d and opt_v ) { print "Closed -> Filtered $ip:$port\n" if ($opt_d > 1); } elsif ( $base_port{$port} eq 'filtered' and $state eq 'closed' and $opt_d and $opt_v ) { print "Filtered -> Closed $ip:$bport\n" if ($opt_d > 1); } elsif ( $base_port{$port} eq 'open' and $state eq 'open' ) { print "No change here, echoing state $ip:$port\n" if ($opt_d > 1); $data .= sprintf(" %5u/tcp open %s\n", $port, $name); } } } if ( $data =~ /\s[\-\+]\s/) { print "$ip $dns\n"; print "$data"; if ($OS =~ /^OS: /) { $OS =~ s/[\|,]/\n /g; print "$OS\n"; } print "\n"; print "-" x 70 . "\n$port_info\n$bport_info\n" if ($opt_d > 2); } print "-" x 70 . "\n" if ($opt_d); } } } else { next FILE; } } if ($opt_m) { close (STDOUT); } 1; sub usage { print "nmap-diff - $VERSION - madahat\@unspecific.com\n\n"; print <<_EOF_; nmap-diff is designed to be used with the log files generated from the nmap-wrapper $0 [-hv] [-s <subnet>] [-i <ip>] [-b <days>] \ [-m <email>] [-l <logdir>] -h help (this stuff) -v is for verbose. This will add all changed ports. Default is to only who new open ports -s <subnet> shows only thaing in that subnet. At this time the subnet accepted is a class C only. -i <IP> only reports on that specific IP. -b <days> sets the base to <days> days back and compares to yesterday's scan. so -b 7 will compare the current scan to the scan from 1 week ago -l <logdir> to specify where the log directory This can be hard coded by editing the script -m <email> to email the output to <email> when the report is generated _EOF_ exit 1; }