| #!/usr/bin/perl |
| |
| # ********************************************************** |
| # Copyright (c) 2006 VMware, Inc. All rights reserved. |
| # ********************************************************** |
| |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are met: |
| # |
| # * Redistributions of source code must retain the above copyright notice, |
| # this list of conditions and the following disclaimer. |
| # |
| # * Redistributions in binary form must reproduce the above copyright notice, |
| # this list of conditions and the following disclaimer in the documentation |
| # and/or other materials provided with the distribution. |
| # |
| # * Neither the name of VMware, Inc. nor the names of its contributors may be |
| # used to endorse or promote products derived from this software without |
| # specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| # ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE |
| # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
| # DAMAGE. |
| |
| ## bugtitle.pl |
| ## by Vladimir Kiriansky |
| ## August 2006 |
| ## |
| ## find odd processes and show description of all found |
| ########################################################################### |
| |
| ## Requires wget |
| |
| ## example use: |
| # just collect all links to select a few suspicious ones |
| # $ ./procdb.pl -s bug_8704/iexplore.exe.1608.00000000.xml |
| # ... |
| # wget -O - http://www.processlibrary.com/directory/files/wscntfy/ | grep -A 5 'Description:' |
| |
| # normal use: |
| # $ ./procdb.pl bug_8704/iexplore.exe.1608.00000000.xml > processes.out |
| # $ cat process.out |
| # .. |
| # <td width="390">regscan.exe is added by |
| # Trojan.W32.Rbot. It is a worm which attemps to spread via |
| # network shares. It also contains backdoor Trojan |
| # capabilities allowing unauthorised remote access to the |
| # infected computer. If found on your system make sure that |
| # you have downloaded the latest update for your antivirus |
| # application. This process is a security risk and should be |
| # removed from your system.<br> |
| |
| |
| # copy&paste from bugtitle.pl |
| |
| # FIXME: should merge with the logic from wld/wld.pl |
| # about having a whitelist database on DLLs |
| |
| |
| # adding only exe's that should be seen only once! |
| # so that we can detect a c:\temp\services.exe as rogue |
| |
| # FIXME: not yet used |
| %seen_known = (); |
| |
| # should add more entries from config/applications.html or even have a |
| # generator from config/application_data.h |
| %known_exe_description = { |
| 'lsass' => 'lsass', |
| 'services' => 'services'}; |
| |
| $tools = $ENV{'DYNAMORIO_TOOLS'}; |
| if ($tools eq "") { |
| # use same dir this script sits in |
| $tools = $0; |
| if ($tools =~ /[\\\/]/) { |
| $tools =~ s/^(.+)[\\\/][\w\.]+$/$1/; |
| $tools =~ s/\\/\\\\/g; |
| } else { |
| $tools = "./"; |
| } |
| # address_query needs DYNAMORIO_TOOLS set to find DRload.exe |
| $ENV{'DYNAMORIO_TOOLS'} = $tools; |
| } |
| |
| # parameters |
| $usage = "Usage: $0 [-v] [-q] [-glob] [-noglob] <forensic_file>\n"; |
| |
| $just_show = 0; |
| $verbose = 0; |
| $quiet = 0; |
| |
| $globall = 0; |
| $noglob = 0; |
| while ($#ARGV >= 0) { |
| if ($ARGV[0] eq '-v') { |
| $verbose = 1; |
| } elsif ($ARGV[0] eq '-q') { |
| $quiet = 1; |
| } elsif ($ARGV[0] eq '-s') { |
| $just_show = 1; |
| } elsif ($ARGV[0] eq '-glob') { |
| $globall = 1; |
| } elsif ($ARGV[0] eq '-noglob') { |
| $noglob = 1; |
| } elsif ($ARGV[0] =~ /^-/) { |
| die $usage; |
| } else { |
| # rest should be forensic file names |
| last; |
| } |
| shift; |
| } |
| |
| die $usage if ($#ARGV < 0); |
| $multiple = ($#ARGV > 0); |
| while ($#ARGV >= 0) { |
| my $filearg = $ARGV[0]; |
| # make it easy for users w/ non-globbing shell and non-globbing perl to |
| # pass *, w/o double-globbing and messing up escaped chars for other users |
| if (!$noglob && ($globall || $filearg =~ /\*/)) { |
| # FIXME: must convert from \ to / BEFORE the glob -- yet don't |
| # want to ruin escaped chars! It's a tradeoff: is \* a directory delimiter |
| # followed by metachar *, or is it an escaped * trying to be literal? |
| # In everyday usage we assume no escaped *'s! |
| # If we didn't care for \* directory delim we might do: |
| # $filearg =~ s|\\\\|//|g; # next rule won't get both slashes so need this rule |
| # $filearg =~ s|\\([\w\d])|/\1|g; # \ to / only if before a normal char |
| $filearg =~ s|\\|/|g; # assume \ is dir delim, no support for \ as escape char |
| @files = glob($filearg); |
| print "globbing: \"$filearg\" => \"@files\"\n" if ($verbose); |
| if ($#files < 0) { |
| # if glob comes up empty, don't use its results (to get error msg) |
| @files = ($filearg); |
| } |
| } else { |
| @files = ($filearg); |
| } |
| $multiple = $multiple || $#files > 0; |
| foreach $file (@files) { |
| print "processing \"$file\"\n" if ($verbose); |
| $file =~ s|\\|/|g; # normalize |
| unless (-f "$file") { |
| die "Error: No forensic file $file\n"; |
| } |
| if ($multiple) { |
| print "\n$file:\n"; |
| } |
| process_file($file); |
| } |
| shift; |
| } |
| |
| sub is_known_exe |
| { |
| my ($exe) = @_; |
| |
| return 0; |
| |
| return 0 unless exists $known_exe_description { $exe }; |
| |
| # known should be only once |
| if (defined $seen_known{ $exe } && |
| $seen_known{ $exe } == 1) { |
| # test with svchost.exe which may also be the Welchia worm |
| print "WARNING: second appearance of $exe\n"; |
| } |
| $seen_known{ $exe } = 1; |
| |
| return 1; |
| } |
| |
| sub get_external_data |
| { |
| # wget -q http://www.processlibrary.com/directory/files/defwatch -O - | grep -A 5 "Description:" |
| my ($exe) = @_; |
| |
| my $base = "http://www.processlibrary.com/directory/files/"; |
| my $url = "$base$exe/"; |
| my $wget = "wget -q -O - "; |
| my $postprocess = "grep -A 5 'Description:'"; |
| my $desc = ""; |
| |
| my $command = "$wget $url | $postprocess"; |
| |
| $desc = `$command` if (!$just_show); |
| print "$command \n" if ($just_show); |
| |
| # FIXME: note processlibrary tries to find a substring if they can't find an exact match |
| # so we have to verify that the process name they are returning is the one we really asked for |
| # for the time being leaving users to worry about it by being more verbose |
| return $desc; |
| } |
| |
| |
| # http://www.processlibrary.com/directory/files/rtvscan/index.html |
| |
| sub process_file($) { |
| my ($file) = @_; |
| $processing = 0; |
| |
| open(IN, "< $file") || die "Error: couldn't open $file\n"; |
| while (<IN>) { |
| # Handle CR |
| s/\r//; |
| |
| # Start of process list |
| if (/^<process-list> <!\[CDATA\[/) { |
| $processing = 1; |
| } |
| elsif (/]]> <\/process-list>/) { |
| $processing = 0; |
| } elsif ($processing) { |
| $skip = 0; |
| if (/^([^\s\<]+).exe$/i) { |
| $process=$1; |
| } else { |
| $process=$_; |
| chomp $process; |
| if ($process ne "System") { |
| print "not an EXE '$process!'\n"; |
| } else { |
| $skip = 1; |
| } |
| } |
| |
| if (!$skip) { |
| print "Querying '$process'\n" if ($verbose); |
| $skip = is_known_exe($exe); |
| } |
| |
| if (!$skip) { |
| print "Querying Externally '$process'\n"; |
| print &get_external_data($process), "\n"; |
| } |
| } |
| } |
| close(IN); |
| } |
| |
| sub unixpath2win32($) { |
| my ($p) = @_; |
| # use cygpath if available, it will convert /home to c:\cygwin\home, etc. |
| $cp = `cygpath -wi \"$p\"`; |
| chomp $cp; |
| if ($cp eq "") { |
| # do it by hand |
| # add support for /x => x: |
| $p =~ s|^/([a-z])/|$1:/|; |
| # forward slash becomes backslash since going through another shell |
| $p =~ s|/|\\|g; |
| } else { |
| $p = $cp; |
| } |
| # make single backslashes doubles |
| $p =~ s|\\{1}|\\\\|g; |
| return $p; |
| } |