9 Feb 2015

Logs de eventos en Windows 7

En Windows 7 el número de logs de eventos, que podemos encontrar en la carpeta c:\Windows\System32\ winevt\Logs, se ha disparado en relación a lo que encontrábamos en Windows XP.

Estos eventos son una fuente de información imprescindible cuando investigamos tanto acciones de un usuario como acciones llevadas a cabo por malware.

Para poder trabajar cómodamente con ellos he recurrido a varias herramientas ajenas al S.O. pero con el tiempo y el uso he encontrado problemas siempre: o bien a veces no extraían toda la información que contenían los logs o bien problemas relacionados con la conversión de la fecha-hora.

Así que al final he optado por usar la propia herramienta de Windows wevtutil.exe junto con un par de transformaciones para hacer manejable la salida.

El primer problema es el de extraer los logs del equipo. Para no perder información de fuentes de logs que sean específicas del equipo hay que realizar su tratamiento en la misma antes de llevárnoslos.

Para ello primero extraigo los logs, los convierto a texto y los almaceno con toda la información de sus fuentes para poder reabrirlos en otra máquina con toda su información aunque no tenga esas fuentes. El formato de texto lo he elegido porque me parece el más equilibrado en cuanto a información y facilidad de proceso. En cualquier caso siempre dispondré de los logs almacenados si necesitara profundizar en alguno en concreto.

La mejor herramienta para esto es wevtutil.exe. En algún lugar he visto que cuando realizan la copia de los logs eliminan los que tienen el tamaño de 69.632 bytes porque están vacíos y esto es un error. La inmensa mayoría de ellos es cierto que no contienen nada útil pero hay algunos que si, por lo que hasta no realizar su tratamiento es mejor no borrar nada. Aparte de eso hay que efectuar algún renombrado porque los nombres de los logs son un poco "especiales".

El bat que ejecuto es:

REM Captura todos los EventLogs y los almacena y vuelca a texto
@echo off
mkdir .\LogFiles
pushd .\LogFiles
FOR /F "tokens=1,2 delims=%%4." %%a IN ('dir /b c:\windows\system32\winevt\Logs') DO (
IF [%%b] == [] (
wevtutil.exe epl "%%a" "%%a".evtx
)
IF %%b == evtx (
wevtutil.exe epl "%%a" "%%a".evtx
) ELSE (
wevtutil.exe epl "%%a/%%b" "%%a_%%b".evtx
)
)
for /R %%G IN (*.evtx) DO (
REM Opcional: Sacar la información a texto
wevtutil.exe qe "%%G" /f:text /lf:true > "%%~nxG".txt
REM y almacenando
wevtutil.exe al "%%G"
)
echo on
popd

Una vez extraído el contenido de los logs tenemos una colección de información del tipo:

Event[]:
  Log Name:
  Source:
  Date:
  Event ID:
  Task:
  Level:
  Opcode:
  Keyword:
  User:
  User Name:
  Computer:
  Description:


Esto en principio no es muy manejable por lo que para poder incorporarlo a un timeline le aplico el siguiente programa escrito en perl:

use warnings;
use strict;
open(ALL, '>:encoding(cp1252)',"AllEventLogs-LocalT.csv");
while (<STDIN>) {
chomp;
my $file = $_;
my $tmpFile = $file.".tmp";
my $tsvFile = $file.".tsv";
my $csvFile = $file."-LocalT.csv";
open(OUT, '>:encoding(cp1252)',"$tmpFile");
open(F, '<:encoding(cp1252)', $file) or die "Can't read file '$file' [$!]\n";
while (<F>) {
 my $linea = $_;
 $linea =~ s/\r|\n|\t//g;
 $linea =~ s/"/'/g;
 $linea =~ s/Event\[.*\]:/\n/g;
 print OUT $linea
}
close(F);
close(OUT);
open(OUT, '>:encoding(cp1252)',$tsvFile);
open(F, '<:encoding(cp1252)', $tmpFile) or die "Can't read file '$file' [$!]\n";
while (<F>) {
 my $linea = $_;
 $linea =~ s/\s{2}Log Name:\s//g;
 $linea =~ s/\s{2}Source:\s/\t/g;
 $linea =~ s/\s{2}Date:\s/\t/g;
 $linea =~ s/\s{2}Event ID:\s/\t/g;
 $linea =~ s/\s{2}Task:\s/\t/g;
 $linea =~ s/\s{2}Level:\s/\t/g;
 $linea =~ s/\s{2}Opcode:\s/\t/g;
 $linea =~ s/\s{2}Keyword:\s/\t/g;
 $linea =~ s/\s{2}User:\s/\t/g;
 $linea =~ s/\s{2}User Name:\s/\t/g;
 $linea =~ s/\s{2}Computer:\s/\t/g;
 $linea =~ s/\s{2}Description:\s/\t/g;
 print OUT $linea
}
close(F);
close(OUT);
unlink ($tmpFile);
open(OUT, '>:encoding(cp1252)',$csvFile);
open(F, '<:encoding(cp1252)', $tsvFile);
while (<F>) {
 next if $_ =~ /^$/;
 my @fields = split(/\t/, $_);
 my @custDateTime = split(/T/, $fields[2]);
 $custDateTime[0] =~ s/^(\d{4})-(\d{2})-(\d{2})/$2\/$3\/$1/g;
 $fields[11] =~ s/\r|\n//g;
 my $salida = join(",",$custDateTime[0],$custDateTime[1],"Local","MACB","EVTX",$fields[1]."[".$fields[0]."]",$fields[5],$fields[9].":".$fields[8],$fields[10],"EventID: ".$fields[3],'"'.$fields[4]."-".$fields[11]."-".$fields[6]."Keyword:".$fields[7].'"',"-","-","-","-","-","-");
 print OUT $salida."\n";
 print ALL $salida."\n";
}
close(F);
close(OUT);
unlink ($tsvFile);
}
close(ALL);



Y como último paso transformo los valores fecha-hora, que están en modo local, a UTC y le agrego las cabeceras del formato log2timeline "date, time, timezone, MACB, source, sourcetype, type, user, host, short, desc, version, filename, inode, notes, format, extra" usando el siempre útil Logparser:

logparser "SELECT Field1 as date,STRCAT(TO_STRING(TO_TIME(TO_UTCTIME(TO_TIMESTAMP(ADD(Field1,Field2), 'MM/dd/yyyyHH:mm:ss.ll'))),'HH:mm:ss'),STRCAT('.',EXTRACT_SUFFIX(Field2,0,'.'))) as time,REPLACE_STR(Field3,'Local','GMT') as timezone,Field4 as MACB,Field5 as source,Field6 as sourcetype,Field7 as type,Field8 as user,Field9 as host,Field10 as short,Field11 as desc,Field12 as version,Field13 as filename,Field14 as inode,Field15 as notes,Field16 as format,Field17 as extra INTO AllEventLogs-GMT.csv FROM AllEventLogs-LocalT.csv" -i:csv -o:csv -headerRow:OFF

A pesar de todo el embrollo en unos segundos tenemos todos los logs en formato log2timeline y perfectamente empaquetados con toda la información específica de las fuentes para poder reabrirlos en cualquier otro equipo.