#!/usr/bin/perl
#################################################################################################
#    log2timeline/faersluskra2timalina
#################################################################################################
# This is a "special" version of log2timeline, which is a direct clone of the log2timeline
# front-end, with parameters and tool name directly translated to Icelandic (a request from
# a co-worker that really wanted to have the CLI more complicated to navigate).
#
# So this is version is dedicated to you Benji..  finally your dream of a pure Icelandic forensic
# tool has become a reality.
#
# Author: Kristinn Gudjonsson
# Date : 19/09/12
#
# Copyright 2009-2012 Kristinn Gudjonsson (kristinn ( a t ) log2timeline (d o t) net)
#
#  This file is part of log2timeline.
#
#    log2timeline 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 3 of the License, or
#    (at your option) any later version.
#
#    log2timeline 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.
#
#    You should have received a copy of the GNU General Public License
#    along with log2timeline.  If not, see <http://www.gnu.org/licenses/>.
#

use strict;

use Time::localtime;       # for time conversion
use Getopt::Long;          # read parameters
use Pod::Usage;            # for man and help messages
use LWP::UserAgent;        # to get the version number from the web
use DateTime::TimeZone;    # for time zones,
use Log2Timeline;          # the main engine of log2timeline
use Digest::MD5;           # for MD5 sum calculation
use Encode;

# define variables
my @dir_content;
my $plug;

my $line;
my @lines;
my $t_line;
my $p_line;
my $verify;

my $log_file;
my $temp;
my @args;    # an array that contains the arguments

# for parameters
my $show_version = 0;
my $print_help   = 0;
my $time_offset  = 0;
my $textfield    = '';
my $format       = '';
my $hostname     = 'unknown';    # a variable defining the hostname
my $output_file  = 'csv';
my $out_file     = 'STDOUT';
my $detail   = 0;   # a variable defining if we should skip the quick test in the verification phase
my $log_file = '';
my $file_exists = 0;
my $format_file;
my $temp_file = ''
  ; # the default value for the temporary file location (it is automatically detected if this option is used)
my $output;
my $check        = 0;
my $timezone     = undef;
my $out_timezone = undef;
my $time_object;
my $debug     = 0;
my $digest    = 0;     # defines whether or not a MD5 sum is to be calculated
my $recursive = 0;     # recursive search or not?
my $preproc   = 0;     # do we want to run pre-processing modules
my $exclude   = '';    # an exclusion list (list of files we would like to exclude from parsing)
my @input_arguments;
my $mft_detail = 0;    # determine if mft module prints $FN timestamps

# record the start time...
my $start_time = time();

# for message digest
my ($sum, %last_sum);

# the l2t object
my $l2t;

# configure the getoptions
Getopt::Long::Configure("no_ignore_case");

# read options
GetOptions(
           "timamismunur=s"      => \$time_offset,
           "fortexti=s"         => \$textfield,
           "fjolordur+"    => \$debug,
           "uppfaersla!"    => \$check,
           "utreikningur!"  => \$digest,
           "inntaksmat=s"  => \$format_file,
           "utgafa!"    => \$show_version,
           "fljotkeyrsla!"          => \$detail,
           "velarnafn=s"      => \$hostname,
           "utgangur=s"    => \$output_file,
           "skrifa=s"     => \$out_file,
           "faersluskra=s"       => \$log_file,
           "endurkvaema!"  => \$recursive,
           "smaatridi!"     => \$mft_detail,
           "forvinnsla!" => \$preproc,
           "timabelti=s"      => \$timezone,
           "Timabelti=s"      => \$out_timezone,
           "undanskilja=s"   => \$exclude,
           "bradabirgda=s"    => \$temp_file,
           "breytur=s"      => \@input_arguments,
           "hjalp|?!"     => \$print_help
          ) or pod2usage(2);

# create the log2timeline object
$l2t = Log2Timeline->new()
  or pod2usage(
               {
                 -message => "Unable to create the Log2Timeline object, unable to continue",
                 -verbose => 1,
                 -exitval => 4
               }
              );

# check if the object is valid (the constructor was able to complete)
pod2usage(
    {
       -message =>
         "The Log2Timeline object is not valid, cannot continue. The dreaded case of an 'Unknown error'.",
       -verbose => 1,
       -exitval => 5
    }
) unless $l2t->is_valid;

# check to see if we want all log messages written to a specific log file (or just to STDERR)
if ($log_file ne '') {
    open(STDERR, '>' . $log_file);
}

# check options
if ($show_version) {
    my @t;
    @t = split(/\//, $0) unless $^O =~ m/MSWin/;
    @t = split(/\\/, $0) if $^O =~ m/MSWin/;
    print $t[$#t] . " version " . $l2t->version . "\n";
    exit 0;
}

if ($check) {

    # check the latest version
    print STDERR $l2t->check_upgrade . "\n";

    exit 0;
}

# check if we want to print the help message
if ($print_help) {

    # check if the option -f is also used, then we print the format file help as well
    if ($format_file ne '' && $format_file ne 'list') {
        eval {

            # print the help message
            print STDERR $l2t->get_help_in($format_file) . "\n";
        };

        # check if we were unable to load the format file
        if ($@) {
            pod2usage(
                {
                   -message =>
                     "Unable to load input module [$format], so no help is printed (try $0 -f list to see available input modules)\nThe error message is: $@",
                   -verbose => 1,
                   -exitval => 12
                }
            );
        }
    }
    else {

        # then we print the help message
        print STDERR "\n\n";
        print STDERR "-------------------------------------------------\n";
        pod2usage(1);
    }
    exit 0;

}

# check the temporary file
unless ($temp_file eq '') {

    # now we need to check the temporary folder, to see if it exists
    pod2usage(
        {
           -message =>
             "The temporary folder ($temp_file) does not exist, it has to exist for the tool to able to use it.\n",
           -verbose => 1,
           -exitval => 8
        }
    ) unless -d $temp_file;

    # set the separator
    my $p;

    $p = $temp_file . '\\bla.txt' if $^O =~ m/MSWin/i;
    $p = $temp_file . '/bla.txt' unless $^O =~ m/MSWin/i;

    # now the folder exists, let's check if we can write a file to it...
    pod2usage(
        {
           -message =>
             "The temporary folder ($temp_file) does not exist, it has to exist for the tool to able to use it.\n",
           -verbose => 1,
           -exitval => 8
        }
    ) unless open(TF, '>' . $p);

    # remove this stuff
    close(TF);
    unlink($p) if -f $p;

}

# find format files, check if format = list (then we are supposed to print available formats)
if ($format_file eq "list") {
    eval { print $l2t->get_inputs; };
    if ($@) {
        pod2usage(
                  {
                    -message => "Error, unable to parse input module.\nError message: $@",
                    -verbose => 1,
                    -exitval => 12
                  }
                 );
    }

    # since we do no parsing we exit from the program
    exit 0;
}

# check if we want to list all output plugins
if ($output_file eq "list") {
    eval { print Log2t::Common::list_output(); };
    if ($@) {
        pod2usage(
                  {
                    -message => "Error, unable to parse output module.\nError message: $@",
                    -verbose => 1,
                    -exitval => 13
                  }
                 );
    }
    exit 0;
}

# check if we are about to list timezone settings
if ($timezone eq "list" or $out_timezone eq "list") {
    print $l2t->get_timezone_list;
    exit 0;
}

# no we know that we are not printing a help message and not listing up available format files or output plugins
# so we are about to parse a log file, and then we need to know the format of the file
# (there is no mechanism to detect the format of the log file, yet it might come in a future version)

# if no input module is defined, then we will use the "all", or guessing which module to use
$format_file = 'all' if $format_file eq '';
$format_file = 'all' if $format_file eq 'guess';

# test parameters, just to see if we have at least one parameter left on the command line (indicates that
# a log file has been provided)
if ($#ARGV < 0) {
    pod2usage(
              {
                -message => "Wrong usage: no log file passed on",
                -verbose => 1,
                -exitval => 1
              }
             );
}

# check if timezone has been set or not
print STDERR "-----------------------------------------------------------------
      [WARNING] 
No timezone has been chosen so the local timezone of this
machine is chosen as the timezone of the suspect drive.

If this is incorrect, then cancel the tool and re-run it
using the -z TIMEZONE parameter to define the suspect drive
timezone settings (and possible time skew with the -s parameter)

(5 second delay has been added to allow you to read this message)
-----------------------------------------------------------------\n" unless defined $timezone;
sleep(5) unless defined $timezone;
$timezone = 'local' unless defined $timezone;

# set the output timezone
$out_timezone = $timezone unless defined $out_timezone;

# check the timezone settings
eval {
    print STDERR "[LOG2TIMELINE] Testing time zone $timezone\n" if $debug;
    $time_object = DateTime::TimeZone->new('name' => "$timezone");
};
if ($@) {
    pod2usage(
              {
                -message => "Timezone [$timezone] is not a valid timezone",
                -verbose => 1,
                -exitval => 45
              }
             );
}

# assign the file name of the log file
$log_file = shift(@ARGV);

# check to see if this file/dir exists
if (-e $log_file || -d $log_file) {

    # file exists
    print STDERR "Start processing file/dir [$log_file] ...\n";
}
else {

    # the file/dir does not exist, exit the code
    pod2usage(
           {
             -message => "Wrong usage: log file [$log_file] does not exist (or unable to find it)",
             -verbose => 1,
             -exitval => 1
           }
    );
}

# print a log message
print STDERR "Starting to parse using input modules(s): [$format_file] \n";

# prepare the output file
if ($out_file eq 'STDOUT') {
    open(MYFILE, ">-");
}
else {

    # check if it exists
    $file_exists = 1 if -f $out_file;

    # we are redirecting to a file
    open(MYFILE, '>>' . $out_file);
}

# start by fixing the settings
eval {
    $l2t->set(
              'file'          => $log_file,
              'recursive'     => $recursive,
              'input'         => $format_file,
              'output'        => $output_file,
              'time_zone'     => $timezone,
              'out_time_zone' => $out_timezone,
              'log_file'      => $out_file,
              'offset'        => $time_offset,
              'exclusions'    => $exclude,
              'text'          => $textfield,
              'append'        => $file_exists,
              'debug'         => $debug,
              'temp'          => $temp_file,
              'digest'        => $digest,
              'quick'         => $detail,
              'raw'           => 0,
              'detailed_time' => $mft_detail,
              'hostname'      => $hostname,
              'preprocess'    => $preproc,
             );
};
if ($@) {
    pod2usage(
              {
                -message => "Unable to configure the log2timeline engine.  Error message: $@\n",
                -verbose => 1,
                -exitval => 11
              }
             );
}

# check if the output file exists, and if it does, we need to
# do some parsing to remove extra footer before appending to it
if ($file_exists) {

    # first verify that the footer actually contains data
    my $footer = $l2t->get_out_footer;

    if (($out_file ne 'STDOUT') && ($footer)) {

        # we need to re-open the file read-only
        close(MYFILE);
        open(MYFILE, '<' . $out_file);

        # we have a footer and need to remove it

        # read the content of the file
        my @content = <MYFILE>;
        close(MYFILE);

        # remove the footer
        @content = grep { !/$footer/ } @content;

        # open the file up again and print the previous content - header
        open(MYFILE, '>' . $out_file);
        print MYFILE @content;
    }
}

eval { $l2t->start; };

# check if there were errors loading the format file
if ($@) {
    pod2usage(
              {
                -message => "Unable to run the tool.  Error message given: $@\n",
                -verbose => 1,
                -exitval => 12
              }
             );
}

# close the file
close(MYFILE);

# check if this was recursive... then we print out end time
printf STDERR "Run time of the tool: %s seconds\n", time() - $start_time if $recursive;

##############################################################################################################
#    COMMON SUBROUTINES
##############################################################################################################
# here follow routines that can be called by each of the format files, that is routines that are shared
# among all of the format files

# a simple routine to print a line
sub print_line($) {
    my $line = shift;

    # print to the file in question
    print MYFILE encode('utf8', $line);

    #print MYFILE $line;
}

__END__

=pod

=head1 NAME

B<faersluskra2timaline> - a log file parser that produces a body file used to create timelines (for forensic investigations).

=head1 SYNOPSIS  

B<faersluskrar2timaline> [OPTIONS] [-f FORMAT] [-z TIMEZONE] [-o OUTPUT MODULE] [-w BODYFILE] LOG_FILE/LOG_DIR [--] [FORMAT FILE OPTIONS]

=head1 OPTIONS

=over 8

=item B<-timamismunur TIMI>

Timamismunur maeldur i sekundum fra rettum tima og theim sem er skradur a upprunalegri vel. Snidid a breytunni TIMI er: X | Xs | Xm | Xh, thar sem X er heiltala og s merkir sekundur, h klukkutima og m minutur. Sjalfgefin hegdun er samt ad tulka toluna sem sekundur.

=item B<-fortexti TEXTI>

Skella textanum B<TEXTI> fyrir framan hverja linu. Thad er ad segja B<TEXTI> er strengur sem er skeytt fyrir framan skraarnafn a hverri skra til ad vista heilstaedari skraarnafn. Til daemis ad nota "-m C:" til ad skeyta textanum "C:/" fyrir framan hvert skraarnafn til ad gefa til kynna ad um se ad raeda skrain komi fra C: drifi vidkomandi tolvu.

=item B<-inntaksmat INNTAK/LISTI>

Nota eftirfarandi inntak eda vidbot til ad kryfja innihald skraar. Haegt ad nota "-inntaksmat list" til ad sja lista yfir allar studdar vidbaetur. Sjalfgefin hegdun a tolinu er ad lata B<faersluskrar2timalina> reyna ad giska a skraarformid (thad er ad segja ad reyna allar vidbaeturnar thangad til ad einhverri tekst ad kryfja skranna).

=item B<-uppfaersla>

Athuga med nyjustu utgafu af B<faersluskra2timalina> og bera saman vid nuverandi utgafa (notad til ad athuga hvort thu sert keyrandi nyjustu utgafuna).

=item B<-velarnafn NAFN>

Skilgreina velarnafnid a velinni sem upplysingarnar koma fra.

=item B<-utgangur FORMAT>

Nota vidkomandi utgangssnid. Sjalfgefin hegdun hja <faersluskra2timalina> er ad nota CSV utgangssnid. Til ad sja lista yfir oll tiltaek snid skal nota "-utgangur list".

=item B<-smaatridi>

Sumar inntaksvidbaetur geta gefid fra ser talsvert itarleg skilabod um hvad se ad gerast, t.d. MFT, setupapi og prefetch. Thessar upplysingar geta verid full itarlegar og ordid til thess ad haegja a rannsokn og thvi er slokkt a theim sjalfgefid. Til ad fa thessar upplysingar inn i uttakid tharf thvi ad notast vid thennan valmoguleika. Thetta segir t.d MFT inntaksvidbotinni ad baeta vid $FN timastimplum, og Prefetch inntakinu ad setja inn nofn a reklum, o.s.frv.

=item B<-skrifa SKRAARNAFN>

Skilgreina skra til ad skrifa uttakid i (ef ekki tilgreint verdur prentad beint ut a skja, STDOUT).

=item B<-timabelti TIMABELTI>

Thessi valmoguleiki er til thess aetladur ad tilgreina hvada timabelti skrarnar a tolvunni sem er verid ad rannsaka voru vistadar i. Sjalfgefna valid a thessari breytu er ad notast vid timabeltid a tolvu thess sem er ad framkvaema rannsoknina. Til ad fa lista yfir oll studd timabelti skal notast vid "-timabelti list".

=item B<-Timabelti TIMABELTI>

Thennan valmoguleika er haegt ad nota til ad uttakid se birt med odru timabelti en thad sem er a tolvunni sem er verid ad rannsaka. Sjalfgefna valid a tolinu er ad nota sama timabelti i uttaki og er notad sem inntak (gildid a tolvunni/gognunum sem er verid ad skoda). Thad er thvi haegt ad nota thetta til ad fa uttakid allt birt t.d. med UTC timabeltinu, thratt fyrir ad gognin hafi verid vistud med odru timabelti.

=item B<-bradabirgda DIR>

Valmoguleiki til ad skilgreina bradabirgdamoppuna sem tolid notast vid. Sjalfgefin hegdun er ad notast vid styriskferfaskilgreinda bradabirgdamoppu, sem velin greinir eftir thvi hvada styrikerfi er notast vid. Hins vegar er haegt ad yfirskrifa tha hegdun med thessum valmoguleika.

T.d. ef velin er keyrd a Windows styrikerfinu tha er gerd tilraun til ad greina stadsetningu fyrir bradabirgdaskrar med adstod Win32::API (gaeti thvi klikkad a 64-bita kerfum). Annars er notast vid moppuna /tmp/ (aetti ad virka a ollum *NIX kerfum).

=item B<-faersluskra SKRAARNAFN>

Skilgreinir skra til ad skrifa allar villur og aflusunarskilabod fra B<faersluskra2timalina> i, ef ekki skilgreint er notast vid sjalfgefna villuuttakkid STDERR.

=item B<-utreikingur>

Ef thessi valmoguleiki er notadur er MD5 summa reiknud ut fyrir allar skrar og geymd med timastimpilshlutnum. Taka skal thad fram ad thetta virkar ekki vel i sumum inntaksvidbotum eins og MFT, sem setur MD5 summuna fyrir $MFT skranna i stad thess ad reikna hana ut fyrir hverja og eina skra sem er verid ad visa i.

=item B<-fljotkeyrsla>

Ef thessi valmoguleiki er notadur tha sleppir B<faersluskra2timalina> tho nokkrum profum til ad akvarda hvort ad skra se i raun veru kryfjanleg af inntaksvidbot. Tolid aetti ad keyra hradar en a moti kemur hugsanlega ad missa af nokkrum skram, thad er likurnar a folskum skilgreingum eykst.

=item B<-undanskilja LISTI>

Listi af skram eda slodum sem a ad undanskilja fra krufningu, skilgreindar med kommu. Ef ad tilgreind skra hefur ollid thvi ad tolid hrynur ead virkar ekki er haegt ad undanskilja thad fra keyrslunni og thar af leidandi ad na ad kryfja hugsanlega fleiri skrar.

=item B<-endurkvaema>

EF thessi valmoguleiki er notadur tha fer B<faersluskra2timalina> i endurkvaeman ham i stad thess ad kryfja einstaka skrar.

=item B<-forvinnsla>

Ef ad  B<faersluskra2timalina> er stillt i endurkvaeman ham (-endurkvaema) er moguleigt ad notast vid -forvinnsla valmoguleikann til ad lata tolid byrja a thvi ad forvinna drifid. Tha eru keyrdar forvinnsluvidbaetur sem safna saman upplysingum um drifid sem eru svo notadar a seinni stigum keyrslunnar.

=item B<-fjolordur> 

Baeta vid aflusunarupplysingum. Haegt ad notast vid moguleikann tvisvar sinnum, -fjolordur -fjolordur til ad fa enn frekari upplysingar.

=item B<-utgafa>

Birta utgafunumer tolsins.

=item B<-h|-hjalp|-?>

Birta thessa hjalp.

=back

Better description can be read in the man page of the program (man B<faersluskra2timalina>).

=head1  DESCRIPTION

Finally, finally we have an all Icelandic forensic command line utility that can be used to produce super timelines. And now to switch over to Icelandic:

B<faersluskra2timalina> er framendi a B<log2timeline>, tol til ad draga ut faerslur sem eru tengjanlegar vid timastimpla sem fyrirfinnast i ymsum skram vidsvegar um hin ymsu styrikerfi. Utgangur tolsins er skra sem inniheldur alla timastimpla sem hafa verid dregnir ut, sjalfgefin hegdun er ad vista tha i textaformi, en audbreytanlegt med uttaksvidbotum.

Tilgangur tolsins er sa sami og B<log2timeline>, serstaklega thar sem thetta er sama tolid, bara lengri skipanalina og erfidari notkun, en hun er a islensku, thvi ylhyra tungumali, tileinkad Benji, sem atti thann draum heitast ad geta notad alislenskt tol i sinum stafraenu rannsoknum.

=head1 AUTHOR

Kristinn Gudjonsson <kristinn (a t) log2timeline ( d o t ) net> is the original author of the program.

The tool is released under GPL so anyone can contribute to the tool.  Some parts of the code have been copied from other GPL'ed programs, such as the Parse::Evtx library by Andreas Schuster, and parts of RegRipper written by H. Carvey.

=head1 COPYRIGHT AND LICENSE

Copyright 2009-2012 by Kristinn Gudjonsson (kristinn ( a t ) log2timeline ( d o t ) net ) 

B<faersluskra2timalina> 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 3 of the License, or (at your option) any later version.

B<faersluskra2timalina> 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.

You should have received a copy of the GNU General Public License along with B<faersluskra2timalina>.  If not, see <http://www.gnu.org/licenses/>.

=head1 SEE ALSO

L<Log2Timeline>

=cut

