예제 #1
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        # Currently we only support x86. The x64 does still have a IDT
        # but hooking is prohibited and results in bugcheck.
        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in modules.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())

        for kpcr in tasks.get_kdbg(addr_space).kpcrs():
            # Get the GDT for access to selector bases
            gdt = dict((i * 8, sd) for i, sd in kpcr.gdt_entries())
            for i, entry in kpcr.idt_entries():
                # Where the IDT entry points.
                addr = entry.Address
                # Per MITRE, add the GDT selector  base if available.
                # This allows us to detect sneaky attempts to hook IDT
                # entries by changing the entry's GDT selector.
                gdt_entry = gdt.get(entry.Selector.v())
                if gdt_entry != None and "Code" in gdt_entry.Type:
                    addr += gdt_entry.Base

                # Lookup the function's owner
                module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(addr))

                yield i, entry, addr, module
예제 #2
0
    def calculate(self):

        if not has_yara:
            debug.error(
                "Please install Yara from https://plusvic.github.io/yara/")

        addr_space = utils.load_as(self._config)

        rules = self._compile_rules()

        if self._config.KERNEL:

            # Find KDBG so we know where kernel memory begins. Do not assume
            # the starting range is 0x80000000 because we may be dealing with
            # an image with the /3GB boot switch.
            kdbg = tasks.get_kdbg(addr_space)

            start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

            # Modules so we can map addresses to owners
            mods = dict((addr_space.address_mask(mod.DllBase), mod)
                        for mod in modules.lsmod(addr_space))
            mod_addrs = sorted(mods.keys())

            # There are multiple views (GUI sessions) of kernel memory.
            # Since we're scanning virtual memory and not physical,
            # all sessions must be scanned for full coverage. This
            # really only has a positive effect if the data you're
            # searching for is in GUI memory.
            sessions = []

            for proc in tasks.pslist(addr_space):
                sid = proc.SessionId
                # Skip sessions we've already seen
                if sid == None or sid in sessions:
                    continue

                session_space = proc.get_process_address_space()
                if session_space == None:
                    continue

                sessions.append(sid)
                scanner = DiscontigYaraScanner(address_space=session_space,
                                               rules=rules)

                for hit, address in scanner.scan(start_offset=start):
                    module = tasks.find_module(
                        mods, mod_addrs, addr_space.address_mask(address))
                    yield (module, address, hit,
                           session_space.zread(address - self._config.REVERSE,
                                               self._config.SIZE))

        else:
            for task in self.filter_tasks(tasks.pslist(addr_space)):
                scanner = VadYaraScanner(task=task, rules=rules)
                for hit, address in scanner.scan():
                    yield (task, address, hit,
                           scanner.address_space.zread(
                               address - self._config.REVERSE,
                               self._config.SIZE))
예제 #3
0
    def generate_suggestions(self):
        """The nt!PoolBigPageTable and nt!PoolBigPageTableSize
        are found relative to nt!PoolTrackTable"""

        track_table = tasks.get_kdbg(self.obj_vm).PoolTrackTable

        for pair in self.distance:
            table_base = obj.Object("address", 
                offset = track_table - pair[0], 
                vm = self.obj_vm)

            table_size = obj.Object("address", 
                offset = track_table - pair[1], 
                vm = self.obj_vm)
                
            if (table_base % 0x1000 == 0 and
                    self.obj_vm.is_valid_address(table_base) and
                    table_size != 0 and 
                    table_size % 0x1000 == 0 and 
                    table_size < 0x1000000):
                break

        debug.debug("Distance Map: {0}".format(repr(self.distance)))
        debug.debug("PoolTrackTable: {0:#x}".format(track_table))
        debug.debug("PoolBigPageTable: {0:#x} => {1:#x}".format(table_base.obj_offset, table_base))
        debug.debug("PoolBigPageTableSize: {0:#x} => {1:#x}".format(table_size.obj_offset, table_size))
        yield table_base, table_size
예제 #4
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        # Currently we only support x86. The x64 does still have a IDT
        # but hooking is prohibited and results in bugcheck.
        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        mods = dict((addr_space.address_mask(mod.DllBase), mod)
                    for mod in modules.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())

        for kpcr in tasks.get_kdbg(addr_space).kpcrs():
            # Get the GDT for access to selector bases
            gdt = dict((i * 8, sd) for i, sd in kpcr.gdt_entries())
            for i, entry in kpcr.idt_entries():
                # Where the IDT entry points.
                addr = entry.Address
                # Per MITRE, add the GDT selector  base if available.
                # This allows us to detect sneaky attempts to hook IDT
                # entries by changing the entry's GDT selector.
                gdt_entry = gdt.get(entry.Selector.v())
                if gdt_entry != None and "Code" in gdt_entry.Type:
                    addr += gdt_entry.Base

                # Lookup the function's owner
                module = tasks.find_module(mods, mod_addrs,
                                           addr_space.address_mask(addr))

                yield i, entry, addr, module
예제 #5
0
    def generate_suggestions(self):
        """The nt!PoolBigPageTable and nt!PoolBigPageTableSize
        are found relative to nt!PoolTrackTable"""

        track_table = tasks.get_kdbg(self.obj_vm).PoolTrackTable

        for pair in self.distance:
            table_base = obj.Object("address",
                                    offset=track_table - pair[0],
                                    vm=self.obj_vm)

            table_size = obj.Object("address",
                                    offset=track_table - pair[1],
                                    vm=self.obj_vm)

            if (table_base % 0x1000 == 0
                    and self.obj_vm.is_valid_address(table_base)
                    and table_size != 0 and table_size % 0x1000 == 0
                    and table_size < 0x1000000):
                break

        debug.debug("Distance Map: {0}".format(repr(self.distance)))
        debug.debug("PoolTrackTable: {0:#x}".format(track_table))
        debug.debug("PoolBigPageTable: {0:#x} => {1:#x}".format(
            table_base.obj_offset, table_base))
        debug.debug("PoolBigPageTableSize: {0:#x} => {1:#x}".format(
            table_size.obj_offset, table_size))
        yield table_base, table_size
예제 #6
0
    def calculate(self):
        kernel_space = utils.load_as(self._config)

        if not self.is_valid_profile(kernel_space.profile):
            debug.error("Windows XP/2003 does not track pool tags")

        knowntags = {}
        if self._config.TAGFILE and os.path.isfile(self._config.TAGFILE):
            taglines = open(self._config.TAGFILE).readlines()
            for tag in taglines:
                tag = tag.strip()
                if tag.startswith("rem") or tag.startswith(" ") or tag == "":
                    continue
                info = tag.split("-", 2)
                try:
                    key = info[0].strip()
                    driver = info[1].strip()
                    reason = info[2].strip()
                except IndexError:
                    continue
                knowntags[key] = (driver, reason)

        track_table = tasks.get_kdbg(kernel_space).PoolTrackTable

        # not really an address, this is just a trick to get
        # a 32bit number on x86 and 64bit number on x64. the
        # size is always directly before the pool table.
        table_size = obj.Object("address",
                                offset=track_table -
                                kernel_space.profile.get_obj_size("address"),
                                vm=kernel_space)

        track_table = track_table.dereference_as("address")

        entries = obj.Object("Array",
                             targetType="_POOL_TRACKER_TABLE",
                             offset=track_table,
                             count=table_size,
                             vm=kernel_space)

        if self._config.TAGS:
            tags = [tag for tag in self._config.TAGS.split(",")]
        else:
            tags = []

        for entry in entries:

            if not self._config.SHOW_FREE:
                if entry.PagedBytes == 0 and entry.NonPagedBytes == 0:
                    continue

            if not tags or entry.Key in tags:
                try:
                    (driver, reason) = knowntags[str(entry.Key).strip()]
                    if self._config.WHITELIST:
                        continue
                except KeyError:
                    (driver, reason) = ("", "")
                yield entry, driver, reason
예제 #7
0
  def __init__(self, config, *args, **kwargs):
    commands.Command.__init__(self, config, *args, **kwargs)
    config.add_option("BUILD_SYMBOLS", default = False, action = 'store_true', cache_invalidator = False, help = "Build symbol table information")
    config.add_option("USE_SYMBOLS", default = False, action = 'store_true', cache_invalidator = False, help = "Use symbol servers to resolve process addresses to module names")

    self.kdbg = tasks.get_kdbg(utils.load_as(config))
    self.build_symbols = getattr(config, 'BUILD_SYMBOLS', False)
    self.use_symbols = getattr(config, 'USE_SYMBOLS', False)
예제 #8
0
    def calculate(self):
        kernel_space = utils.load_as(self._config)

        if not self.is_valid_profile(kernel_space.profile):
            debug.error("Windows XP/2003 does not track pool tags")

        knowntags = {}
        if self._config.TAGFILE and os.path.isfile(self._config.TAGFILE):
            taglines = open(self._config.TAGFILE).readlines()
            for tag in taglines:
                tag = tag.strip()
                if tag.startswith("rem") or tag.startswith(" ") or tag == "":
                    continue
                info = tag.split("-", 2)
                try:
                    key = info[0].strip()
                    driver = info[1].strip()
                    reason = info[2].strip()
                except IndexError:
                    continue
                knowntags[key] = (driver, reason)

        track_table = tasks.get_kdbg(kernel_space).PoolTrackTable

        # not really an address, this is just a trick to get 
        # a 32bit number on x86 and 64bit number on x64. the
        # size is always directly before the pool table. 
        table_size = obj.Object("address", offset = 
            track_table - kernel_space.profile.get_obj_size("address"), 
            vm = kernel_space
            )

        track_table = track_table.dereference_as("address")

        entries = obj.Object("Array", targetType = "_POOL_TRACKER_TABLE", 
            offset = track_table, count = table_size, 
            vm = kernel_space
            )

        if self._config.TAGS:
            tags = [tag for tag in self._config.TAGS.split(",")]
        else:
            tags = []

        for entry in entries:

            if not self._config.SHOW_FREE:
                if entry.PagedBytes == 0 and entry.NonPagedBytes == 0:
                    continue

            if not tags or entry.Key in tags:
                try:
                    (driver, reason) = knowntags[str(entry.Key).strip()]
                    if self._config.WHITELIST:
                        continue
                except KeyError:
                    (driver, reason) = ("", "")
                yield entry, driver, reason
예제 #9
0
    def calculate(self):

        if not has_pydeep:
            debug.error(
                "Please install ssdeep and pydeep from http://ssdeep.sourceforge.net/ and https://github.com/kbandla/pydeep"
            )

        addr_space = utils.load_as(self._config)
        self._addr_space = addr_space

        page_sig = self._pydeep_page()
        if page_sig == None:
            debug.error("Pydeep was not able to hash the input")

        if self._config.KERNEL:

            # Find KDBG so we know where kernel memory begins. Do not assume
            # the starting range is 0x80000000 because we may be dealing with
            # an image with the /3GB boot switch.
            kdbg = tasks.get_kdbg(addr_space)

            start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

            # Modules so we can map addresses to owners
            mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in modules.lsmod(addr_space))
            mod_addrs = sorted(mods.keys())

            # There are multiple views (GUI sessions) of kernel memory.
            # Since we're scanning virtual memory and not physical,
            # all sessions must be scanned for full coverage. This
            # really only has a positive effect if the data you're
            # searching for is in GUI memory.
            sessions = []

            for proc in tasks.pslist(addr_space):
                sid = proc.SessionId
                # Skip sessions we've already seen
                if sid == None or sid in sessions:
                    continue

                session_space = proc.get_process_address_space()
                if session_space == None:
                    continue

                sessions.append(sid)
                scanner = DiscontigSSDeepScanner(address_space=session_space, rules=rules)

                for hit, address in scanner.scan(start_offset=start):
                    module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(address))
                    yield (module, address, hit, session_space.zread(address - self._config.REVERSE, self._config.SIZE))

        else:
            for task in self.filter_tasks(tasks.pslist(addr_space)):
                scanner = VadSSDeepScanner(task=task, pydeep_hash=page_sig)
                for sig, vStart, vLength, offset, alike in scanner.scan():
                    yield (task, sig, vStart, vLength, offset, alike, scanner.address_space.zread(offset, 0x1000))
예제 #10
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        # Currently we only support x86. The x64 does still have a GDT
        # but hooking is prohibited and results in bugcheck.
        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        for kpcr in tasks.get_kdbg(addr_space).kpcrs():
            for i, entry in kpcr.gdt_entries():
                yield i, entry
예제 #11
0
파일: idt.py 프로젝트: Jack47/volatility
    def calculate(self):
        addr_space = utils.load_as(self._config)

        # Currently we only support x86. The x64 does still have a GDT 
        # but hooking is prohibited and results in bugcheck. 
        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        for kpcr in tasks.get_kdbg(addr_space).kpcrs():
            for i, entry in kpcr.gdt_entries():
                yield i, entry
예제 #12
0
파일: malfind.py 프로젝트: Austi/volatility
    def calculate(self):

        if not has_yara:
            debug.error("Please install Yara from code.google.com/p/yara-project")

        addr_space = utils.load_as(self._config)

        rules = self._compile_rules()

        if self._config.KERNEL:

            # Find KDBG so we know where kernel memory begins. Do not assume
            # the starting range is 0x80000000 because we may be dealing with
            # an image with the /3GB boot switch. 
            kdbg = tasks.get_kdbg(addr_space)

            start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

            # Modules so we can map addresses to owners
            mods = dict((addr_space.address_mask(mod.DllBase), mod)
                        for mod in modules.lsmod(addr_space))
            mod_addrs = sorted(mods.keys())

            # There are multiple views (GUI sessions) of kernel memory.
            # Since we're scanning virtual memory and not physical, 
            # all sessions must be scanned for full coverage. This 
            # really only has a positive effect if the data you're
            # searching for is in GUI memory. 
            sessions = []

            for proc in tasks.pslist(addr_space):
                sid = proc.SessionId
                # Skip sessions we've already seen 
                if sid == None or sid in sessions:
                    continue

                session_space = proc.get_process_address_space()
                if session_space == None:
                    continue

                sessions.append(sid)
                scanner = DiscontigYaraScanner(address_space = session_space,
                                               rules = rules)

                for hit, address in scanner.scan(start_offset = start):
                    module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(address))
                    yield (module, address, hit, session_space.zread(address, 1024))

        else:
            for task in self.filter_tasks(tasks.pslist(addr_space)):
                scanner = VadYaraScanner(task = task, rules = rules)
                for hit, address in scanner.scan():
                    yield (task, address, hit, scanner.address_space.zread(address, 1024))
예제 #13
0
    def get_bugcheck_callbacks(self):
        """
        Enumerate generic Bugcheck callbacks.

        Note: These structures don't exist in tagged pools, but you can find 
        them via KDDEBUGGER_DATA64 on all versions of Windows.
        """

        kbcclh = tasks.get_kdbg(self.kern_space).KeBugCheckCallbackListHead.dereference_as('_KBUGCHECK_CALLBACK_RECORD')

        for l in kbcclh.Entry.list_of_type("_KBUGCHECK_CALLBACK_RECORD", "Entry"):
            yield "KeBugCheckCallbackListHead", l.CallbackRoutine, l.Component.dereference()
예제 #14
0
def lsmod(addr_space):
    """ A Generator for modules (uses _KPCR symbols) """
    ## Locate the kpcr struct - either hard coded or specified by the command line

    PsLoadedModuleList = tasks.get_kdbg(addr_space).PsLoadedModuleList

    if PsLoadedModuleList.is_valid():
        ## Try to iterate over the process list in PsActiveProcessHead
        ## (its really a pointer to a _LIST_ENTRY)
        for l in PsLoadedModuleList.dereference_as("_LIST_ENTRY").list_of_type(
            "_LDR_DATA_TABLE_ENTRY", "InLoadOrderLinks"):
            yield l
예제 #15
0
def get_thread_modules(thread, config):
    # get the loaded modules of the process containing the thread
    # this function also pays respect to already gathered modules
    # for increased performance

    global kernel_modules
    global enumerated_processes

    thread_modules = []
    user_modules = []

    addr_space = utils.load_as(config)
    system_range = tasks.get_kdbg(
        addr_space).MmSystemRangeStart.dereference_as("Pointer")

    if len(kernel_modules) == 0:
        for mod in modules.lsmod(addr_space):
            if mod:
                thread_modules.append(ThreadModule(mod))
                thread_modules[-1].functions = get_module_exports(
                    thread, thread_modules[-1].ldr_object)
                thread_modules[-1].functions = sorted(
                    thread_modules[-1].functions,
                    key=lambda item: item.address)
        thread_modules = sorted(thread_modules,
                                key=lambda item: item.ldr_object.DllBase)
        kernel_modules = thread_modules
    else:
        pass

    owning_process = thread.owning_process()
    if not owning_process.is_valid():
        owner = None
    else:
        try:
            user_modules = enumerated_processes[owning_process.obj_offset]
        except KeyError:
            for mod in owning_process.get_load_modules():
                if mod:
                    user_modules.append(ThreadModule(mod))
                    user_modules[-1].functions = get_module_exports(
                        thread, user_modules[-1].ldr_object)
                    user_modules[-1].functions = sorted(
                        user_modules[-1].functions,
                        key=lambda item: item.address)
            user_modules = sorted(user_modules,
                                  key=lambda item: item.ldr_object.DllBase)
            enumerated_processes[owning_process.obj_offset] = user_modules

    thread_modules = user_modules + kernel_modules
    return thread_modules
예제 #16
0
파일: winobj.py 프로젝트: kslgroup/WinObj
    def calculate(self):

        # gets the kernel address space
        addr_space = utils.load_as(self._config)

        # updates vtype objects' size
        self.update_sizes(addr_space)

        kdbg = tasks.get_kdbg(addr_space)
        root_dir = self.get_root_directory(kdbg, addr_space)
        self.parse_directory(root_dir, addr_space, self.root_obj_list)

        # checks for the SUPPLY_ADDR option
        if self._config.SUPPLY_ADDR:
            addrs = self._config.SUPPLY_ADDR.split(",")
            for addr in addrs:
                l = []

                # validates the address
                try:
                    addr = eval(addr)

                # addr is not valid
                except (SyntaxError, NameError):
                    continue

                obj_header = Obj.Object("_OBJECT_HEADER",
                                        addr - self.OBJECT_HEADER_SIZE,
                                        addr_space)
                name = self.GetName(obj_header, addr_space)

                # validates the directory
                if name:
                    self.parse_directory(addr, addr_space, l)
                    self.tables[name] = (addr, l)

        # checks for the FULL_PATH option
        elif self._config.FULL_PATH:

            # gets all dirs
            dirs = self._config.FULL_PATH.split(",")
            for path in dirs:
                self.SaveByPath(path, addr_space)

        # default option
        else:
            self.tables["/"] = (root_dir, self.root_obj_list)

            # checks for the PARSE_ALL option
            if self._config.PARSE_ALL:
                self.get_directory(addr_space)
예제 #17
0
    def _scan_kernel_memory(self, addr_space, rules):
        # Find KDBG so we know where kernel memory begins. Do not assume
        # the starting range is 0x80000000 because we may be dealing with
        # an image with the /3GB boot switch.
        kdbg = tasks.get_kdbg(addr_space)

        start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

        # Modules so we can map addresses to owners
        mods = dict(
            (addr_space.address_mask(mod.DllBase), mod)
            for mod in modules.lsmod(addr_space)
        )
        mod_addrs = sorted(mods.keys())

        # There are multiple views (GUI sessions) of kernel memory.
        # Since we're scanning virtual memory and not physical,
        # all sessions must be scanned for full coverage. This
        # really only has a positive effect if the data you're
        # searching for is in GUI memory.
        sessions = []

        for proc in tasks.pslist(addr_space):
            sid = proc.SessionId
            # Skip sessions we've already seen
            if sid == None or sid in sessions:
                continue

            session_space = proc.get_process_address_space()
            if session_space == None:
                continue

            sessions.append(sid)
            scanner = DiscontigYaraScanner(
                address_space=session_space, rules=rules
            )

            for hit, address in scanner.scan(start_offset=start):
                module = tasks.find_module(
                    mods, mod_addrs, addr_space.address_mask(address)
                )
                yield (
                    module,
                    address - self._config.REVERSE,
                    hit,
                    session_space.zread(
                        address - self._config.REVERSE, self._config.SIZE
                    ),
                )
예제 #18
0
    def find_smglobals(self, addrspace):
        """Find and read the nt!SmGlobals value.

        On success, return True and save the SmGlobals value in
        self._smglobals. On Failure, return False.

        This method must be called before performing any tasks that require
        SmGlobals. Otherwise reading compressed pages is out of the question.
        """
        meta = addrspace.profile.metadata
        vers = (meta.get("major", 0), meta.get("minor", 0))

        # This only applies to Windows 10 or greater
        if vers < (6, 4):
            return False

        # Prevent subsequent attempts from recalculating the existing value
        if self._smglobals:
            return True

        if not has_yara:
            debug.warning("Yara module is not installed")
            return False

        kdbg = tasks.get_kdbg(addrspace)
        if not kdbg:
            debug.warning("Cannot find KDBG")
            return False

        # First module should be ntoskrnl
        try:
            nt_mod = next(kdbg.modules())
        except StopIteration:
            debug.warning("Cannot find ntoskrnl")
            return False

        if not nt_mod:
            debug.warning("Cannot find ntoskrnl")
            return False

        if meta.get('memory_model', '32bit') == '32bit':
            smglobals = self._get_smglobals(addrspace, nt_mod,
                                            self._x86_smglobals)
        else:
            smglobals = self._get_smglobals(addrspace, nt_mod,
                                            self._x64_smglobals)

        self._smglobals = smglobals
        return True
예제 #19
0
    def check_pspcid(self, addr_space):
        """Enumerate processes by walking the PspCidTable"""
        ret = dict()

        # Follow the pointers to the table base
        kdbg = tasks.get_kdbg(addr_space)
        PspCidTable = kdbg.PspCidTable.dereference().dereference()

        # Walk the handle table
        for handle in PspCidTable.handles():
            if handle.get_object_type() == "Process":
                process = handle.dereference_as("_EPROCESS")
                ret[process.obj_vm.vtop(process.obj_offset)] = process

        return ret
예제 #20
0
    def check_pspcid(self, addr_space):
        """Enumerate processes by walking the PspCidTable"""
        ret = dict()

        # Follow the pointers to the table base
        kdbg = tasks.get_kdbg(addr_space)
        PspCidTable = kdbg.PspCidTable.dereference().dereference()

        # Walk the handle table
        for handle in PspCidTable.handles():
            if handle.get_object_type() == "Process":
                process = handle.dereference_as("_EPROCESS")
                ret[process.obj_vm.vtop(process.obj_offset)] = process

        return ret
예제 #21
0
    def __init__(self, addr_space, build_symbols):
        self.parser = NameParser()

        # Used to cache symbol/export/module information in an SQLite3 DB
        # NB: Volatility cache storeage area used, but we manage things manually.
        cache_sym_db_path = "{0}/symbols".format(
            addr_space._config.CACHE_DIRECTORY)
        if not os.path.exists(cache_sym_db_path):
            os.makedirs(cache_sym_db_path)
        self._sym_db_conn = sqlite3.connect("{0}/{1}.db".format(
            cache_sym_db_path, addr_space.profile.__class__.__name__))
        db = self.get_cursor()
        db.execute("attach ':memory:' as volatility")
        self._sym_db_conn.commit()

        kdbg = tasks.get_kdbg(addr_space)

        # Build tables and indexes
        self.create_tables(db)

        # Insert kernel space module information
        debug.info("Building function symbol tables for kernel space...")
        for mod in kdbg.modules():
            if build_symbols:
                # Module row created by add_exports if it doesn't already exist
                self.add_exports(db, mod)
                self.add_debug_symbols(db, kdbg.obj_vm, mod)
            # Link in system modules to each process
            for eproc in kdbg.processes():
                self.add_module(db, eproc, mod)

        # Insert (per process) user space module information
        debug.info(
            "Building function symbol tables for each processes user space...")
        for eproc in kdbg.processes():
            debug.info("Processing PID {0} ...".format(
                int(eproc.UniqueProcessId)))
            for mod in eproc.get_load_modules():
                if build_symbols:
                    # Module row created by add_exports if it doesn't already exist
                    self.add_exports(db, mod)
                    self.add_debug_symbols(db,
                                           eproc.get_process_address_space(),
                                           mod)
                # Link in user module to current process
                self.add_module(db, eproc, mod)

        debug.info("Symbol tables successfully built")
예제 #22
0
파일: mvolatility.py 프로젝트: vertrex/DFF
 def start(self, args):
     if not with_volatility:
         raise RuntimeError("Volatility not found. Please install it")
     self.memdump = args["file"].value()
     self._config.updateCtx('location', "file://" + self.memdump.absolute())
     self._config.updateCtx('filename', self.memdump.name())
     self._config.updateCtx('debug', True)
     self.__processes = []
     self.__dlls = {}
     self.__step = 1
     self.__steps = 6
     starttime = time.time()
     if args.has_key("profile"):
         self.stateinfo = "Using provided profile: " + args[
             'profile'].toString()
         self._config.updateCtx('profile', args['profile'].value())
         self._aspace = utils.load_as(self._config)
         self._kdbg = tasks.get_kdbg(self._aspace)
         self._config.updateCtx('kdbg', self._kdbg.obj_offset)
     else:
         try:
             self.__guessProfile()
         except:
             traceback.print_exc()
     try:
         self.root = WinRootNode("Windows RAM", self.memdump, self)
         self.registerTree(self.memdump, self.root)
         self.__psxview = psxview.PsXview(self._config)
         self.__findConnections()
         self.__findProcesses()
         self.__createProcessTree()
         self.__createDlls()
         self.__createModules()
         self.__createProcessesVadTree()
         self.stateinfo = ""
     except:
         traceback.print_exc()
     aspace = self._aspace
     count = 0
     if debug:
         while aspace:
             count += 1
             print 'AS Layer', str(
                 count), aspace.__class__.__name__, "(", aspace.name, ")"
             aspace = aspace.base
         print time.time() - starttime
예제 #23
0
    def __init__(self, config, *args, **kwargs):
        commands.Command.__init__(self, config, *args, **kwargs)
        config.add_option("BUILD_SYMBOLS",
                          default=False,
                          action='store_true',
                          cache_invalidator=False,
                          help="Build symbol table information")
        config.add_option(
            "USE_SYMBOLS",
            default=False,
            action='store_true',
            cache_invalidator=False,
            help=
            "Use symbol servers to resolve process addresses to module names")

        self.kdbg = tasks.get_kdbg(utils.load_as(config))
        self.build_symbols = getattr(config, 'BUILD_SYMBOLS', False)
        self.use_symbols = getattr(config, 'USE_SYMBOLS', False)
예제 #24
0
    def calculate(self):
        if not has_yara:
            debug.error(
                "Please install Yara from code.google.com/p/yara-project")
        addr_space = utils.load_as(self._config)
        rules = yara.compile(sources=ghost_sig)
        decrypted_data = None
        mal_proc = {}

        kdbg = tasks.get_kdbg(addr_space)
        start = kdbg.MmSystemRangeStart.dereference_as("Pointer")
        mods = dict((addr_space.address_mask(mod.DllBase), mod)
                    for mod in modules.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())
        sessions = []
        for proc in tasks.pslist(addr_space):
            sid = proc.SessionId

            if sid == None or sid in sessions:
                continue
            session_space = proc.get_process_address_space()
            if session_space == None:
                continue
            sessions.append(sid)
            scanner = malfind.DiscontigYaraScanner(address_space=session_space,
                                                   rules=rules)
            for hit, address in scanner.scan(start_offset=start):
                module = tasks.find_module(mods, mod_addrs,
                                           addr_space.address_mask(address))
                content = session_space.zread(address, 1024)
                header_size = content.find("\x78\x9c")
                magic_header_size = header_size - 8
                magic_keyword = content[:magic_header_size]
                comp_uncomp_size = content[magic_header_size:header_size]
                s = struct.Struct("I I")
                comp_size, uncomp_size = s.unpack(comp_uncomp_size)
                enc_data = content[0:comp_size]
                to_decrypt = content[header_size:comp_size]
                dec_data = self.decrypt_communication(to_decrypt)
                if not mal_proc:
                    self.get_ghost_process(magic_keyword, mal_proc, addr_space)
                    os_version = self.get_os_version(addr_space)
                yield (mal_proc, address, magic_keyword, enc_data, dec_data,
                       os_version)
예제 #25
0
  def __init__(self, addr_space, build_symbols):
    self.parser = NameParser()

    # Used to cache symbol/export/module information in an SQLite3 DB
    # NB: Volatility cache storeage area used, but we manage things manually.
    cache_sym_db_path = "{0}/symbols".format(addr_space._config.CACHE_DIRECTORY)
    if not os.path.exists(cache_sym_db_path):
      os.makedirs(cache_sym_db_path)
    self._sym_db_conn = sqlite3.connect("{0}/{1}.db".format(cache_sym_db_path, addr_space.profile.__class__.__name__))
    db = self.get_cursor()
    db.execute("attach ':memory:' as volatility")
    self._sym_db_conn.commit()

    kdbg = tasks.get_kdbg(addr_space)

    # Build tables and indexes
    self.create_tables(db)

    # Insert kernel space module information
    debug.info("Building function symbol tables for kernel space...")
    for mod in kdbg.modules():
      if build_symbols:
        # Module row created by add_exports if it doesn't already exist
        self.add_exports(db, mod)
        self.add_debug_symbols(db, kdbg.obj_vm, mod)
      # Link in system modules to each process
      for eproc in kdbg.processes():
        self.add_module(db, eproc, mod)

    # Insert (per process) user space module information
    debug.info("Building function symbol tables for each processes user space...")
    for eproc in kdbg.processes():
      debug.info("Processing PID {0} ...".format(int(eproc.UniqueProcessId)))
      for mod in eproc.get_load_modules():
        if build_symbols:
          # Module row created by add_exports if it doesn't already exist
          self.add_exports(db, mod)
          self.add_debug_symbols(db, eproc.get_process_address_space(), mod)
        # Link in user module to current process
        self.add_module(db, eproc, mod)

    debug.info("Symbol tables successfully built")
예제 #26
0
    def calculate(self):
        if not has_yara:
            debug.error("Please install Yara from code.google.com/p/yara-project")
        addr_space = utils.load_as(self._config)
        rules = yara.compile(sources=ghost_sig)
        decrypted_data = None
        mal_proc = {}

        kdbg = tasks.get_kdbg(addr_space)
        start = kdbg.MmSystemRangeStart.dereference_as("Pointer")
        mods = dict((addr_space.address_mask(mod.DllBase), mod)
                        for mod in modules.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())
        sessions = []
        for proc in tasks.pslist(addr_space):
                sid = proc.SessionId

                if sid == None or sid in sessions:
                    continue
                session_space = proc.get_process_address_space()
                if session_space == None:
                    continue
                sessions.append(sid)
                scanner = malfind.DiscontigYaraScanner(address_space = session_space,
                                               rules = rules)
                for hit, address in scanner.scan(start_offset = start):
                    module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(address))
                    content = session_space.zread(address,1024)
                    header_size = content.find("\x78\x9c")
                    magic_header_size = header_size - 8
                    magic_keyword = content[:magic_header_size]
                    comp_uncomp_size = content[magic_header_size:header_size]
                    s = struct.Struct("I I")
                    comp_size, uncomp_size = s.unpack(comp_uncomp_size)
                    enc_data = content[0:comp_size]
                    to_decrypt = content[header_size:comp_size]
                    dec_data = self.decrypt_communication(to_decrypt)
                    if not mal_proc:
                        self.get_ghost_process(magic_keyword, mal_proc, addr_space)
                        os_version = self.get_os_version(addr_space)
                    yield (mal_proc, address, magic_keyword, enc_data, dec_data, os_version)
예제 #27
0
    def _scan_kernel_memory(self, addr_space, rules):
        # Find KDBG so we know where kernel memory begins. Do not assume
        # the starting range is 0x80000000 because we may be dealing with
        # an image with the /3GB boot switch. 
        kdbg = tasks.get_kdbg(addr_space)

        start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

        # Modules so we can map addresses to owners
        mods = dict((addr_space.address_mask(mod.DllBase), mod)
                    for mod in modules.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())

        # There are multiple views (GUI sessions) of kernel memory.
        # Since we're scanning virtual memory and not physical, 
        # all sessions must be scanned for full coverage. This 
        # really only has a positive effect if the data you're
        # searching for is in GUI memory. 
        sessions = []

        for proc in tasks.pslist(addr_space):
            sid = proc.SessionId
            # Skip sessions we've already seen 
            if sid == None or sid in sessions:
                continue

            session_space = proc.get_process_address_space()
            if session_space == None:
                continue

            sessions.append(sid)
            scanner = DiscontigYaraScanner(address_space = session_space,
                                           rules = rules)

            for hit, address in scanner.scan(start_offset = start):
                module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(address))
                yield (module, address - self._config.REVERSE, hit, session_space.zread(address - self._config.REVERSE, self._config.SIZE))
예제 #28
0
    def calculate(self):

        if not has_distorm3:
            debug.warning("For best results please install distorm3")

        # Checks that subclass AbstractThreadCheck
        checks = registry.get_plugin_classes(AbstractThreadCheck)

        # If --listtags is chosen, just print the tags and return 
        if self._config.LISTTAGS:
            for cls_name, cls in checks.items():
                sys.stdout.write("{0:<20} {1}\n".format(cls_name, pydoc.getdoc(cls)))
            return

        addr_space = utils.load_as(self._config)
        system_range = tasks.get_kdbg(addr_space).MmSystemRangeStart.dereference_as("Pointer")

        # Only show threads owned by particular processes
        pidlist = []
        if self._config.PID:
            pidlist = [int(p) for p in self._config.PID.split(',')]
        elif self._config.OFFSET:
            process = self.virtual_process_from_physical_offset(addr_space, self._config.OFFSET)
            if process:
                pidlist = [int(process.UniqueProcessId)]

        # Get sorted list of kernel modules 
        mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in modules.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())

        # Are we on x86 or x64. Save this for render_text 
        self.bits32 = addr_space.profile.metadata.\
            get("memory_model", "32bit") == "32bit"

        # Get a list of hooked SSDTs but only on x86
        if self.bits32:
            hooked_tables = self.get_hooked_tables(addr_space)
        else:
            hooked_tables = None

        # Dictionary to store threads. Keys are physical offsets of
        # ETHREAD objects. Values are tuples, where the first item is
        # a boolean specifying if the object was found by scanning and
        # the second item is the actual ETHREAD object. 
        seen_threads = dict()

        # Gather threads by list traversal of active/linked processes 
        for task in taskmods.DllList(self._config).calculate():
            for thread in task.ThreadListHead.\
                    list_of_type("_ETHREAD", "ThreadListEntry"):
                seen_threads[thread.obj_vm.vtop(thread.obj_offset)] = (False, thread)

        # Now scan for threads and save any that haven't been seen
        for thread in modscan.ThrdScan(self._config).calculate():
            if not seen_threads.has_key(thread.obj_offset):
                seen_threads[thread.obj_offset] = (True, thread)

        # Keep a record of processes whose DLLs we've already enumerated
        process_dll_info = {}

        for _offset, (found_by_scanner, thread) in seen_threads.items():

            # Skip processes the user doesn't want to see
            if ((self._config.PID or self._config.OFFSET) and not pidlist) or (pidlist and thread.Cid.UniqueProcess not in pidlist):
                continue

            # Do we need to gather DLLs for module resolution 
            if addr_space.address_compare(thread.StartAddress, system_range) != -1:
                owner = tasks.find_module(mods, 
                                          mod_addrs, 
                                          addr_space.address_mask(thread.StartAddress))
            else:
                owning_process = thread.owning_process() 
                if not owning_process.is_valid(): 
                    owner = None
                else:
                    try:
                        user_mod_addrs, user_mods = process_dll_info[owning_process.obj_offset]
                    except KeyError:
                        user_mods = dict((addr_space.address_mask(mod.DllBase), mod) 
                                            for mod in owning_process.get_load_modules())
                        user_mod_addrs = sorted(user_mods.keys())
                        process_dll_info[owning_process.obj_offset] = (user_mod_addrs, user_mods)
                    owner = tasks.find_module(user_mods, 
                                              user_mod_addrs, 
                                              addr_space.address_mask(thread.StartAddress))
            
            if owner:
                owner_name = str(owner.BaseDllName or '')
            else:
                owner_name = "UNKNOWN"

            # Replace the dummy class with an instance 
            instances = dict(
                        (cls_name, cls(thread, mods, mod_addrs,
                            hooked_tables, found_by_scanner))
                        for cls_name, cls in checks.items()
                        )

            yield thread, addr_space, mods, mod_addrs, \
                        instances, hooked_tables, system_range, owner_name
예제 #29
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        if not self.is_valid_profile(addr_space.profile):
            debug.error("This command does not support the selected profile.")

        # Get the OS version we're analyzing 
        version = (addr_space.profile.metadata.get('major', 0),
                   addr_space.profile.metadata.get('minor', 0))

        modlist = list(modules.lsmod(addr_space))
        mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in modlist)
        mod_addrs = sorted(mods.keys())

        # KTIMERs collected 
        timers = []

        # Valid KTIMER.Header.Type values 
        TimerNotificationObject = 8
        TimerSynchronizationObject = 9
        valid_types = (TimerNotificationObject, TimerSynchronizationObject)

        if version == (5, 1) or (version == (5, 2) and
                                addr_space.profile.metadata.get('build', 0) == 3789):

            # On XP SP0-SP3 x86 and Windows 2003 SP0, KiTimerTableListHead
            # is an array of 256 _LIST_ENTRY for _KTIMERs.

            KiTimerTableListHead = self.find_list_head(modlist[0],
                                        "KeUpdateSystemTime",
                                        "\x25\xFF\x00\x00\x00\x8D\x0C\xC5")

            lists = obj.Object("Array", offset = KiTimerTableListHead,
                                        vm = addr_space,
                                        targetType = '_LIST_ENTRY',
                                        count = 256)

            for l in lists:
                for t in l.list_of_type("_KTIMER", "TimerListEntry"):
                    timers.append(t)

        elif version == (5, 2) or version == (6, 0):

            # On XP x64, Windows 2003 SP1-SP2, and Vista SP0-SP2, KiTimerTableListHead
            # is an array of 512 _KTIMER_TABLE_ENTRY structs.

            KiTimerTableListHead = self.find_list_head(modlist[0],
                                        "KeCancelTimer",
                                        "\xC1\xE7\x04\x81\xC7")

            lists = obj.Object("Array", offset = KiTimerTableListHead,
                                        vm = addr_space,
                                        targetType = '_KTIMER_TABLE_ENTRY',
                                        count = 512)

            for l in lists:
                for t in l.Entry.list_of_type("_KTIMER", "TimerListEntry"):
                    timers.append(t)

        elif version == (6, 1):

            # On Windows 7, there is no more KiTimerTableListHead. The list is
            # at _KPCR.PrcbData.TimerTable.TimerEntries (credits to Matt Suiche
            # for this one. See http://pastebin.com/FiRsGW3f).
            for kpcr in tasks.get_kdbg(addr_space).kpcrs():
                for table in kpcr.ProcessorBlock.TimerTable.TimerEntries:
                    for t in table.Entry.list_of_type("_KTIMER", "TimerListEntry"):
                        timers.append(t)

        for timer in timers:

            # Sanity check on the timer type 
            if timer.Header.Type not in valid_types:
                continue

            # Ignore timers without DPCs
            if not timer.Dpc.is_valid() or not timer.Dpc.DeferredRoutine.is_valid():
                continue

            # Lookup the module containing the DPC
            module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(timer.Dpc.DeferredRoutine))

            yield timer, module
예제 #30
0
    def get_threads(self,process,vthreads,pslist1):

        result = []
        result.append("False")
        result.append("False")
        result.append("False")
        result.append("False")

        thread1 = {}

        addr_space = utils.load_as(self._config)
        system_range = tasks.get_kdbg(addr_space).MmSystemRangeStart.dereference_as("Pointer")
        mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in moduless.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())
        seen_threads = dict()

        ## Gather threads by list traversal of active/linked processes
        for thread in process.ThreadListHead.list_of_type("_ETHREAD", "ThreadListEntry"):
            seen_threads[thread.obj_vm.vtop(thread.obj_offset)] = (False, thread)

        process_dll_info = {}

        for _offset, (found_by_scanner, thread) in seen_threads.items():
            # Do we need to gather DLLs for module resolution
            if addr_space.address_compare(thread.StartAddress, system_range) != -1:
                owner = tasks.find_module(mods, mod_addrs,addr_space.address_mask(thread.StartAddress))
            else:
                owning_process = thread.owning_process()
                if not owning_process.is_valid():
                    owner = None
                else:
                    try:
                        user_mod_addrs, user_mods = process_dll_info[owning_process.obj_offset]
                    except KeyError:
                        user_mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in owning_process.get_load_modules())
                        user_mod_addrs = sorted(user_mods.keys())
                        process_dll_info[owning_process.obj_offset] = (user_mod_addrs, user_mods)

                    owner = tasks.find_module(user_mods, user_mod_addrs, addr_space.address_mask(thread.StartAddress))

            # Specific fields
            thread1["ThreadId"] = ""
            thread1["PsCrossThreadFlagsImpersonating"] = "False"
            thread1["PsCrossThreadFlagsHideFromDbg"] = "False"
            thread1["PsCrossThreadFlagsSystem"] = "False"
            thread1["PsCrossThreadFlagsTerminated"] = "False"
            thread1["PsCrossThreadFlagsDeadThread"] = "False"
            thread1["PsCrossThreadFlagsBreakOnTermination"] = "False"
            thread1["PsCrossThreadFlagsSkipCreationMsg"] = "False"
            thread1["PsCrossThreadFlagsSkipTerminationMsg"] = "False"
            thread1["StartAddress"] = ""
            thread1["State"] = ""
            thread1["WaitReason"] = ""
            thread1["CreateTime"] = ""
            thread1["ExitTime"] = ""
            thread1["OwnerName"] = ""
            thread1["OwningProcess"] = ""
            thread1["AttachedProcess"] = ""
            thread1["Win32StartAddress"] = ""
            # Process fields necessaries to a new idEvent
            thread1["idEvent"] = 101
            thread1["ProcessId"] = pslist1["ProcessId"]
            thread1["ProcessGuid"] = pslist1["ProcessGuid"]
            thread1["SyspceId"] = pslist1["SyspceId"]
            thread1["Image"] = pslist1["Image"]
            thread1["Source"] = "Memory"
            thread1['computer'] = pslist1['computer']
            thread1["OwningProcess"] = str(thread.owning_process().ImageFileName)
            thread1["AttachedProcess"] = str(thread.attached_process().ImageFileName)

            if "PS_CROSS_THREAD_FLAGS_IMPERSONATING" in str(thread.CrossThreadFlags):
                result[1] = "True"
                thread1["PsCrossThreadFlagsImpersonating"] = "True"

            if "PS_CROSS_THREAD_FLAGS_HIDEFROMDBG" in str(thread.CrossThreadFlags):
                result[2] = "True"
                thread1["PsCrossThreadFlagsHideFromDbg"] = "True"

            if "PS_CROSS_THREAD_FLAGS_SYSTEM" in str(thread.CrossThreadFlags):
                result[3] = "True"
                thread1["PsCrossThreadFlagsSystem"] = "True"

            if "PS_CROSS_THREAD_FLAGS_TERMINATED" in str(thread.CrossThreadFlags):
                thread1["PsCrossThreadFlagsTerminated"] = "True"

            if "PS_CROSS_THREAD_FLAGS_DEADTHREAD" in str(thread.CrossThreadFlags):
                thread1["PsCrossThreadFlagsDeadThread"] = "True"

            if "PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION" in str(thread.CrossThreadFlags):
                thread1["PsCrossThreadFlagsBreakOnTermination"] = "True"

            if "PS_CROSS_THREAD_FLAGS_SKIP_CREATION_MSG" in str(thread.CrossThreadFlags):
                thread1["PsCrossThreadFlagsSkipCreationMsg"] = "True"

            if "PS_CROSS_THREAD_FLAGS_SKIP_TERMINATION_MSG" in str(thread.CrossThreadFlags):
                thread1["PsCrossThreadFlagsSkipTerminationMsg"] = "True"

            if owner:
                owner_name = str(owner.BaseDllName or 'None')
                thread1["OwnerName"] =  str(owner.BaseDllName or 'None')
            else:
                owner_name = "Unknown"
                thread1["OwnerName"] = "Unknown"
                result[0] = "True"

            thread1["StartAddress"] = str(thread.StartAddress)
            thread1["State"] = str(thread.Tcb.State)
            thread1["WaitReason"] = str(thread.Tcb.WaitReason)
            thread1["ThreadId"] = int(thread.Cid.UniqueThread)
            thread1["CreateTime"] = str(thread.CreateTime)
            thread1["ExitTime"] = str(thread.ExitTime)
            thread1["Win32StartAddress"] = str(thread.Win32StartAddress)
            vthreads.append(thread1)
            thread1 = {}

        return result
예제 #31
0
    def calculate(self):

        if not has_yara:
            debug.error("Please install Yara from code.google.com/p/yara-project")

        addr_space = utils.load_as(self._config)

        if self._config.YARA_RULES:
            s = self._config.YARA_RULES
            # Don't wrap hex or regex rules in quotes 
            if s[0] not in ("{", "/"): s = '"' + s + '"'
            # Scan for unicode strings 
            if self._config.WIDE: s += "wide"
            rules = yara.compile(sources = {
                        'n' : 'rule r1 {strings: $a = ' + s + ' condition: $a}'
                        })
        elif self._config.YARA_FILE:
            rules = yara.compile(self._config.YARA_FILE)
        else:
            debug.error("You must specify a string (-Y) or a rules file (-y)")

        if self._config.KERNEL:

            # Find KDBG so we know where kernel memory begins. Do not assume
            # the starting range is 0x80000000 because we may be dealing with
            # an image with the /3GB boot switch. 
            kdbg = tasks.get_kdbg(addr_space)

            start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

            # Modules so we can map addresses to owners
            mods = dict((mod.DllBase, mod)
                        for mod in modules.lsmod(addr_space))
            mod_addrs = sorted(mods.keys())

            # There are multiple views (GUI sessions) of kernel memory.
            # Since we're scanning virtual memory and not physical, 
            # all sessions must be scanned for full coverage. This 
            # really only has a positive effect if the data you're
            # searching for is in GUI memory. 
            sessions = []

            for proc in tasks.pslist(addr_space):
                sid = proc.SessionId
                # Skip sessions we've already seen 
                if sid == None or sid in sessions:
                    continue

                session_space = proc.get_process_address_space()
                if session_space == None:
                    continue

                sessions.append(sid)
                scanner = DiscontigYaraScanner(address_space = session_space,
                                               rules = rules)

                for hit, address in scanner.scan(start_offset = start):
                    module = tasks.find_module(mods, mod_addrs, address)
                    yield (module, address, hit, session_space.zread(address, 1024))

        else:
            for task in self.filter_tasks(tasks.pslist(addr_space)):
                scanner = VadYaraScanner(task = task, rules = rules)
                for hit, address in scanner.scan():
                    yield (task, address, hit, scanner.address_space.zread(address, 1024))
예제 #32
0
    def execute(self,options,config,yarapath):
        addr_space = utils.load_as(config)

        if not os.path.isfile("kdcopydatablock.txt"):
            if (addr_space.profile.metadata.get("os") == "windows" and addr_space.profile.metadata.get("memory_model") == "64bit" and addr_space.profile.metadata.get("major") >= 6 and addr_space.profile.metadata.get("minor") >= 2):
                kdbg = tasks.get_kdbg(addr_space)
                fout = open('kdcopydatablock.txt', 'w')
                kdblockaddr = '{0:#x}'.format(kdbg.KdCopyDataBlock)
                fout.write(kdblockaddr)
                fout.close()
                sys.argv.append("--kdbg")
                sys.argv.append(kdblockaddr)
        
        processList = tasks.pslist(addr_space)

        if adutils.getConfigValue(options,'sockets') == True:
            getSocketsDelegate = adsockets.getSocketsFactory(addr_space.profile)
            sockets = getSocketsDelegate(config,addr_space)

        if adutils.getConfigValue(options,'yarascan') == True:
            getYaraDelegate = adyarascan.getYaraFactory(addr_space.profile)
            config.update('YARA_RULES_DIRECTORY',yarapath)
            compiledrules = getYaraDelegate(config).compile_rules()

        list_head_offset = None
        has_service_table = False

        process_obj_list = datastructs.rootType()

        for processIndex, eprocess in enumerate(processList):
            config.process_id = eprocess.UniqueProcessId
            config.dtb = eprocess.Pcb.DirectoryTableBase

            all_mods = list(eprocess.get_load_modules())

            # get Token for Privileges
            token = eprocess.Token.dereference_as('_TOKEN')
            if hasattr(token.Privileges, 'Present'):
                privileges = token.Privileges.Present
            else:
                # Current memory analysis erroneously points
                # to token.ModifiedId for privileges for XP
                # The line below will match what the current memory analysis collects:
                # privileges = token.ModifiedId.LowPart
                # I don't think this is correct, either.
                luid = token.Privileges.dereference_as('_LUID_AND_ATTRIBUTES')
                privileges = luid.Luid.LowPart
            
            validName = "Unknown"    
            if eprocess.ImageFileName:
                validName = eprocess.ImageFileName
            name = self.get_full_name(name=validName, path=eprocess.Peb.ProcessParameters.ImagePathName or '')
            try:
                process_obj = process_obj_list.Process.add(
                    resultitemtype=18,
                    Name=name,
                    Path=adutils.SmartUnicode(eprocess.Peb.ProcessParameters.ImagePathName or ""),
                    StartTime=adutils.SmartUnicode(eprocess.CreateTime or ""),
                    WorkingDir=adutils.SmartUnicode(eprocess.Peb.ProcessParameters.CurrentDirectory.DosPath or ""),
                    CommandLine=adutils.SmartUnicode(eprocess.Peb.ProcessParameters.CommandLine or ""),
                    LinkTime=0,
                    Subsystem=long(eprocess.Peb.ImageSubsystem),
                    Imagebase=long(eprocess.Peb.ImageBaseAddress),
                    Characteristics=0,
                    Checksum=0,
                    KernelTime=long(eprocess.Pcb.KernelTime),
                    UserTime=long(eprocess.Pcb.UserTime),
                    Privileges=long(privileges),
                    PID=int(eprocess.UniqueProcessId),
                    ParentPID=int(eprocess.InheritedFromUniqueProcessId),
                    User='',
                    Group='',
                    MD5=BLANK_MD5,
                    SHA1=BLANK_SHA1,
                    FuzzySize=0,
                    Fuzzy='',
                    Fuzzy2X='',
                    KFFStatus=0,
                    FromMemory='',
                    EffectiveUser='',
                    EffectiveGroup='',
                    Size=calculate_image_size(eprocess),
                    EProcBlockLoc=long(eprocess.obj_vm.vtop(eprocess.obj_offset)) or 0,
                    WindowTitle=adutils.SmartUnicode(eprocess.Peb.ProcessParameters.WindowTitle or "")
                )
            except:
                debug.info('Caught error in adding process, continuing')
                continue

            kthread = eprocess.Pcb.ThreadListHead.Flink.dereference_as('_KTHREAD')
            list_head_offset = kthread.ThreadListEntry.obj_offset - kthread.obj_offset
            kthread = obj.Object('_KTHREAD', offset=eprocess.Pcb.ThreadListHead.Flink - list_head_offset, vm=eprocess.obj_vm)
            if hasattr(kthread, 'ServiceTable'):
                SDTs = set()
                for i in range(eprocess.ActiveThreads):
                    if _is_valid_service_table_address(address=kthread.ServiceTable, memory_model=eprocess.obj_vm.profile.metadata.get('memory_model', '32bit')):
                        SDTs.add(long(kthread.ServiceTable))
                    kthread = obj.Object('_KTHREAD', offset=kthread.ThreadListEntry.Flink - list_head_offset, vm=eprocess.obj_vm)
                for sdt in SDTs:
                    process_obj.SDT.append(sdt)

            if adutils.getConfigValue(options,'processdlls') == True:
                for moduleIndex, module in enumerate(all_mods):
                    baseName = "Unknown"
                    if module.BaseDllName:
                        baseName = module.BaseDllName
                    dll_obj = process_obj.Loaded_DLL_List.DLL.add(
                        Name=adutils.SmartUnicode(baseName or ''),
                        Description='',
                        Path=adutils.SmartUnicode(module.FullDllName or ''),
                        Version='',
                        MD5=BLANK_MD5,
                        SHA1=BLANK_SHA1,
                        FuzzySize=0,
                        Fuzzy='',
                        Fuzzy2X='',
                        CreateTime=u"0000-00-00 00:00:00", #adutils.SmartUnicode(module.TimeDateStamp),
                        KFFStatus=0,
                        PID=int(eprocess.UniqueProcessId),
                        baseAddress=long(module.DllBase),
                        ImageSize=long(module.SizeOfImage),
                        ProcessName=name,
                        FromMemory=''
                    )
            if adutils.getConfigValue(options,'sockets') == True:
                pid = int(eprocess.UniqueProcessId)
                if pid in sockets:
                    process_obj.Open_Sockets_List.CopyFrom(sockets[pid])

            if adutils.getConfigValue(options,'handles') == True:
                if eprocess.ObjectTable.HandleTableList:
                    for handle in eprocess.ObjectTable.handles():
                        if not handle.is_valid():
                            continue
                        handle_obj = process_obj.Open_Handles_List.OpenHandle.add(
                            ID=long(handle.HandleValue),
                            Type=adutils.SmartUnicode(handle.get_object_type()),
                            Path=get_handle_name(handle),
                            AccessMask=int(handle.GrantedAccess),
                            Name='',
                            PID=int(eprocess.UniqueProcessId),
                            PointerCount=long(handle.PointerCount),
                            ObjectAddress=long(handle.obj_offset),
                            FromMemory='',
                            Owner='',
                            Group='',
                            Permissions=''
                        )
            if adutils.getConfigValue(options,'vad') == True:
                for vad in eprocess.VadRoot.traverse():
                    longflags = 0
                    if hasattr(vad, 'u'):
                        longflags = long(vad.u.LongFlags)
                    elif hasattr(vad, 'Core'):
                        longflags = long(vad.Core.u.LongFlags)
                    vad_obj = process_obj.Vad_List.Vad.add(
                        Protection=int(vad.VadFlags.Protection),
                        StartVpn=long(vad.Start >> PAGE_SIZE),
                        EndVpn=long(vad.End >> PAGE_SIZE),
                        Address=long(vad.obj_offset),
                        Flags=longflags,
                        Mapped=u'False',
                        ProcessName=process_obj.Name,
                        PID=process_obj.PID,
                        FromMemory='')
                    if not vad.Tag in _MMVAD_SHORT_TAGS:
                        if vad.FileObject and vad.FileObject.FileName:
                            name = str(vad.FileObject.FileName)
                            if len(name) > 0 and name[0] == '\\':
                                vad_obj.Filename = adutils.SmartUnicode(name)
                                vad_obj.Mapped = u'True'
                            else:
                                print name

            if adutils.getConfigValue(options,'yarascan') == True:
                pid = int(eprocess.UniqueProcessId)
                config.update('pid',str(pid))
                yara = getYaraDelegate(config).calculateonvad(compiledrules, eprocess)
                try:
                    for hit in yara:
                        process_obj.YaraHits.YaraHit.add(
                            id='',
                            Name=hit[2].rule,
                            Category='')
                except:
                    debug.info('Caught error in adding yarahit, continuing')

        file = open(config.OUTPUT_PATH + "processes.xml", "w")
        #file.write(process_obj_list.SerializeToString())
        file.write(proto2xml(process_obj_list,indent=0))
예제 #33
0
    def findcookie(self, kernel_space):
        """Find and read the nt!ObHeaderCookie value. 

        On success, return True and save the cookie value in self._cookie.
        On Failure, return False. 

        This method must be called before performing any tasks that require 
        object header validation including handles, psxview (due to pspcid) 
        and the object scanning plugins (psscan, etc). 

        NOTE: this cannot be implemented as a volatility "magic" class,
        because it must be persistent across various classes and sources. 
        We don't want to recalculate the cookie value multiple times. 
        """

        meta = kernel_space.profile.metadata 
        vers = (meta.get("major", 0), meta.get("minor", 0))

        # this algorithm only applies to Windows 10 or greater 
        if vers < (6, 4):
            return True 

        # prevent subsequent attempts from recalculating the existing value 
        if self._cookie:
            return True

        if not has_distorm:
            debug.warning("distorm3 module is not installed")
            return False 

        kdbg = tasks.get_kdbg(kernel_space)
        nt_mod = list(kdbg.modules())[0]

        addr = nt_mod.getprocaddress("ObGetObjectType")
        if addr == None:
            debug.warning("Cannot find nt!ObGetObjectType")
            return False 

        # produce an absolute address by adding the DLL base to the RVA 
        addr += nt_mod.DllBase 
        if not nt_mod.obj_vm.is_valid_address(addr):
            debug.warning("nt!ObGetObjectType at {0} is invalid".format(addr))
            return False 

        # in theory...but so far we haven't tested 32-bits 
        model = meta.get("memory_model")    
        if model == "32bit":
            mode = distorm3.Decode32Bits
        else:
            mode = distorm3.Decode64Bits

        data = nt_mod.obj_vm.read(addr, 100)
        ops = distorm3.Decompose(addr, data, mode, distorm3.DF_STOP_ON_RET)
        addr = None

        # search backwards from the RET and find the MOVZX 

        if model == "32bit":
            # movzx ecx, byte ptr ds:_ObHeaderCookie
            for op in reversed(ops):
                if (op.size == 7 and 
                            'FLAG_DST_WR' in op.flags and
                            len(op.operands) == 2 and 
                            op.operands[0].type == 'Register' and 
                            op.operands[1].type == 'AbsoluteMemoryAddress' and 
                            op.operands[1].size == 8):
                    addr = op.operands[1].disp & 0xFFFFFFFF
                    break
        else:
            # movzx ecx, byte ptr cs:ObHeaderCookie 
            for op in reversed(ops):
                if (op.size == 7 and 
                            'FLAG_RIP_RELATIVE' in op.flags and
                            len(op.operands) == 2 and 
                            op.operands[0].type == 'Register' and 
                            op.operands[1].type == 'AbsoluteMemory' and 
                            op.operands[1].size == 8):
                    addr = op.address + op.size + op.operands[1].disp 
                    break

        if not addr:
            debug.warning("Cannot find nt!ObHeaderCookie")
            return False

        if not nt_mod.obj_vm.is_valid_address(addr):
            debug.warning("nt!ObHeaderCookie at {0} is not valid".format(addr))
            return False

        cookie = obj.Object("unsigned int", offset = addr, vm = nt_mod.obj_vm)
        self._cookie = int(cookie)

        return True
예제 #34
0
def lsmod(addr_space):
    """ A Generator for modules """

    for m in tasks.get_kdbg(addr_space).modules():
        yield m
예제 #35
0
    def findcookie(self, kernel_space):
        """Find and read the nt!ObHeaderCookie value. 

        On success, return True and save the cookie value in self._cookie.
        On Failure, return False. 

        This method must be called before performing any tasks that require 
        object header validation including handles, psxview (due to pspcid) 
        and the object scanning plugins (psscan, etc). 

        NOTE: this cannot be implemented as a volatility "magic" class,
        because it must be persistent across various classes and sources. 
        We don't want to recalculate the cookie value multiple times. 
        """

        meta = kernel_space.profile.metadata
        vers = (meta.get("major", 0), meta.get("minor", 0))

        # this algorithm only applies to Windows 10 or greater
        if vers < (6, 4):
            return True

        # prevent subsequent attempts from recalculating the existing value
        if self._cookie:
            return True

        if not has_distorm:
            debug.warning("distorm3 module is not installed")
            return False

        kdbg = tasks.get_kdbg(kernel_space)

        if not kdbg:
            debug.warning("Cannot find KDBG")
            return False

        nt_mod = None

        for mod in kdbg.modules():
            nt_mod = mod
            break

        if nt_mod == None:
            debug.warning("Cannot find NT module")
            return False

        addr = nt_mod.getprocaddress("ObGetObjectType")
        if addr == None:
            debug.warning("Cannot find nt!ObGetObjectType")
            return False

        # produce an absolute address by adding the DLL base to the RVA
        addr += nt_mod.DllBase
        if not nt_mod.obj_vm.is_valid_address(addr):
            debug.warning("nt!ObGetObjectType at {0} is invalid".format(addr))
            return False

        # in theory...but so far we haven't tested 32-bits
        model = meta.get("memory_model")
        if model == "32bit":
            mode = distorm3.Decode32Bits
        else:
            mode = distorm3.Decode64Bits

        data = nt_mod.obj_vm.read(addr, 100)
        ops = distorm3.Decompose(addr, data, mode, distorm3.DF_STOP_ON_RET)
        addr = None

        # search backwards from the RET and find the MOVZX

        if model == "32bit":
            # movzx ecx, byte ptr ds:_ObHeaderCookie
            for op in reversed(ops):
                if (op.size == 7 and 'FLAG_DST_WR' in op.flags
                        and len(op.operands) == 2
                        and op.operands[0].type == 'Register'
                        and op.operands[1].type == 'AbsoluteMemoryAddress'
                        and op.operands[1].size == 8):
                    addr = op.operands[1].disp & 0xFFFFFFFF
                    break
        else:
            # movzx ecx, byte ptr cs:ObHeaderCookie
            for op in reversed(ops):
                if (op.size == 7 and 'FLAG_RIP_RELATIVE' in op.flags
                        and len(op.operands) == 2
                        and op.operands[0].type == 'Register'
                        and op.operands[1].type == 'AbsoluteMemory'
                        and op.operands[1].size == 8):
                    addr = op.address + op.size + op.operands[1].disp
                    break

        if not addr:
            debug.warning("Cannot find nt!ObHeaderCookie")
            return False

        if not nt_mod.obj_vm.is_valid_address(addr):
            debug.warning("nt!ObHeaderCookie at {0} is not valid".format(addr))
            return False

        cookie = obj.Object("unsigned int", offset=addr, vm=nt_mod.obj_vm)
        self._cookie = int(cookie)

        return True
예제 #36
0
def lsmod(addr_space):
    """ A Generator for modules """

    for m in tasks.get_kdbg(addr_space).modules():
        yield m
예제 #37
0
    def calculate(self):

        if self._config.SLACK and (self._config.DSTS or self._config.PCAP):
            debug.error('SLACK can\'t be used with PCAP or DSTS')

        # Make sure the MAC address is valid
        if self._config.MAC:
            hex_mac = self.validate_mac(self._config.MAC)
            if not hex_mac:
                debug.error('Invalid MAC address')

        # Ensure PCAP file won't overwrite an existing file
        if self._config.PCAP and os.path.exists(self._config.PCAP):
            debug.error(
                '\'{}\' already exists.  Cowardly refusing to overwrite it...'.
                format(self._config.PCAP))

        # Ensure DSTS file won't overwrite an existing file
        if self._config.DSTS and os.path.exists(self._config.DSTS):
            debug.error(
                '\'{}\' already exists.  Cowardly refusing to overwrite it...'.
                format(self._config.DSTS))

        if self._config.SLACK:
            # Compiled RegEx = (tiny) increase in efficiency
            # NetBIOS code chars
            self.rx_nbchars = re.compile('^([ACDEFH][A-P])+$')

        # Get the start of kernel space
        addr_space = utils.load_as(self._config)
        kdbg = tasks.get_kdbg(addr_space)
        start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

        # 64-bit to 48-bit adjustment
        # TODO: Is there a more Volatility-esque way of doing this?
        if start > 0xffff000000000000:
            start = start & 0x0000ffffffffffff

        macs = set()  # Store the MAC addresses we find
        if self._config.MAC:
            macs.add(hex_mac)
        else:  # No MAC provided, so we'd better try and find one
            # Attemp 1: NDsh
            new_macs = self.macfind_ndsh(addr_space, start)
            if new_macs:
                for new_mac in new_macs:
                    macs.add(new_mac)

        if len(macs) < 1:
            debug.error('No MAC addresses found.')

        hits = []
        _MAX_SLACK_LENGTH = 128
        for session_space in self.gen_session_spaces(addr_space):

            for mac in macs:

                scanner = MacScanner(mac)

                for address in scanner.scan(session_space, offset=start):

                    if address in hits:
                        continue

                    hits.append(address)
                    eth = obj.Object('_ETHERNET',
                                     vm=session_space,
                                     offset=address)
                    if eth.eth_type == 0x0800 or eth.eth_type == 0x86dd:

                        raw = session_space.zread(address, 2048)

                        # Parse ethernet's payload
                        if eth.eth_type == 0x0800:  # IPv4:
                            eth_payload = obj.Object('_IPv4',
                                                     vm=session_space,
                                                     offset=eth.v() + 0x0E)
                            end = 14 + eth_payload.length
                            if self._config.SLACK:
                                yield address, raw[end:end + _MAX_SLACK_LENGTH]
                                continue
                            raw = raw[:end]
                        elif eth.eth_type == 0x86dd:  # IPv6
                            eth_payload = obj.Object('_IPv6',
                                                     vm=session_space,
                                                     offset=eth.v() + 0x0E)
                            end = 14 + 40 + eth_payload.pld_len
                            if self._config.SLACK:
                                yield address, raw[end:end + _MAX_SLACK_LENGTH]
                                continue
                            raw = raw[:end]
                        else:  # This shouldn't happen, but just in case
                            continue

                        # Parse ethernet's payload's payload
                        if eth_payload.is_tcp():
                            payload = obj.Object(
                                '_TCP',
                                vm=session_space,
                                offset=eth_payload.payload_offset())
                        elif eth_payload.is_udp():
                            payload = obj.Object(
                                '_UDP',
                                vm=session_space,
                                offset=eth_payload.payload_offset())
                        else:
                            yield raw, eth, eth_payload, None
                            continue
                        yield raw, eth, eth_payload, payload
예제 #38
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        # Get the OS version we're analyzing
        version = (addr_space.profile.metadata.get('major', 0),
                   addr_space.profile.metadata.get('minor', 0))

        modlist = list(modules.lsmod(addr_space))
        mods = dict(
            (addr_space.address_mask(mod.DllBase), mod) for mod in modlist)
        mod_addrs = sorted(mods.keys())

        # KTIMERs collected
        timers = []

        # Valid KTIMER.Header.Type values
        TimerNotificationObject = 8
        TimerSynchronizationObject = 9
        valid_types = (TimerNotificationObject, TimerSynchronizationObject)

        if version == (5, 1) or (version == (5, 2)
                                 and addr_space.profile.metadata.get(
                                     'build', 0) == 3789):

            # On XP SP0-SP3 x86 and Windows 2003 SP0, KiTimerTableListHead
            # is an array of 256 _LIST_ENTRY for _KTIMERs.

            if self._config.LISTHEAD:
                KiTimerTableListHead = self._config.LISTHEAD
            else:
                KiTimerTableListHead = self.find_list_head(
                    modlist[0], "KeUpdateSystemTime",
                    "\x25\xFF\x00\x00\x00\x8D\x0C\xC5")

            if not KiTimerTableListHead:
                debug.warning("Cannot find KiTimerTableListHead")
            else:
                lists = obj.Object("Array",
                                   offset=KiTimerTableListHead,
                                   vm=addr_space,
                                   targetType='_LIST_ENTRY',
                                   count=256)

                for l in lists:
                    for t in l.list_of_type("_KTIMER", "TimerListEntry"):
                        timers.append(t)

        elif version == (5, 2) or version == (6, 0):

            # On XP x64, Windows 2003 SP1-SP2, and Vista SP0-SP2, KiTimerTableListHead
            # is an array of 512 _KTIMER_TABLE_ENTRY structs.

            if self._config.LISTHEAD:
                KiTimerTableListHead = self._config.LISTHEAD
            else:
                if addr_space.profile.metadata.get("memory_model") == "32bit":
                    sigData = [
                        (False, "KeCancelTimer", "\xC1\xE7\x04\x81\xC7"),
                        (True, "KeUpdateSystemTime",
                         "\x48\xB9\x00\x00\x00\x00\x80\xF7\xFF\xFF\x4C\x8D\x1D"
                         )
                    ]
                else:
                    sigData = [
                        (
                            True, "KeCancelTimer",
                            "\x48\x8D\x4C\x6D\x00\x48\x8D\x05"
                        ),  # lea rcx, [rbp+rbp*2+0] / lea rax, KiTimerTableListHead (nt.dll md5 825926D6AD714A529F4069D9EBBD1D3B)
                        (True, "KeUpdateSystemTime",
                         "\x48\xB9\x00\x00\x00\x00\x80\xF7\xFF\xFF\x4C\x8D\x1D"
                         )  # mov     rcx, 0FFFFF78000000000h / lea r11, KiTimerTableListHead (xp64sp1/2k3sp2 B1E08186348ED662D50118618F012445)
                    ]
                for sig in sigData:
                    if sig[0]:
                        KiTimerTableListHead = self.find_list_head_offset(
                            modlist[0], sig[1], sig[2])
                    else:
                        KiTimerTableListHead = self.find_list_head(
                            modlist[0], sig[1], sig[2])
                    if KiTimerTableListHead:
                        break

            if not KiTimerTableListHead:
                debug.warning("Cannot find KiTimerTableListHead")
            else:
                lists = obj.Object("Array",
                                   offset=KiTimerTableListHead,
                                   vm=addr_space,
                                   targetType='_KTIMER_TABLE_ENTRY',
                                   count=512)

                for l in lists:
                    #                    print "List at %s" % hex(int(l.obj_offset))
                    for t in l.Entry.list_of_type("_KTIMER", "TimerListEntry"):
                        #                        print "Timer at %s" % hex(int(t.obj_offset))
                        timers.append(t)

        elif version >= (6, 1):

            # Starting with Windows 7, there is no more KiTimerTableListHead. The list is
            # at _KPCR.PrcbData.TimerTable.TimerEntries (credits to Matt Suiche
            # for this one. See http://pastebin.com/FiRsGW3f).
            for kpcr in tasks.get_kdbg(addr_space).kpcrs():
                for table in kpcr.ProcessorBlock.TimerTable.TimerEntries:
                    for t in table.Entry.list_of_type("_KTIMER",
                                                      "TimerListEntry"):
                        timers.append(t)

        for timer in timers:
            # Sanity check on the timer type
            if timer.Header.Type not in valid_types:
                #                print 'bad type %d' % timer.Header.Type
                continue

            # Ignore timers without DPCs
#            if not timer.Dpc.is_valid():
#                print 'dpc not valid'
#                continue
#            if not timer.Dpc.DeferredRoutine.is_valid():
#                print 'dpc deferredroutine not valid'
#                continue

# Lookup the module containing the DPC
            module = tasks.find_module(
                mods, mod_addrs,
                addr_space.address_mask(timer.Dpc.DeferredRoutine))

            yield timer, module
예제 #39
0
    def calculate(self):

        if not has_yara:
            debug.error("Please install Yara from code.google.com/p/yara-project")

        addr_space = utils.load_as(self._config)

        if self._config.YARA_RULES:
            s = self._config.YARA_RULES
            # Don't wrap hex or regex rules in quotes 
            if s[0] not in ("{", "/"): s = '"' + s + '"'
            # Scan for unicode strings 
            if self._config.WIDE: s += "wide"
            rules = yara.compile(sources = {
                        'n' : 'rule r1 {strings: $a = ' + s + ' condition: $a}'
                        })
        elif self._config.YARA_FILE:
            rules = yara.compile(self._config.YARA_FILE)
        else:
            debug.error("You must specify a string (-Y) or a rules file (-y)")

        if self._config.KERNEL:

            # Find KDBG so we know where kernel memory begins. Do not assume
            # the starting range is 0x80000000 because we may be dealing with
            # an image with the /3GB boot switch. 
            kdbg = tasks.get_kdbg(addr_space)

            start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

            # Modules so we can map addresses to owners
            mods = dict((mod.DllBase, mod)
                        for mod in modules.lsmod(addr_space))
            mod_addrs = sorted(mods.keys())

            # There are multiple views (GUI sessions) of kernel memory.
            # Since we're scanning virtual memory and not physical, 
            # all sessions must be scanned for full coverage. This 
            # really only has a positive effect if the data you're
            # searching for is in GUI memory. 
            sessions = []

            for proc in tasks.pslist(addr_space):
                sid = proc.SessionId
                # Skip sessions we've already seen 
                if sid == None or sid in sessions:
                    continue

                session_space = proc.get_process_address_space()
                if session_space == None:
                    continue

                sessions.append(sid)
                scanner = DiscontigYaraScanner(address_space = session_space,
                                               rules = rules)

                for hit, address in scanner.scan(start_offset = start):
                    module = tasks.find_module(mods, mod_addrs, address)
                    yield (module, address, hit, session_space.zread(address, 1024))

        else:
            for task in self.filter_tasks(tasks.pslist(addr_space)):
                scanner = VadYaraScanner(task = task, rules = rules)
                for hit, address in scanner.scan():
                    yield (task, address, hit, scanner.address_space.zread(address, 1024))
예제 #40
0
    def calculate(self):

        if self._config.SLACK and (self._config.DSTS or self._config.PCAP):
            debug.error('SLACK can\'t be used with PCAP or DSTS')
        
        # Make sure the MAC address is valid
        if self._config.MAC:
            hex_mac = self.validate_mac(self._config.MAC)
            if not hex_mac:
                debug.error('Invalid MAC address')
    
        # Ensure PCAP file won't overwrite an existing file
        if self._config.PCAP and os.path.exists(self._config.PCAP):
            debug.error('\'{}\' already exists.  Cowardly refusing to overwrite it...'.format(
                self._config.PCAP))

        # Ensure DSTS file won't overwrite an existing file
        if self._config.DSTS and os.path.exists(self._config.DSTS):
            debug.error('\'{}\' already exists.  Cowardly refusing to overwrite it...'.format(
                self._config.DSTS))

        if self._config.SLACK:
            # Compiled RegEx = (tiny) increase in efficiency
            # NetBIOS code chars
            self.rx_nbchars = re.compile('^([ACDEFH][A-P])+$')

        # Get the start of kernel space
        addr_space = utils.load_as(self._config)
        kdbg = tasks.get_kdbg(addr_space)
        start = kdbg.MmSystemRangeStart.dereference_as("Pointer")

        # 64-bit to 48-bit adjustment
        # TODO: Is there a more Volatility-esque way of doing this?
        if start > 0xffff000000000000:
            start = start & 0x0000ffffffffffff

        macs = set()  # Store the MAC addresses we find
        if self._config.MAC:
            macs.add(hex_mac)
        else:  # No MAC provided, so we'd better try and find one
            # Attemp 1: NDsh
            new_macs = self.macfind_ndsh(addr_space, start)
            if new_macs:
                for new_mac in new_macs:
                    macs.add(new_mac)
        
        if len(macs) < 1:
            debug.error('No MAC addresses found.')
        
        hits = []
        _MAX_SLACK_LENGTH = 128
        for session_space in self.gen_session_spaces(addr_space):
        
            for mac in macs:
            
                scanner = MacScanner(mac)
            
                for address in scanner.scan(session_space, offset=start):
                    
                    if address in hits:
                        continue
                
                    hits.append(address)
                    eth = obj.Object('_ETHERNET', vm=session_space, offset=address)
                    if eth.eth_type == 0x0800 or eth.eth_type == 0x86dd:
                        
                        raw = session_space.zread(address, 2048)
                        
                        # Parse ethernet's payload
                        if eth.eth_type == 0x0800: # IPv4:
                            eth_payload = obj.Object('_IPv4', vm=session_space,
                                offset = eth.v() + 0x0E)
                            end = 14 + eth_payload.length
                            if self._config.SLACK:
                                yield address, raw[end:end+_MAX_SLACK_LENGTH]
                                continue
                            raw = raw[:end]
                        elif eth.eth_type == 0x86dd: # IPv6
                            eth_payload = obj.Object('_IPv6', vm=session_space,
                                offset = eth.v() + 0x0E)
                            end = 14 + 40 + eth_payload.pld_len
                            if self._config.SLACK:
                                yield address, raw[end:end+_MAX_SLACK_LENGTH]
                                continue
                            raw = raw[:end]
                        else:  # This shouldn't happen, but just in case
                            continue
                        
                        # Parse ethernet's payload's payload
                        if eth_payload.is_tcp():
                            payload = obj.Object('_TCP', vm=session_space,
                                offset=eth_payload.payload_offset())
                        elif eth_payload.is_udp():
                            payload = obj.Object('_UDP', vm=session_space,
                                offset=eth_payload.payload_offset())
                        else:
                            yield raw, eth, eth_payload, None
                            continue
                        yield raw, eth, eth_payload, payload
예제 #41
0
    def calculate(self):
	## Stop executing if the user did not mean to overwrite the file
	if os.path.isfile(self.save_location):
		resp = raw_input("Are you sure you want to overwrite {}? [Y/n] ".format(self.save_location)) 
		if resp.upper() == 'N':
			self.abort = True
			return # Not continuing 

        ## Read from existing target configuration (if modifying)
        if self._config.MODIFY:
            self.new_config.read(self.save_location)


        ## Attempt to automatically determine profile
        if self._config.AUTO:
            print("Determining profile based on KDBG search...")
            self.suglist = [ s for s, _ in kdbgscan.KDBGScan.calculate(self)]
            if self.suglist:
                self.new_config.set("DEFAULT", "profile", self.suglist[0])
                ## Update profile so --offsets will work
                self._config.PROFILE = self.suglist[0]
                self._exclude_options.append('profile')
            else:
                print("Failed to determine profile")

        ## Read in current command line (precedence over settings in configs)
        for key in self._config.opts:
            if key not in self._exclude_options:
                self.new_config.set("DEFAULT", key, self._config.opts[key])
                ## Add to excluded list so we do not overwrite them later
                self._exclude_options.append(key)

        ## Save options from configuration files (unless excluded by user)
        if self._config.EXCLUDE_CONF == False:
            for key in self._config.cnf_opts:
                if key not in self._exclude_options:
                    self.new_config.set("DEFAULT", key, self._config.cnf_opts[key])

        ## Get offsets (KDBG and DTB)
        if self._config.OFFSETS:
            addr_space = utils.load_as(self._config)
            kdbg = tasks.get_kdbg(addr_space)
            self.new_config.set("DEFAULT", "kdbg", str(kdbg.v()))
            if hasattr(addr_space, "dtb"):
                self.new_config.set("DEFAULT", "dtb", str(addr_space.dtb))


        ## Ensure DTB and KDBG are converted properly at the last moment:
        ## Note, volatility will convert these to int when read from CNF_OPTS
        try:
            kdbg = self.new_config.get("DEFAULT", "kdbg")
            self.new_config.set("DEFAULT", "kdbg", str(hex(int(kdbg))))
        except ConfigParser.NoOptionError:
            pass
        try:
            dtb = self.new_config.get("DEFAULT", "dtb")
            self.new_config.set("DEFAULT", "dtb", str(hex(int(dtb))))
        except ConfigParser.NoOptionError:
            pass


        ## Write the new configuration file
        with open(self.save_location, "wb") as configfile:
            self.new_config.write(configfile)
예제 #42
0
파일: malfind.py 프로젝트: revers3r/PyMal
    def calculate(self):

        if not has_yara:
            debug.error("Please install Yara from code.google.com/p/yara-project")

        addr_space = utils.load_as(self._config)

        if self._config.YARA_RULES:
            s = self._config.YARA_RULES
            # Don't wrap hex or regex rules in quotes 
            if s[0] not in ("{", "/"): s = '"' + s + '"'
            # Scan for unicode strings 
            if self._config.WIDE: s += "wide"
            rules = yara.compile(sources = {
                        'n' : 'rule r1 {strings: $a = ' + s + ' condition: $a}'
                        })
        elif self._config.YARA_FILE:
            rules = yara.compile(self._config.YARA_FILE)
        else:
            debug.error("You must specify a string (-Y) or a rules file (-y)")

        if self._config.KERNEL:

            # Find KDBG so we know where kernel memory begins. Do not assume
            # the starting range is 0x80000000 because we may be dealing with
            # an image with the /3GB boot switch. 
            kdbg = tasks.get_kdbg(addr_space)

            # FIXME: Addresses should be truncated to 48 bits. Currently
            # we do that in Pointer.__eq__ but not in Pointer.v(). This prevents
            # module lookups in yarascan's --kernel mode on x64 from working
            # properly because win32.tasks.find_module cannot match the truncated
            # address with non-truncated mod.DllBase.v(). Changing Pointer.v()
            # could have wide spread effects, so this yarascan issue is fixed 
            # temporarily by giving YaraScan a private version of find_module
            # that performs the pointer truncation. After fixing this globally,
            # we can dereference MmSystemRangeStart as a Pointer instead of an 
            # address and then remove the manual bitmask below. 
            start = kdbg.MmSystemRangeStart.dereference_as("address")
            start = start & 0xffffffffffff

            # Modules so we can map addresses to owners
            mods = dict((mod.DllBase & 0xffffffffffff, mod)
                        for mod in modules.lsmod(addr_space))
            mod_addrs = sorted(mods.keys())

            # There are multiple views (GUI sessions) of kernel memory.
            # Since we're scanning virtual memory and not physical, 
            # all sessions must be scanned for full coverage. This 
            # really only has a positive effect if the data you're
            # searching for is in GUI memory. 
            sessions = []

            for proc in tasks.pslist(addr_space):
                sid = proc.SessionId
                # Skip sessions we've already seen 
                if sid == None or sid in sessions:
                    continue

                session_space = proc.get_process_address_space()
                if session_space == None:
                    continue

                sessions.append(sid)
                scanner = DiscontigYaraScanner(address_space = session_space,
                                               rules = rules)

                for hit, address in scanner.scan(start_offset = start):
                    module = self.find_module(mods, mod_addrs, address)
                    yield (module, address, hit, session_space.zread(address, 1024))

        else:
            for task in self.filter_tasks(tasks.pslist(addr_space)):
                scanner = VadYaraScanner(task = task, rules = rules)
                for hit, address in scanner.scan():
                    yield (task, address, hit, scanner.address_space.zread(address, 1024))