Wednesday, 15 August 2012

Java Forensics using TLN Timelines

Based on my last two previous posts I thought it might be a good time to see how we can introduce some of the Java artifacts we've reviewed. I decided to create a perl script to parse .idx files within the Java cache into TLN format for import into our timelines. I hope that this script will be able to provide analysts with greater context to their investigations and also have a quick way to eyeball URLs within the idx files for anything that could be potentially malicious. Its important to note that again this script is in BETA and further testing is required before you should trust the results within your own investigations.

I had a strong response from my last post on TLN and browser forensics however a number of users did have issues when copying the code and attempting to run with errors such as "Can't find string terminator "EOT" anywhere before EOF at C:\idx.pl line 31". If you get this error its most likely you need to remove the two spaces after EOT and one space before EOT at the very end of the file. I'm also in the process of organising a Google code repository and hopefully this will resolve that issue.

In saying that lets take a look at the script.


 #! c:\perl\bin\perl.exe  
 #---------------------------------------------------------------------  
 # idx.pl   
 # Parse .idx files with the Java cache to TLN format  
 #   
 #   
 # Version: 0.1 (BETA)   
 # Examples:   
 # 1335156604|JAVA|WORKSTATIONNAME|USERNAME|http://malicious_site.com.br/js/jar//fap4.jar?r=1051139  
 # 1347043129|JAVA|WORKSTATIONNAME|USERNAME|http://www.malicious_site.pro/P4fLBitJ-PxK2/yUA83mE  
 # 1347043127|JAVA|WORKSTATIONNAME|USERNAME|http://www.malicious_site.pro/SfLBitJ-PxK2/yUA83mE  
 #---------------------------------------------------------------------  
 use DBI;  
 use strict;  
 use Getopt::Long;  
 use File::Find;  
 use Regexp::Common qw /URI/;  
 use Time::Local;  
 my %config = ();  
 Getopt::Long::Configure("prefix_pattern=(-|\/)");  
 GetOptions(\%config, qw(path|p=s system|s=s user|u=s help|?|h));  
 if ($config{help} || ! %config) {  
     _syntax();  
     exit 1;  
 }  
 die "You must enter a path.\n" unless ($config{path});  
 #die "File not found.\n" unless (-e $config{path} && -f $config{path});  
 my $path =$config{path};  
 my @files;  
 my $line = $_;  
 my %months = ('Jan'=>'01','Feb'=>'02','Mar'=>'03','Apr'=>'04','May'=>'05','Jun'=>'06','Jul'=>'07','Aug'=>'08','Sep'=>'09','Oct'=>'10','Nov'=>'11','Dec'=>'12');  
 my $start_dir = $path;  
 find(  
   sub { push @files, $File::Find::name unless -d; },  
   $start_dir  
 );  
 for my $file (@files) {  
   my ($ext) = $file =~ /(\.[^.]+)$/;  
   if ($ext eq ".idx") {  
             $file =~ s/\\/\//g;  
             open( FILE, "< $file" ) or die "Can't open $file : $!";  
             $line=<FILE>;  
             if ($line){  
                 my @timestamps = $line =~ m/[0-3][0-9] [a-zA-Z][a-z][a-z] [0-9][0-9][0-9][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]/g;   
                 my @url = $line =~ m/($RE{URI}{HTTP}{-scheme => qr(https?)})/g;   
                 $timestamps[1] = getEpoch($timestamps[1]);  
                 print $timestamps[1]."|JAVA|".$config{system}."|".$config{user}."|".$url[0]."\n";  
             }  
             close(FILE);  
     }  
 }  
 sub getEpoch {  
     my $time = substr ( $_[0],index($_[0], ' ', 10)+1,length($_[0])-1);  
     my $date = substr ( $_[0],0,index($_[0], ' ', 10));  
     my ($hr,$min,$sec) = split(/:/,$time,3);  
     my ($dd,$mm,$yyyy) = split(/ /,$date,3);  
     $mm = $months{$mm};  
     $mm =~ s/^0//;  
     my $epoch = timegm($sec,$min,$hr, $dd,($mm)-1,$yyyy);  
     return $epoch;  
 }  
 sub _syntax {  
 print<< "EOT";  
 idx.pl  
 [option]  
 Parse Java cache IDX files (  
  -p Path..................path to java cache  
  -s Systemname............add systemname to appropriate field in tln file  
  -u user..................add user (or SID) to appropriate field in tln file  
  -h ......................Help (print this information)  
 Ex: C:\\> idx.pl -p C:\\Documents and Settings\\userprofile\\Application Data\\Sun\\Java\\Deployment\\cache\\\ -s %COMPUTERNAME% -u %USERNAME% > events.txt  
 **All times printed as GMT/UTC  
 copyright 2012 Sploit  
 EOT  
 }  

I'm not a programmer by any means so I do my best with my coding but if anybody has any views on some improvements for performance or bugs then let me know. I'm not sure whether its possible to have an IDX file without any of the values i'm looking for so potentially if you have any idx files that don't have a date listed within them then my script will most likely fail. I've also added in some examples of what the output looks like within the script but I'll list them here also to highlight some examples.


  # 1335156604|JAVA|WORKSTATIONNAME|USERNAME|http://malicious_site.com.br/js/jar//fap4.jar?r=1051139   
  # 1347043129|JAVA|WORKSTATIONNAME|USERNAME|http://www.malicious_site.pro/P4fLBitJ-PxK2/yUA83mE   
  # 1347043127|JAVA|WORKSTATIONNAME|USERNAME|http://www.malicious_site.pro/SfLBitJ-PxK2/yUA83mE   

Also to note in regards to IDX files there are typically two timestamps within an IDX file. One is listed as date and one is listed as last modified. In this instance I'm using the "date" to produce the TLN value as from what I've seen this seems to be the time the incident occurred.

Let me know if you find this script of value and if you find any bugs. As mentioned I'll hopefully upload the script to my own Google Code repository shortly and I'll let you all know when that is available in case you're having any troubles getting it to work for you.




3 comments:

  1. You need to slurp in the IDX files. I noticed some get truncated when reading the files in. I also uc the extension to ensure case problems don't cause them to get skipped.

    Here's my small update:

    if ( uc($ext) eq ".IDX" ) {
    my $fh;
    my $line = do {
    local $/ = undef;
    open $fh, "<", $file
    or die "could not open $file: $!";
    <$fh>;
    };
    if ($line) { #...

    ReplyDelete
  2. Many thanks for the comments its great to get some feedback. I had noticed this issue also after some initial testing and had added the following lines to the last files

    while(){
    $data .= $_;
    }
    I'll double check that my code achieves what yours does above, yours looks more efficient. I'll definitely incorporate the changes in regards to case problems.

    You'll find my updated files at http://code.google.com/p/sploited/ when i release the changes.

    ReplyDelete
  3. I know I'm a bit late to the party, but I just wrote up some Perl code for parsing the Java cache .idx files. Looking at your idx.pl on the Google Code site, we just took different approaches.

    I'm glad to see others doing this sort of thing...

    ReplyDelete