Код:
#!/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;
}




