#----------------------------------------------------------------------------------------------
# dumpevtsec.pl
# Version: 0.01
# 
# Purpose:  Queries server eventlog and produces a report on certain security activity
#  
# NOTES: 
# - Added enhancements to original dumpevt.pl by Harlan Carvey, keydet89@yahoo.com
# 
#
# Author: Dave Chappell
#----------------------------------------------------------------------------------------------
use strict;
use Win32;
use Win32::EventLog;
use Benchmark;
use POSIX;

my $server =  "\\\\testsrv"; #shift || Win32::NodeName;
my $t0;
my $t1;
my $evtrec;
my $sid;
my ($rptevtname,$rptevtcnt,$rptusr,$rptcomp,$rptevtdate,$rptevtrecnum);

my $evtcnt = &GetEvents($server,"Security");
&report($evtcnt);


#----------------------------------------------------
# Reporting Templates
# 
#----------------------------------------------------
format STDOUT =            
Event Type                                                  Total 
------------------------------------------------------------------
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  @>>>>>
$rptevtname,                                                $rptevtcnt

.

format STDBODY =
Details
----------------------------------------------------------------------------------------------------------------------------------
Reporting User                                                 Reporting Computer    Date                  Eventlog Record Number
----------------------------------------------------------------------------------------------------------------------------------
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<      @<<<<<<<<<<<<<<<<<    @<<<<<<<<<<<<<<<<<    @<<<<<<<<<<<<<<<<<
$rptusr,                                                        $rptcomp,             $rptevtdate,          $rptevtrecnum
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<      @<<<<<<<<<<<<<<<<<    @<<<<<<<<<<<<<<<<<    @<<<<<<<<<<<<<<<<<
$rptusr,                                                        $rptcomp,             $rptevtdate,          $rptevtrecnum

.

##################
# Functions
##################
#----------------------------------------------------
# GetEvents()
# Input:  Server name, EventLog
# Output: Log entries, to $acctcnt hash
#----------------------------------------------------
sub GetEvents {
	my($server,$log) = @_;
	my ($evt,$total,$oldest,$evtHashRef);
	my $start = 0;
	my $counter = 0;
        my $acctcnt;
	#$evt = Win32::EventLog->new("D:\\dev\\dumpevt\\dev\\new\\sec-test.evt") || die "Could not open $log log on $server: $!\n";
	$evt = Win32::EventLog->new($log,$server) || die "Could not open $log log on $server: $!\n";
	$evt->GetNumber($total) || die "Can't get number of EventLog records: $!\n";
	$evt->GetOldest($oldest) || die "Can't get number of oldest EventLog record: $!\n";
	my $t0 = new Benchmark;
	while ($start < $total) {
	    
	    $evt->Read(EVENTLOG_FORWARDS_READ|EVENTLOG_SEEK_READ,$oldest+$start,$evtHashRef) or die "Can't read EventLog entry #$start\n";
            my $id = (${$evtHashRef}{EventID} & 0xffff);
            my $acctevts = join '|', 624..670; #Filter account management events
            
            $sid = unpack("H" . 2 * length(${$evtHashRef}{User}), ${$evtHashRef}{User});
            
            # Retrieve interesting events and filter out events generated by the System account
            if ($id =~ /$acctevts/ && $sid =~ /[aA-fF]/){  
                
                my $sidbin = ${$evtHashRef}{User};
                my  $sidtxt = &SID_bin2text($sidbin);
                Win32::EventLog::GetMessageText($evtHashRef);    
                my $msg = $evtHashRef->{Message};
                $evtrec = ${$evtHashRef}{RecordNumber};
                
                #Track number of events by ID
                ${$acctcnt}->{$id}->{counter}++;
                ${$acctcnt}->{$id}->{$evtrec}->{rptcomputer} = ${$evtHashRef}{Computer};
                ${$acctcnt}->{$id}->{$evtrec}->{Date} = localtime(${$evtHashRef}{TimeGenerated});
                ${$acctcnt}->{$id}->{$evtrec}->{rptuser} = $sid;
                ${$acctcnt}->{$id}->{$evtrec}->{evtmsg} = $msg;                    
            }
            $start++;
	}
	my $t1 = new Benchmark;
	print "\n\nDONE\n\n";
	warn(strftime("%Y/%m/%d %H:%M:%S", localtime), " Record parser took ", timestr(timediff($t1, $t0)), " to parse ($total) records\n");
	return ${$acctcnt};
}

#----------------------------------------------------
# SID_bin2text()
# Input:  SID in binary form
# Output: Returns Text Representation of SID
#----------------------------------------------------
sub SID_bin2text {
	my ($bin) = @_;
	my ($Revision, $SubAuthorityCount,@IdentifierAuthorities) = unpack("CCnnn", $bin);
	($IdentifierAuthorities[0] || $IdentifierAuthorities[1]) and return;
	my ($temp, $temp2, @SubAuthorities) = unpack("VVV$SubAuthorityCount",$bin);
  	return "S-$Revision-$IdentifierAuthorities[2]-" . join("-", @SubAuthorities);
}

#----------------------------------------------------
# SID_bin2bin()
# Input:  SID in Text form
# Output: Returns binary Representation of SID
#----------------------------------------------------
sub SID_text2bin {
my($text) = @_;
	my (@Values) = split(/\-/, $text);
	($Values[0] == "S") or return;
	return pack("CCnnnV".(@Values-3), $Values[1], @Values-3, 0, 0, $Values[2], @Values[3..(@Values-1)]);
}
#----------------------------------------------------
# SID_bin2text()
# Input:  Eventlog hash
# Output: produces Report
#
#Example:
#
# Event Type                                                  Total
#------------------------------------------------------------------
#User Account Changed                                            16
#
#----------------------------------------------------------------------------------------------------------------------------------------------------------------
#Reporting User								Reporting Computer		Date				Eventlog Record Number
#----------------------------------------------------------------------------------------------------------------------------------------------------------------
#<user binary SID>        		                                TEST			        Tue Dec 10 09:17:54 2002        <not implementated yet>
#<user binary SID>        		                                TEST			        Tue Dec 10 09:17:54 2002        <not implementated yet>
#<user binary SID>        		                                TEST			        Tue Dec 10 09:17:54 2002        <not implementated yet>
#<user binary SID>        		                                TEST			        Tue Dec 10 09:17:54 2002        <not implementated yet>
#<user binary SID>        		                                TEST			        Tue Dec 10 09:17:54 2002        <not implementated yet>
#...
#
#----------------------------------------------------
sub report {
    my ($hashref) = $_[0];
    my $id;
    my $summ;
    my %evtdescriptor = (
        624 => 'User Account Created',
        625 => 'User Account Type Change',
        626 => "User Account Enabled",
        627 => "Change Password Attempt",
        628 => "User Account password set",
        629 => "User Account Disabled",
        630 => "User Account Deleted",
        631 => "Security Enabled Global Group Created",
        632 => "Security Enabled Global Group Member Added", 
        633 => "Security Enabled Global Group Member Removed",
        634 => "Security Enabled Global Group Deleted",
        635 => "Security Enabled Local Group Created",
        636 => "Security Enabled Local Group Member Added", 
        637 => "Security Enabled Local Group Member Removed",
        638 => "Security Enabled Local Group Deleted",
        639 => "Security Enabled Local Group Changed",
        640 => "General Account Database Change",
        641 => "Security Enabled Global Group Changed",
        642 => "User Account Changed",
        643 => "Domain Policy Changed",
        644 => "User Account Locked Out",
        645 => "Computer Account Created",
        646 => "Computer Account Changed",
        647 => "Computer Account Deleted",
        648 => "Security Disabled Local Group Created",
        649 => "Security Disabled Local Group Changed",
        650 => "Security Disabled Local Group Member Added",
        651 => "Security Disabled Local Group Member Removed",
        652 => "Security Disabled Local Group Deleted",
        653 => "Security Disabled Global Group Created",
        654 => "Security Disabled Global Group Changed",
        655 => "Security Disabled Global Group Member Added",
        656 => "Security Disabled Global Group Member Removed",
        657 => "Security Disabled Global Group Deleted",
        658 => "Security Enabled Universal Group Created",
        659 => "Security Enabled Universal Group Changed",
        660 => "Security Enabled Universal Group Member Added",
        661 => "Security Enabled Universal Group Member Removed",
        662 => "Security Enabled Universal Group Deleted",
        663 => "Security Disabled Universal Group Created",
        664 => "Security Disabled Universal Group Changed",
        665 => "Security Disabled Universal Group Member Added",
        666 => "Security Disabled Universal Group Member Removed",
        667 => "Security Disabled Universal Group Deleted",
        668 => "Group Type Changed",
        669 => "Add SID History (Success)",
        670 => "Add SID History (Failure)"
   );

    foreach $id (keys %{$hashref}){
        
        foreach $summ (keys %evtdescriptor) {
            if ($id == $summ) {
                $rptevtname = $evtdescriptor{$summ};
                $rptevtcnt = ${$hashref}{$id}{counter};
                select (STDOUT);
                write (STDOUT);
                
                select (STDBODY); 
                foreach my $sum2 (keys %{${$hashref}{$id}}){
                    if ($sum2 =~ /.*\d/) {
                        
                        $rptusr = ${$hashref}{$id}{$sum2}{rptuser};
                        $rptcomp = ${$hashref}{$id}{$sum2}{rptcomputer};
                        $rptevtdate = ${$hashref}{$id}{$sum2}{Date};
                        $rptevtrecnum = $sum2;
                        write (STDBODY);
                    }
                }
            }
        }
    }
}


