# Suspicious # Copyright (C) 2008 Jesse Kornblum # # This program 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 2 of the License, or (at # your option) any later version. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # """ @author: Jesse Kornblum @license: GNU General Public License 2.0 or later @contact: research@jessekornblum.com @organization: """ from forensics.object2 import * from forensics.object import * from vutils import * from forensics.win32.tasks import * UNKNOWN_CMD = "(unknown)" def command_line_suspicious(command_line): if command_line is None: return False if command_line == UNKNOWN_CMD: return False # We want to display TrueCrypt command lines because they sometimes # include the volume name being mounted. If you combine the name # of the volume with the passphrase from cryptoscan, you should # be able to access the protected volume. if "TrueCrypt" in command_line: print "Found possible TrueCrypt process. Command line: " return True # Command lines that begin with a lowercase drive letter have # usually been typed by the user. Although not *always* suspicious, # they are worthy of futher examination if command_line[0].islower() and command_line[1] == ':': print "Command line begins with lowercase drive letter: " return True return False class suspicious(forensics.commands.command): # Declare meta information associated with this plugin meta_info = forensics.commands.command.meta_info meta_info['author'] = 'Jesse Kornblum' meta_info['copyright'] = 'Copyright (C) 2008 Jesse Kornblum' meta_info['contact'] = 'research@jessekornblum.com' meta_info['license'] = 'GNU General Public License 2.0 or later' meta_info['url'] = 'http://jessekornblum.com/' meta_info['os'] = 'WIN_32_XP_SP2' meta_info['version'] = '1.0' # This module makes use of the standard parser. Thus it is not # necessary to override the forensics.commands.command.parser() method. # The standard parser provides the following command line options: # '-f', '--file', '(required) Image file' # '-b', '--base', '(optional) Physical offset (in hex) of DTB' # '-t', '--type', '(optional) Identify the image type' # We need to override the forensics.commands.command.help() method to # change the user help message. This function returns a string that # will be displayed when a user lists available plugins. def help(self): return "Find suspicious command lines and display them" # Finally we override the forensics.commands.command.execute() method # which provides the plugins core functionality. Command line options # are accessed as attributes of self.opts. For example, the options # provided by the standard parse would would provide the following # attributes: self.opts.filename, self.opts.base, self.opts.type. def execute(self): theProfile = Profile() (addr_space, symtab, types) = load_and_identify_image(self.op, \ self.opts) all_tasks = process_list(addr_space,types,symtab) for task in all_tasks: if not addr_space.is_valid_address(task): continue eprocess = Object('_EPROCESS', task, addr_space, None, theProfile) command_line = eprocess.CommandLine if command_line_suspicious(command_line): print command_line class _EPROCESS(Object): """Class representing an _EPROCESS. Adds the following special behavior: * Uses self.Pcb.DirectoryTableBase to re-calculate its address space. * Presents ImageFileName as a Python string rather than an array of unsigned chars. * Uses self.Peb.ProcessParameters to find the command line used to start the process """ hasMembers = True name = "EPROCESS" def __new__(typ, *args, **kwargs): obj = object.__new__(typ) return obj def __init__(self, name, address, space, parent=None,profile=None): super(_EPROCESS,self).__init__(name, address, space,parent,profile) self.new_dtb = self.Pcb.DirectoryTableBase[0] self.vm = create_addr_space(self.vm, self.new_dtb) # Custom attributes def getImageFileName(self): return read_null_string(self.vm, types, ['_EPROCESS', 'ImageFileName'], self.offset) ImageFileName = property(fget=getImageFileName) def getCreateTime(self): return process_create_time(self.vm, types, self.offset) CreateTime = property(fget=getCreateTime) def getCommandLine(self): if self.Peb.offset == 0: return UNKNOWN_CMD mypeb = Object('_PEB', self.Peb.offset, self.vm, self, self.profile) if mypeb.ProcessParameters is None: return UNKNOWN_CMD cmdline = read_unicode_string(self.vm, types, ['_RTL_USER_PROCESS_PARAMETERS', 'CommandLine'], mypeb.ProcessParameters.offset) if cmdline is None: return UNKNOWN_CMD return cmdline CommandLine = property(fget=getCommandLine)