I have corrected a bug were some Exploits and Worms were not reported. 
For smtp support you will need to define your smtp server and email address in the 
perl script.

You will also need "LogSyslog" enabled in your clamav.conf for Milter logging.

Options:
-h Help
-f Log file
-l Log type - valid types are: amavis and milter - Defaults to milter
-r Show recipients
-s Show senders - Milter only
-c Minimum virus count for unique hosts
-v Minimum virus type count
-m Email report to predefined values set in this perl script
-V Version

For example:
./source_virus_count.pl -l amavis -f amavis/amavis.log -r -c 10
Shows a count of each virus type:
Count is 16 for Worm.SomeFool.P
Count is 13 for Worm.Zafi.B
Count is 7 for Worm.Klez.H
Count is 3 for Worm.SomeFool.Gen-1
Count is 1 for Worm.SomeFool.Q
Count is 1 for Worm.SomeFool.I
Count is 1 for Worm.Bagle.Gen-zippwd, Worm.Bagle.Gen-zippwd
Count is 1 for Worm.Bagle.AG.2
Count is 1 for Worm.SomeFool.X
 
Shows uniques hosts with a virus count over 10:
 
mail.nsslawoffice.com sent the following virus's a total of 12 times:
Worm.Zafi.B was transmitted 12 times.
 
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.
Recipient address [EMAIL PROTECTED] was seen 1 times.

#!/usr/bin/perl

# Licensed under the GNU GPL
# Author - Brett L Simpson

# Features
# Count the number of times a virus was sent in descending order
# Count the number of times an IP address sent a virus in descending order
# Show each unique virus that was sent for each IP address.
# Populate a complex data structure with message id's, ip address's, and virus names. This is necesary since the ip address and virus name are on separate lines but have the same message id.
# Capable of sending email based reports

# Changelog
# 10/07/2004 - Released version 0.30
# 10/07/2004 - Corrected a bug were HTML.Phishing.Bank-1, Worm.SomeFool.Gen-1, and a few others weren't reported. 
# 08/31/2004 - Put error handling into opening of log files and pull the hostname of the system for mailed reports.
# 08/31/2004 - Released version 0.20
# 08/30/2004 - Released version 0.10
# 08/30/2004 - Added command line arguments
# 08/27/2004 - Corrected a bug were multiple Senders or virus's per IP address would produce errors
# 08/20/2004 - Commented out Recipient information

# TODO
# Review and cleanup of code
# Add command line argument for only showing specific hosts who sent virus's
# Add a csv option
# Maybe add an option to plot a graph
# Trending similar to Graphdefang


use warnings;
use diagnostics;
use strict;
use vars qw/ $opt_h $opt_f $opt_l $opt_r $opt_s $opt_c $opt_v $opt_m $opt_V /;
use Getopt::Std;

	my $Version = "0.30";
	my $host_count = "10";
	my $virus_count = "1";
	my $mail_server = '207.156.7.30';
	my $mail_user = "[EMAIL PROTECTED]";
	my $log_file = '/var/log/maillog';


getopts( 'hf:l:sc:v:rmV' );	

if ($opt_h) {
	print "Options: \n";
	print "-h Help \n";
	print "-f Log file \n";
	print "-l Log type - valid types are: amavis and milter - Defaults to milter \n";
	print "-r Show recipients \n";
	print "-s Show senders - Milter only \n";
	print "-c Minimum virus count for unique hosts \n";
	print "-v Minimum virus type count \n";
	print "-m Email report to predefined values set in this perl script  \n";
	print "-V Version \n";
	exit 0
}

if ($opt_f) {
	$log_file = $opt_f;
}


my $log_type;
if ($opt_l) {
	if ($opt_l eq "amavis") {
	$log_type = $opt_l;
	} elsif ($opt_l eq "milter") {
	$log_type = $opt_l;
	} else {
	print "-l Log type - valid types are: amavis and milter  \n";
	exit 1
	}
} else {
	$log_type = "milter";
}

my $show_senders;
if ($opt_s) {
	if ($log_type eq "amavis") {
		print "Showing of Senders not yet supported for Amavis\n";
		exit 1
	} else {
		$show_senders = "1";
	}
}

$host_count = $opt_c if ($opt_c);

$virus_count = $opt_v if ($opt_v);

my $show_recipients = "1" if ($opt_r);

my $send_email = "1" if ($opt_m);

if ($opt_V) {
	print "Version $Version \n";
	exit 0
}

	our ($ip_addr, $sender);
	my ($email, %ip_addr, $virus, %virus, $Virus, $Sender, $recipient, $Recipient, $message_id, @text_body);

open(FILE, "$log_file") or die("Error opening $log_file: $!\n");
while(<FILE>) {

	if ($log_type eq "milter") {

		if (/(?:\d|\D)+sendmail\[(?:\d)+\]:\s((?:\w)+):(?:\d|\D)+\[(\d+\.\d+\.\d+\.\d+)\]/) {
			$message_id = $1;
			$ip_addr = $2;
			$email->{$message_id}{ip_addr} = $ip_addr;
		} 
		elsif (/(?:\d|\D)+clamav-milter\[(?:\d)+\]:\s((?:\w)+):\sstream:\s((?:\d|\D)+)\sIntercepted virus from \<((?:\d|\D)+)\> to \<((?:\d|\D)+)\>/) {
        		$message_id = $1;
			$virus = $2;
			$sender = $3;
			$recipient = $4;
			$email->{$message_id}{virus} = $virus;
			$email->{$message_id}{sender} = $sender;
			$email->{$message_id}{recipient} = $recipient;
		}
	} elsif ($log_type eq "amavis") {
		if (/(?:\d|\D)+\s\(((?:\d|\D)+)\)\sBlocked INFECTED\s\(((?:\d|\D)+)\)\,\s\<\?\@((?:\d|\D)+)\>\s\-\>\s\<((?:\d|\D)+)\>\,\squar(?:\d|\D)+/) {
			$message_id = $1;
			$virus = $2;
			$ip_addr = $3;
			$recipient = $4;
                                                                                                                                                             
			$email->{$message_id}->{virus} = $virus;
			$email->{$message_id}->{recipient} = $recipient;
			$email->{$message_id}->{ip_addr} = $ip_addr;                                                                                         
		}
	}

}
close(FILE);

foreach $message_id ( keys  %{ $email } ) {
		if ( $email->{$message_id}{virus} ) {
			$virus = $email->{$message_id}{virus};
			$ip_addr = $email->{$message_id}{ip_addr};
			$recipient = $email->{$message_id}{recipient};
			$sender = $email->{$message_id}{sender};
			#Counts total number of times a virus was sent
			$ip_addr{$virus}++;
			#Counts total number of virus's sent by IP address
			$virus{$ip_addr}++;
			#Counts total number of unique virus's per IP address
			$email->{$ip_addr}{virus}{$virus}++;
			#Counts total number of unique senders per IP address
			if ($show_senders) {
				$email->{$ip_addr}{sender}{$sender}++;
			}
			#Counts total number of unique recipients per IP address
			if ($show_recipients) {
				$email->{$ip_addr}{recipient}{$recipient}++;
			}
		}
}

sub hashValueDescendingVirus {
	   $email->{$ip_addr}{virus}{$b} <=> $email->{$ip_addr}{virus}{$a};
}
		
sub hashValueDescendingRecipient {
	   $email->{$ip_addr}{recipient}{$b} <=> $email->{$ip_addr}{recipient}{$a};
}

sub hashValueDescendingSender {
	   $email->{$ip_addr}{sender}{$b} <=> $email->{$ip_addr}{sender}{$a};
}

sub hashValueDescendingNum {
   $ip_addr{$b} <=> $ip_addr{$a};
}

sub hashValueDescendingIp {
   $virus{$b} <=> $virus{$a};
}

push(@text_body, "Shows a count of each virus type:\n");

foreach $virus (sort hashValueDescendingNum (keys(%ip_addr))) {
	if ($ip_addr{$virus} >=  "$virus_count") {
		push(@text_body, "Count is $ip_addr{$virus} for $virus\n");
	}
}

if ($host_count) {
	push(@text_body, "\nShows uniques hosts with a virus count over $host_count:\n");
}


for $ip_addr (sort hashValueDescendingIp (keys(%virus))) {
#	add check to only show specific unique hosts -u address, address2
	if ($virus{"$ip_addr"} >= "$host_count") {


		push(@text_body, "\n$ip_addr sent the following virus's a total of $virus{$ip_addr} times: \n");
		
		foreach $Virus (sort hashValueDescendingVirus (keys (%{$email->{$ip_addr}{virus}}) )) {
			push(@text_body, "$Virus was transmitted $email->{$ip_addr}{virus}{$Virus} times.\n");
		}

		push(@text_body, "\n");

		if ($show_senders) {
#			modify to show -s address, address2 from command line			
#			if ($ip_addr eq "$ip_address") {		
				foreach $Sender (sort hashValueDescendingSender (keys( %{ $email->{$ip_addr}{sender} } ))) {
					push(@text_body, "Possibly spoofed sender address $Sender was seen $email->{$ip_addr}{sender}{$Sender} times.\n");
				}
#			}
		}

		if ($show_recipients) {
#			modify to show -r address, address2 from command line			
#			if ($ip_addr eq "$ip_address") {		
				foreach $Recipient (sort hashValueDescendingRecipient (keys( %{ $email->{$ip_addr}{recipient} } ))) {
					push(@text_body, "Recipient address $Recipient was seen $email->{$ip_addr}{recipient}{$Recipient} times.\n");
				}
#			}
		}
	}
}


	

#Email handling section

if ($send_email) {
	#Find hostname
	use Sys::Hostname;
	my $hostname = hostname();

	use Net::SMTP;
	my $smtp;
	$smtp = Net::SMTP->new($mail_server);
	$smtp->mail($ENV{USER});
	$smtp->to($mail_user);
	$smtp->data();
	$smtp->datasend("To: $mail_user\n");
	$smtp->datasend("Subject: Analysis of $log_type logs for Virus's on $hostname\n");
	for(my $counter=0 ; $counter < @text_body ; $counter++) {
		$smtp->datasend("$text_body[$counter]");
	}
	$smtp->dataend();
	$smtp->quit;
}

#Print out data
unless ($send_email) {
	for(my $counter=0 ; $counter < @text_body ; $counter++) {
		print "$text_body[$counter]" ;
	}
}
_______________________________________________
http://lists.clamav.net/cgi-bin/mailman/listinfo/clamav-users

Reply via email to