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

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

        ssdts = set()

        if addr_space.profile.metadata.get('memory_model', '32bit') == '32bit':
            # Gather up all SSDTs referenced by threads
            debug.info("[x86] Gathering all referenced SSDTs from KTHREADs...")
            for proc in tasks.pslist(addr_space):
                for thread in proc.ThreadListHead.list_of_type(
                        "_ETHREAD", "ThreadListEntry"):
                    ssdt_obj = thread.Tcb.ServiceTable.dereference_as(
                        '_SERVICE_DESCRIPTOR_TABLE')
                    ssdts.add(ssdt_obj)
        else:
            debug.info(
                "[x64] Gathering all referenced SSDTs from KeAddSystemServiceTable..."
            )
            # The NT module always loads first
            ntos = list(modules.lsmod(addr_space))[0]
            func_rva = ntos.getprocaddress("KeAddSystemServiceTable")
            if func_rva == None:
                raise StopIteration("Cannot locate KeAddSystemServiceTable")
            KeAddSystemServiceTable = ntos.DllBase + func_rva
            for table_rva in find_tables(KeAddSystemServiceTable, addr_space):
                ssdt_obj = obj.Object("_SERVICE_DESCRIPTOR_TABLE",
                                      ntos.DllBase + table_rva, addr_space)
                ssdts.add(ssdt_obj)

        # Get a list of *unique* SSDT entries. Typically we see only two.
        tables = set()

        for ssdt_obj in ssdts:
            for i, desc in enumerate(ssdt_obj.Descriptors):
                # Apply some extra checks - KiServiceTable should reside in kernel memory and ServiceLimit
                # should be greater than 0 but not unbelievably high
                if not desc.is_valid(
                ) or desc.ServiceLimit <= 0 or desc.ServiceLimit >= 0xFFFF or desc.KiServiceTable <= 0x80000000:
                    break
                else:
                    tables.add(
                        (i, desc.KiServiceTable.v(), desc.ServiceLimit.v()))

        debug.info("Finding appropriate address space for tables...")
        tables_with_vm = []
        procs = list(tasks.pslist(addr_space))
        for idx, table, n in tables:
            vm = tasks.find_space(addr_space, procs, table)
            if vm:
                tables_with_vm.append((idx, table, n, vm))
            else:
                debug.debug("[SSDT not resident at 0x{0:08X}]\n".format(table))

        for idx, table, n, vm in sorted(tables_with_vm, key=itemgetter(0)):
            yield idx, table, n, vm, mods, mod_addrs
Beispiel #2
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

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

        ssdts = set()

        if addr_space.profile.metadata.get("memory_model", "32bit") == "32bit":
            # Gather up all SSDTs referenced by threads
            print "[x86] Gathering all referenced SSDTs from KTHREADs..."
            for proc in tasks.pslist(addr_space):
                for thread in proc.ThreadListHead.list_of_type("_ETHREAD", "ThreadListEntry"):
                    ssdt_obj = thread.Tcb.ServiceTable.dereference_as("_SERVICE_DESCRIPTOR_TABLE")
                    ssdts.add(ssdt_obj)
        else:
            print "[x64] Gathering all referenced SSDTs from KeAddSystemServiceTable..."
            # The NT module always loads first
            ntos = list(modules.lsmod(addr_space))[0]
            func_rva = ntos.getprocaddress("KeAddSystemServiceTable")
            if func_rva == None:
                raise StopIteration("Cannot locate KeAddSystemServiceTable")
            KeAddSystemServiceTable = ntos.DllBase + func_rva
            for table_rva in find_tables(KeAddSystemServiceTable, addr_space):
                ssdt_obj = obj.Object("_SERVICE_DESCRIPTOR_TABLE", ntos.DllBase + table_rva, addr_space)
                ssdts.add(ssdt_obj)

        # Get a list of *unique* SSDT entries. Typically we see only two.
        tables = set()

        for ssdt_obj in ssdts:
            for i, desc in enumerate(ssdt_obj.Descriptors):
                # Apply some extra checks - KiServiceTable should reside in kernel memory and ServiceLimit
                # should be greater than 0 but not unbelievably high
                if (
                    desc.is_valid()
                    and desc.ServiceLimit > 0
                    and desc.ServiceLimit < 0xFFFF
                    and desc.KiServiceTable > 0x80000000
                ):
                    tables.add((i, desc.KiServiceTable.v(), desc.ServiceLimit.v()))

        print "Finding appropriate address space for tables..."
        tables_with_vm = []
        procs = list(tasks.pslist(addr_space))
        for idx, table, n in tables:
            vm = tasks.find_space(addr_space, procs, table)
            if vm:
                tables_with_vm.append((idx, table, n, vm))
            else:
                debug.debug("[SSDT not resident at 0x{0:08X}]\n".format(table))

        for idx, table, n, vm in sorted(tables_with_vm, key=itemgetter(0)):
            yield idx, table, n, vm, mods, mod_addrs
 def driver_dump(self):
     procs = list(tasks.pslist(self.addr_space))
     mods = dict(
         (mod.DllBase.v(), mod) for mod in modules.lsmod(self.addr_space))
     for mod in mods.values():
         mod_base = mod.DllBase.v()
         mode_end = mod_base + mod.SizeOfImage
         space = tasks.find_space(self.addr_space, procs, mod_base)
         if space:
             pe_data = self.get_pe_content(space, mod_base)
             if self._config.LIST_SECTIONS:
                 yield PESection(mod.BaseDllName,
                                 self.get_pe_sections(pe_data))
             else:
                 sections = self.process_section(None, self._config.SECTION,
                                                 pe_data)
                 for sec in sections:
                     for engine in self.hash_engines:
                         yield DriverObject(sec['data'], mod_base, mode_end,
                                            mod.FullDllName, engine,
                                            sec['section'])
                         if self._config.TMP_FOLDER:
                             dump_path = os.path.join(
                                 self._config.TMP_FOLDER,
                                 'driver.{0:x}.{1}{2}.sys'.format(
                                     mod_base, mod.BaseDllName,
                                     sec['section']))
                             self.backup_file(dump_path, sec['data'])
Beispiel #4
0
    def render_text(self, outfd, data):

        # Kernel AS for looking up modules 
        kernel_space = utils.load_as(self._config)

        # Modules sorted for address lookups 
        mods = dict((kernel_space.address_mask(mod.DllBase), mod) for mod in modules.lsmod(kernel_space))
        mod_addrs = sorted(mods.keys())

        for session in data:
            outfd.write("*" * 50 + "\n")
            outfd.write("Session(V): {0:x} ID: {1} Processes: {2}\n".format(
                session.obj_offset,
                session.SessionId,
                len(list(session.processes())),
                ))
            outfd.write("PagedPoolStart: {0:x} PagedPoolEnd {1:x}\n".format(
                session.PagedPoolStart,
                session.PagedPoolEnd,
                ))
            for process in session.processes():
                outfd.write(" Process: {0} {1} {2}\n".format(
                    process.UniqueProcessId,
                    process.ImageFileName,
                    process.CreateTime,
                    ))
            for image in session.images():
                module = tasks.find_module(mods, mod_addrs, kernel_space.address_mask(image.Address))
                outfd.write(" Image: {0:#x}, Address {1:x}, Name: {2}\n".format(
                    image.obj_offset,
                    image.Address,
                    str(module and module.BaseDllName or '')
                    ))
Beispiel #5
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))
Beispiel #6
0
    def render_text(self, outfd, data):

        # Kernel AS for looking up modules
        kernel_space = utils.load_as(self._config)

        # Modules sorted for address lookups
        mods = dict((kernel_space.address_mask(mod.DllBase), mod)
                    for mod in modules.lsmod(kernel_space))
        mod_addrs = sorted(mods.keys())

        for session in data:
            outfd.write("*" * 50 + "\n")
            outfd.write("Session(V): {0:x} ID: {1} Processes: {2}\n".format(
                session.obj_offset,
                session.SessionId,
                len(list(session.processes())),
            ))
            outfd.write("PagedPoolStart: {0:x} PagedPoolEnd {1:x}\n".format(
                session.PagedPoolStart,
                session.PagedPoolEnd,
            ))
            for process in session.processes():
                outfd.write(" Process: {0} {1} {2}\n".format(
                    process.UniqueProcessId,
                    process.ImageFileName,
                    process.CreateTime,
                ))
            for image in session.images():
                module = tasks.find_module(
                    mods, mod_addrs, kernel_space.address_mask(image.Address))
                outfd.write(
                    " Image: {0:#x}, Address {1:x}, Name: {2}\n".format(
                        image.obj_offset, image.Address,
                        str(module and module.BaseDllName or '')))
Beispiel #7
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
    def calculate(self):
        addr_space = utils.load_as(self._config)

        if self._config.REGEX:
            try:
                if self._config.IGNORE_CASE:
                    mod_re = re.compile(self._config.REGEX, re.I)
                else:
                    mod_re = re.compile(self._config.REGEX)
            except re.error as e:
                debug.error('Error parsing regular expression: %s' % e)

        mods = dict((mod.DllBase.v(), mod) for mod in modules.lsmod(addr_space))
        # We need the process list to find spaces for some drivers. Enumerate them here
        # instead of inside the find_space function, so we only have to do it once. 
        procs = list(tasks.pslist(addr_space))

        if self._config.BASE:
            if self._config.BASE in mods:
                mod_name = mods[self._config.BASE].BaseDllName
            else:
                mod_name = "UNKNOWN"
            yield addr_space, procs, int(self._config.BASE), mod_name
        else:
            for mod in list(mods.values()):
                if self._config.REGEX:
                    if not mod_re.search(str(mod.FullDllName or '')) and not mod_re.search(str(mod.BaseDllName or '')):
                        continue
                yield addr_space, procs, mod.DllBase.v(), mod.BaseDllName
Beispiel #9
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
Beispiel #10
0
 def __init__(self, start, stack_base, stack_limit, eproc, modules=None, module_addrs=None, *args, **kwargs):
   EBP.__init__(self, start, stack_base, stack_limit, eproc, *args, **kwargs)
   if modules == None:
     self.modules = dict( (m.DllBase, m) for m in list(sysmods.lsmod(eproc.get_process_address_space())) + list(eproc.get_load_modules()) )
     self.module_addrs = sorted(self.modules.keys())
   else:
     self.modules = modules
     self.module_addrs = module_addrs
   mod = tasks.find_module(self.modules, self.module_addrs, self.eip)
   self.security_cookie = None
   self.cookie = None
   security_cookie_addr = None
   if mod != None:
     load_config = mod.get_load_config_directory()
     if load_config == None:
       # Attempt to use PDB symbols to locate this module's ___security_cookie
       addrs = eproc.lookup("{0}/.data!___security_cookie".format(str(mod.BaseDllName)))
       if len(addrs) > 0:
         security_cookie_addr = addrs[0]
     else:
       # Use _IMAGE_LOAD_CONFIG_DIRECTORY to locate this module's ___security_cookie
       security_cookie_addr = load_config.SecurityCookie
     if security_cookie_addr != None and self.addrspace.is_valid_address(security_cookie_addr):
       self.security_cookie = self.addrspace.read_long_phys(self.addrspace.vtop(security_cookie_addr))
     if self.addrspace.is_valid_address(self.ebp - self.alignment):
       self.cookie = self.addrspace.read_long_phys(self.addrspace.vtop(self.ebp - self.alignment))
Beispiel #11
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        if self._config.REGEX:
            try:
                if self._config.IGNORE_CASE:
                    mod_re = re.compile(self._config.REGEX, re.I)
                else:
                    mod_re = re.compile(self._config.REGEX)
            except re.error as e:
                debug.error('Error parsing regular expression: {0}'.format(e))

        mods = dict(
            (mod.DllBase.v(), mod) for mod in modules.lsmod(addr_space))
        # We need the process list to find spaces for some drivers. Enumerate them here
        # instead of inside the find_space function, so we only have to do it once.
        procs = list(tasks.pslist(addr_space))

        if self._config.BASE:
            if self._config.BASE in mods:
                mod_name = mods[self._config.BASE].BaseDllName
            else:
                mod_name = "UNKNOWN"
            yield addr_space, procs, int(self._config.BASE), mod_name
        else:
            for mod in list(mods.values()):
                if self._config.REGEX:
                    if not mod_re.search(str(mod.FullDllName
                                             or '')) and not mod_re.search(
                                                 str(mod.BaseDllName or '')):
                        continue
                yield addr_space, procs, mod.DllBase.v(), mod.BaseDllName
Beispiel #12
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        tasklist = []
        modslist = []

        if self._config.SCAN:
            if not self._config.KERNEL_ONLY:
                for t in filescan.PSScan(self._config).calculate():
                    v = self.virtual_process_from_physical_offset(addr_space, t.obj_offset)
                    if v:
                        tasklist.append(v)
            if not self._config.PROCESS_ONLY:
                modslist = [m for m in modscan.ModScan(self._config).calculate()]
        else:
            if not self._config.KERNEL_ONLY:
                tasklist = [t for t in tasks.pslist(addr_space)]
            if not self._config.PROCESS_ONLY:
                modslist = [m for m in modules.lsmod(addr_space)]

        for task in tasklist:
            for mod in task.get_load_modules():
                yield task, mod

        for mod in modslist:
            yield None, mod
Beispiel #13
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        tasklist = []
        modslist = []

        if self._config.SCAN:
            if not self._config.KERNEL_ONLY:
                for t in filescan.PSScan(self._config).calculate():
                    v = self.virtual_process_from_physical_offset(addr_space, t.obj_offset)
                    if v:
                        tasklist.append(v)
            if not self._config.PROCESS_ONLY:
                modslist = [m for m in modscan.ModScan(self._config).calculate()]
        else:
            if not self._config.KERNEL_ONLY:
                tasklist = [t for t in tasks.pslist(addr_space)]
            if not self._config.PROCESS_ONLY:
                modslist = [m for m in modules.lsmod(addr_space)]

        for task in tasklist:
            for mod in task.get_load_modules():
                yield task, mod

        for mod in modslist:
            yield None, mod
Beispiel #14
0
    def gather_exports_symbols_values(self):

        symbols_values = []
        addr_space = utils.load_as(self._config)

        #############################
        # collect kernel mode exports
        if self._config.PID == None:
            all_mods = list(modules.lsmod(addr_space))
            for mod in all_mods:
                if mod.DllBase != self._config.BASE:
                    dllBaseAppended = False
                    for ordinal, func_addr, func_name in mod.exports():
                        if func_addr != None:
                            name = func_name or ordinal or ''
                            if self._config.AGGRESIVE or (
                                    "%s" % mod.BaseDllName
                            ).lower() in self.kernel_common_mods:
                                if self._config.DLLBASES and not dllBaseAppended:
                                    symbols_values.append(
                                        (mod.DllBase,
                                         ("dllbase_%s" %
                                          mod.BaseDllName).replace(
                                              ".", "_").lower()))
                                    dllBaseAppended = True
                                symbols_values.append(
                                    (mod.DllBase + func_addr, str(name)
                                     ))  #"%s_%s" % (mod.BaseDllName, name))

        ###########################
        # collect user mode exports
        # for specified process
        else:
            for prc in tasks.pslist(addr_space):
                if prc.UniqueProcessId == self._config.PID:
                    #addr_space = prc.get_process_address_space()
                    for mod in prc.get_load_modules():
                        if mod.DllBase != self._config.BASE:
                            dllBaseAppended = False
                            for ordinal, func_addr, func_name in mod.exports():
                                if func_addr != None:
                                    name = func_name or ordinal or ''
                                    if self._config.AGGRESIVE or (
                                            "%s" % mod.BaseDllName
                                    ).lower() in self.user_common_mods:
                                        if self._config.DLLBASES and not dllBaseAppended:
                                            symbols_values.append(
                                                (mod.DllBase,
                                                 ("dllbase_%s" %
                                                  mod.BaseDllName).replace(
                                                      ".", "_").lower()))
                                            dllBaseAppended = True
                                        symbols_values.append(
                                            (mod.DllBase + func_addr,
                                             str(name))
                                        )  #"%s_%s" % (mod.BaseDllName, name)))
                    break

        return symbols_values
Beispiel #15
0
class ModDump(procdump.ProcDump):
    """Dump a kernel driver to an executable file sample"""
    def __init__(self, config, *args, **kwargs):
        procdump.ProcDump.__init__(self, config, *args, **kwargs)
        config.remove_option("PID")
        config.remove_option("OFFSET")
        config.remove_option("NAME")
        config.add_option('REGEX',
                          short_option='r',
                          help='Dump modules matching REGEX',
                          action='store',
                          type='string')
        config.add_option('IGNORE-CASE',
                          short_option='i',
                          help='Ignore case in pattern match',
                          action='store_true',
                          default=False)
        config.add_option('BASE',
                          short_option='b',
                          default=None,
                          help='Dump driver with BASE address (in hex)',
                          action='store',
                          type='int')

    @cache.CacheDecorator(
        lambda self: "tests/moddump/regex={0}/ignore-case={1}/base={2}".format(
            self._config.REGEX, self._config.IGNORE_CASE, self._config.BASE))
    def calculate(self):
        addr_space = utils.load_as(self._config)

        if self._config.REGEX:
            try:
                if self._config.IGNORE_CASE:
                    mod_re = re.compile(self._config.REGEX, re.I)
                else:
                    mod_re = re.compile(self._config.REGEX)
            except re.error, e:
                debug.error('Error parsing regular expression: {0}'.format(e))

        mods = dict(
            (mod.DllBase.v(), mod) for mod in modules.lsmod(addr_space))
        # We need the process list to find spaces for some drivers. Enumerate them here
        # instead of inside the find_space function, so we only have to do it once.
        procs = list(tasks.pslist(addr_space))

        if self._config.BASE:
            if mods.has_key(self._config.BASE):
                mod_name = mods[self._config.BASE].BaseDllName
            else:
                mod_name = "UNKNOWN"
            yield addr_space, procs, int(self._config.BASE), mod_name
        else:
            for mod in mods.values():
                if self._config.REGEX:
                    if not mod_re.search(str(mod.FullDllName
                                             or '')) and not mod_re.search(
                                                 str(mod.BaseDllName or '')):
                        continue
                yield addr_space, procs, mod.DllBase.v(), mod.BaseDllName
Beispiel #16
0
    def render_text(self, outfd, data):

        addr_space = utils.load_as(self._config)

        # Compile the regular expression for filtering by driver name
        if self._config.regex != None:
            mod_re = re.compile(self._config.regex, re.I)
        else:
            mod_re = None

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

        bits = addr_space.profile.metadata.get('memory_model', '32bit')

        self.table_header(None, [('i', ">4"), ('Funcs', "36"),
                                 ('addr', '[addrpad]'), ('name', '')])

        for object_obj, driver_obj, _ in data:
            driver_name = str(object_obj.NameInfo.Name or '')
            # Continue if a regex was supplied and it doesn't match
            if mod_re != None:
                if not (mod_re.search(driver_name)
                        or mod_re.search(driver_name)):
                    continue

            # Write the standard header for each driver object
            outfd.write("{0}\n".format("-" * 50))
            outfd.write("DriverName: {0}\n".format(driver_name))
            outfd.write("DriverStart: {0:#x}\n".format(driver_obj.DriverStart))
            outfd.write("DriverSize: {0:#x}\n".format(driver_obj.DriverSize))
            outfd.write("DriverStartIo: {0:#x}\n".format(
                driver_obj.DriverStartIo))

            # Write the address and owner of each IRP function
            for i, function in enumerate(driver_obj.MajorFunction):
                function = driver_obj.MajorFunction[i]
                module = tasks.find_module(mods, mod_addrs,
                                           addr_space.address_mask(function))
                if module:
                    module_name = str(module.BaseDllName or '')
                else:
                    module_name = "Unknown"
                # This is where we check for inline hooks once the
                # ApiHooks plugin is ported to 2.1.
                self.table_row(outfd, i, MAJOR_FUNCTIONS[i], function,
                               module_name)

                if self._config.verbose:
                    data = addr_space.zread(function, 64)
                    outfd.write("\n".join([
                        "{0:#x} {1:<16} {2}".format(o, h, i)
                        for o, i, h in malfind.Disassemble(data=data,
                                                           start=function,
                                                           bits=bits,
                                                           stoponret=True)
                    ]))
                    outfd.write("\n")
Beispiel #17
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

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

        drivers = dtree.DriverIrp(self._config).calculate()
        driver_name = "UNKNOWN"
        service_key = "UNKNOWN"
        driver_name3 = "UNKNOWN"
        module_name = "UNKNOWN"

        if self._config.ADDR:
            find_address = self._config.ADDR

            module_name = tasks.find_module(
                mods,
                mod_addrs,
                list(mods.values())[0].obj_vm.address_mask(find_address),
            )
            if module_name:
                module_name = (module_name.BaseDllName
                               or module_name.FullDllName)

            for driver in drivers:
                if (driver.DriverStart <= find_address <
                        driver.DriverStart + driver.DriverSize):
                    header = driver.get_object_header()
                    driver_name = header.NameInfo.Name
                    driver_name = str(driver.get_object_header().NameInfo.Name
                                      or '')
                    service_key = str(driver.DriverExtension.ServiceKeyName
                                      or '')
                    driver_name3 = str(driver.DriverName or '')
                    break

            yield (module_name, driver_name, service_key, driver_name3)

        else:
            for driver in drivers:
                driver_name = str(driver.get_object_header().NameInfo.Name
                                  or '')
                service_key = str(driver.DriverExtension.ServiceKeyName or '')
                driver_name3 = str(driver.DriverName or '')

                owning_module = tasks.find_module(
                    mods,
                    mod_addrs,
                    list(mods.values())[0].obj_vm.address_mask(
                        driver.DriverStart),
                )
                module_name = "UNKNOWN"
                if owning_module:
                    module_name = (owning_module.BaseDllName
                                   or owning_module.FullDllName)

                yield (module_name, driver_name, service_key, driver_name3)
Beispiel #18
0
    def render_text(self, outfd, data):

        addr_space = utils.load_as(self._config)

        # Compile the regular expression for filtering by driver name 
        if self._config.regex != None:
            mod_re = re.compile(self._config.regex, re.I)
        else:
            mod_re = None

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

        bits = addr_space.profile.metadata.get('memory_model', '32bit')

        self.table_header(None, [('i', ">4"),
                                 ('Funcs', "36"),
                                 ('addr', '[addrpad]'),
                                 ('name', '')
                                 ])

        for driver in data:

            header = driver.get_object_header()

            driver_name = str(header.NameInfo.Name or '')
            # Continue if a regex was supplied and it doesn't match 
            if mod_re != None:
                if not (mod_re.search(driver_name) or
                        mod_re.search(driver_name)): continue

            # Write the standard header for each driver object 
            outfd.write("{0}\n".format("-" * 50))
            outfd.write("DriverName: {0}\n".format(driver_name))
            outfd.write("DriverStart: {0:#x}\n".format(driver.DriverStart))
            outfd.write("DriverSize: {0:#x}\n".format(driver.DriverSize))
            outfd.write("DriverStartIo: {0:#x}\n".format(driver.DriverStartIo))

            # Write the address and owner of each IRP function 
            for i, function in enumerate(driver.MajorFunction):
                function = driver.MajorFunction[i]
                module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(function))
                if module:
                    module_name = str(module.BaseDllName or '')
                else:
                    module_name = "Unknown"
                # This is where we check for inline hooks once the 
                # ApiHooks plugin is ported to 2.1. 
                self.table_row(outfd, i, MAJOR_FUNCTIONS[i], function, module_name)

                if self._config.verbose:
                    data = addr_space.zread(function, 64)
                    outfd.write("\n".join(
                        ["{0:#x} {1:<16} {2}".format(o, h, i)
                        for o, i, h in malfind.Disassemble(data = data, 
                            start = function, bits = bits, stoponret = True)
                    ]))
                    outfd.write("\n")
Beispiel #19
0
 def calculate(self):
     addr_space = utils.load_as(self._config)
     for mod in modules.lsmod(addr_space):
         # Finding the VC kernel module
         if str(mod.BaseDllName).lower() == "veracrypt.sys" or str(
                 mod.BaseDllName).lower() == "veracrypt-x64.sys":
             for offset, password in self.scan_module(
                     addr_space, mod.DllBase, self._config.MIN_LENGTH):
                 yield offset, password
Beispiel #20
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))
Beispiel #21
0
    def calculate(self):
        addr_space = utils.load_as(self._config)
        addr_space.profile.add_types(sde_types)

        if addr_space.profile.metadata.get("major", 0) == 5 and addr_space.profile.metadata.get("minor", 0) == 2:
            addr_space.profile.add_types(sdt_types_2k3)
        else:
            addr_space.profile.add_types(sdt_types)

        ## Get a sorted list of module addresses
        mods = dict((mod.DllBase.v(), mod) for mod in modules.lsmod(addr_space))
        mod_addrs = sorted(mods.keys())

        # Gather up all SSDTs referenced by threads
        print "Gathering all referenced SSDTs from KTHREADs..."
        ssdts = set()
        for proc in tasks.pslist(addr_space):
            for thread in proc.ThreadListHead.list_of_type("_ETHREAD", "ThreadListEntry"):
                ssdt_obj = thread.Tcb.ServiceTable.dereference_as("_SERVICE_DESCRIPTOR_TABLE")
                ssdts.add(ssdt_obj)

        # Get a list of *unique* SSDT entries. Typically we see only two.
        tables = set()

        for ssdt_obj in ssdts:
            for i, desc in enumerate(ssdt_obj.Descriptors):
                # Apply some extra checks - KiServiceTable should reside in kernel memory and ServiceLimit
                # should be greater than 0 but not unbelievably high
                if (
                    desc.is_valid()
                    and desc.ServiceLimit > 0
                    and desc.ServiceLimit < 0xFFFF
                    and desc.KiServiceTable > 0x80000000
                ):
                    tables.add((i, desc.KiServiceTable.v(), desc.ServiceLimit.v()))

        print "Finding appropriate address space for tables..."
        tables_with_vm = []
        for idx, table, n in tables:
            found = False
            for p in tasks.pslist(addr_space):
                ## This is the process address space
                ps_ad = p.get_process_address_space()
                ## Is the table accessible from the process AS?
                if ps_ad.is_valid_address(table):
                    tables_with_vm.append((idx, table, n, ps_ad))
                    found = True
                    break
            ## If not we use the kernel address space
            if not found:
                # Any VM is equally bad...
                tables_with_vm.append((idx, table, n, addr_space))

        for idx, table, n, vm in sorted(tables_with_vm, key=itemgetter(0)):
            yield idx, table, n, vm, mods, mod_addrs
Beispiel #22
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        for mod in modules.lsmod(addr_space):

            # Finding the TC kernel module
            if str(mod.BaseDllName).lower() != "truecrypt.sys":
                continue

            for offset, password in self.scan_module(addr_space, mod.DllBase, self._config.MIN_LENGTH):
                yield offset, password
Beispiel #23
0
    def calculate(self):
        if self._config.TAP_FILE is None or not os.path.exists(
                self._config.TAP_FILE):
            debug.error("Tap file not found")
        taplist = open(self._config.TAP_FILE, "r")

        taps = []
        for line in taplist:
            line = line.split()
            (stack, cr3) = line[:-1], line[-1]
            try:
                stack = [int(s, 16) for s in stack]
                cr3 = int(cr3, 16)
            except ValueError:
                debug.error("Tap file format invalid.")
            taps.append((stack, cr3))

        cr3s = set(t[1] for t in taps)
        cr3s.discard(0)

        # First do the userland ones
        addr_space = utils.load_as(self._config)
        procs = list(tasks.pslist(addr_space))
        # CR3 => proc mapping
        proc_map = {}
        for proc in procs:
            dtb = proc.Pcb.DirectoryTableBase.v()
            if dtb in cr3s: proc_map[dtb] = proc

        for cr3, proc in proc_map.items():
            print ">>> Working on {0}[{1}]".format(proc.ImageFileName,
                                                   proc.UniqueProcessId)

            ps_ad = proc.get_process_address_space()
            proc_taps = [t for t in taps if t[1] == cr3]
            mods = list(proc.get_load_modules())
            sorted_mods = sorted([(m.DllBase.v(), m.SizeOfImage.v(),
                                   str(m.BaseDllName)) for m in mods])

            for v in self.resolve_taps(proc_taps, sorted_mods,
                                       lambda m: ps_ad):
                yield v + (proc.ImageFileName, )

        # Now kernel mode taps
        print ">>> Working on kernel taps"
        kern_taps = [t for t in taps if t[1] == 0]
        sorted_mods = sorted([(mod.DllBase.v(), mod.SizeOfImage.v(),
                               str(mod.BaseDllName))
                              for mod in modules.lsmod(addr_space)])
        bases = [m[0] for m in sorted_mods]
        for v in self.resolve_taps(
                kern_taps, sorted_mods,
                lambda m: tasks.find_space(addr_space, procs, m)):
            yield v + ("Kernel", )
Beispiel #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 = 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))
Beispiel #25
0
    def calculate(self):
        # All scanners will share a kernel and physical space
        self.kern_space = utils.load_as(self._config)
        self.phys_space = utils.load_as(self._config, astype='physical')

        # We currently dont support x64
        if not self.is_valid_profile(self.kern_space.profile):
            debug.error("This command does not support the selected profile.")

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

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

        # First few routines are valid on all OS versions
        for info in self.get_fs_callbacks():
            yield info, mods, mod_addrs

        for info in self.get_bugcheck_callbacks():
            yield info, mods, mod_addrs

        for info in self.get_shutdown_callbacks():
            yield info, mods, mod_addrs

        for info in self.get_generic_callbacks():
            yield info, mods, mod_addrs

        for info in self.get_bugcheck_reason_callbacks(modlist[0]):
            yield info, mods, mod_addrs

        for info in self.get_kernel_callbacks(modlist[0]):
            yield info, mods, mod_addrs

        # Valid for Vista and later
        if version >= (6, 0):
            for info in self.get_dbgprint_callbacks():
                yield info, mods, mod_addrs

            for info in self.get_registry_callbacks():
                yield info, mods, mod_addrs

            for info in self.get_pnp_callbacks():
                yield info, mods, mod_addrs

        # Valid for XP
        if version == (5, 1):
            for info in self.get_registry_callbacks_legacy(modlist[0]):
                yield info, mods, mod_addrs
Beispiel #26
0
    def calculate(self):
        # All scanners will share a kernel and physical space 
        self.kern_space = utils.load_as(self._config)
        self.phys_space = utils.load_as(self._config, astype = 'physical')

        # We currently dont support x64
        if not self.is_valid_profile(self.kern_space.profile):
            debug.error("This command does not support the selected profile.")

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

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

        # First few routines are valid on all OS versions 
        for info in self.get_fs_callbacks():
            yield info, mods, mod_addrs

        for info in self.get_bugcheck_callbacks():
            yield info, mods, mod_addrs

        for info in self.get_shutdown_callbacks():
            yield info, mods, mod_addrs

        for info in self.get_generic_callbacks():
            yield info, mods, mod_addrs

        for info in self.get_bugcheck_reason_callbacks(modlist[0]):
            yield info, mods, mod_addrs

        for info in self.get_kernel_callbacks(modlist[0]):
            yield info, mods, mod_addrs

        # Valid for Vista and later
        if version >= (6, 0):
            for info in self.get_dbgprint_callbacks():
                yield info, mods, mod_addrs

            for info in self.get_registry_callbacks():
                yield info, mods, mod_addrs

            for info in self.get_pnp_callbacks():
                yield info, mods, mod_addrs

        # Valid for XP 
        if version == (5, 1):
            for info in self.get_registry_callbacks_legacy(modlist[0]):
                yield info, mods, mod_addrs
Beispiel #27
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
Beispiel #28
0
    def Win32KBase(self):
        """Get the base address of the win32k.sys as mapped 
        into this session's memory. 

        Since win32k.sys is always the first image to be 
        mapped, we can just grab the first list entry.

        Update: we no longer use the session image list, because
        it seems to have gone away in Win8/2012."""

        for mod in modules.lsmod(self.obj_vm):
            if str(mod.BaseDllName or '').lower() == "win32k.sys":
                return mod.DllBase
        return obj.Object("Cannot find win32k.sys base address")
Beispiel #29
0
    def Win32KBase(self):
        """Get the base address of the win32k.sys as mapped 
        into this session's memory. 

        Since win32k.sys is always the first image to be 
        mapped, we can just grab the first list entry.

        Update: we no longer use the session image list, because
        it seems to have gone away in Win8/2012."""
        
        for mod in modules.lsmod(self.obj_vm):
            if str(mod.BaseDllName or '').lower() == "win32k.sys":
                return mod.DllBase
        return obj.Object("Cannot find win32k.sys base address")
Beispiel #30
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
                    ),
                )
Beispiel #31
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        for mod in modules.lsmod(addr_space):

            # Finding the TC kernel module
            if str(mod.BaseDllName).lower() != "truecrypt.sys":
                continue

            dos_header = obj.Object("_IMAGE_DOS_HEADER", 
                                    offset = mod.DllBase, 
                                    vm = addr_space)
            nt_header = dos_header.get_nt_header()

            # Finding the PE data section 
            data_section = None
            for sec in nt_header.get_sections():
                if str(sec.Name) == ".data":
                    data_section = sec
                    break
 
            if not data_section:
                break

            base = sec.VirtualAddress + mod.DllBase
            size = sec.Misc.VirtualSize

            # Looking for the Length member, DWORD-aligned 
            ints = obj.Object("Array", targetType = "int", 
                              offset = base, count = size / 4, 
                              vm = addr_space)
        
            for length in ints:
                # Min and max passphrase lengths 
                if length >= self._config.MIN_LENGTH and length <= 64:
                    offset = length.obj_offset + 4
                    passphrase = addr_space.read(offset, length)
                    if not passphrase:
                        continue
                    # All characters in the range must be ASCII
                    chars = [c for c in passphrase if ord(c) >= 0x20 and ord(c) <= 0x7F]
                    if len(chars) != length:
                        continue
                    # At least three zero-bad bytes must follow 
                    if addr_space.read(offset + length, 3) != "\x00" * 3:
                        continue
                    yield offset, passphrase 
Beispiel #32
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)
Beispiel #33
0
 def get_target_mod_name(self):
     addr_space = utils.load_as(self._config)
     # kernel mod
     if self._config.PID == None:         
         all_mods = list(modules.lsmod(addr_space))            
         for mod in all_mods:
             if self._config.BASE == mod.DllBase: 
                 return os.path.splitext(str(mod.BaseDllName))[0]
     # user mod
     else:
         for prc in tasks.pslist(addr_space):
             if prc.UniqueProcessId == self._config.PID:
                 print "pid: %d" % prc.UniqueProcessId
                 for mod in prc.get_load_modules():
                     print "mod: %x" % mod.DllBase
                     if self._config.BASE == mod.DllBase: 
                         return os.path.splitext(str(mod.BaseDllName))[0]
                 break     
     return "unknown"
Beispiel #34
0
 def get_target_mod_name(self):
     addr_space = utils.load_as(self._config)
     # kernel mod
     if self._config.PID == None:
         all_mods = list(modules.lsmod(addr_space))
         for mod in all_mods:
             if self._config.BASE == mod.DllBase:
                 return os.path.splitext(str(mod.BaseDllName))[0]
     # user mod
     else:
         for prc in tasks.pslist(addr_space):
             if prc.UniqueProcessId == self._config.PID:
                 print "pid: %d" % prc.UniqueProcessId
                 for mod in prc.get_load_modules():
                     print "mod: %x" % mod.DllBase
                     if self._config.BASE == mod.DllBase:
                         return os.path.splitext(str(mod.BaseDllName))[0]
                 break
     return "unknown"
Beispiel #35
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        modlist = list(modules.lsmod(addr_space))
        mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in modlist)
        mod_addrs = sorted(mods.keys())
            
        drivers = dtree.DriverIrp(self._config).calculate()    
        driver_name = "UNKNOWN"
        service_key = "UNKNOWN"
        driver_name3 = "UNKNOWN"
        module_name = "UNKNOWN"

        if self._config.ADDR:
            find_address = self._config.ADDR
            
            module_name = tasks.find_module(mods, mod_addrs, mods.values()[0].obj_vm.address_mask(find_address))
            if module_name:
                module_name = module_name.BaseDllName or module_name.FullDllName

            for driver in drivers:
                if driver.DriverStart <= find_address < driver.DriverStart + driver.DriverSize:
                    header = driver.get_object_header()
                    driver_name = header.NameInfo.Name
                    driver_name  = str(driver.get_object_header().NameInfo.Name or '') 
                    service_key = str(driver.DriverExtension.ServiceKeyName or '') 
                    driver_name3 = str(driver.DriverName or '') 
                    break
            
            yield (module_name, driver_name, service_key, driver_name3)

        else:                
            for driver in drivers:
                driver_name  = str(driver.get_object_header().NameInfo.Name or '')
                service_key = str(driver.DriverExtension.ServiceKeyName or '')
                driver_name3 = str(driver.DriverName or '')
                
                owning_module = tasks.find_module(mods, mod_addrs, mods.values()[0].obj_vm.address_mask(driver.DriverStart))
                module_name = "UNKNOWN"
                if owning_module:
                    module_name = owning_module.BaseDllName or owning_module.FullDllName

                yield (module_name, driver_name, service_key, driver_name3)
Beispiel #36
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

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

        drivers = dtree.DriverIrp(self._config).calculate()
        found_driver = "UNKNOWN"

        if self._config.ADDR:
            find_address = self._config.ADDR

            found_module = tasks.find_module(
                mods, mod_addrs,
                mods.values()[0].obj_vm.address_mask(find_address))
            if found_module:
                found_module = found_module.BaseDllName or found_module.FullDllName
            else:
                found_module = "UNKNOWN"

            for driver in drivers:
                if driver.DriverStart <= find_address < driver.DriverStart + driver.DriverSize:
                    header = driver.get_object_header()
                    found_driver = header.NameInfo.Name
                    break

            yield (found_module, found_driver)

        else:
            for driver in drivers:
                driver_name = driver.get_object_header().NameInfo.Name
                owning_module = tasks.find_module(
                    mods, mod_addrs,
                    mods.values()[0].obj_vm.address_mask(driver.DriverStart))

                if owning_module:
                    module_name = owning_module.BaseDllName or owning_module.FullDllName
                else:
                    module_name = "UNKNOWN"

                yield (module_name, driver_name)
Beispiel #37
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        for mod in modules.lsmod(addr_space):

            # Finding the TC kernel module
            if str(mod.BaseDllName).lower() != "truecrypt.sys":
                continue

            dos_header = obj.Object("_IMAGE_DOS_HEADER", offset=mod.DllBase, vm=addr_space)
            nt_header = dos_header.get_nt_header()

            # Finding the PE data section
            data_section = None
            for sec in nt_header.get_sections():
                if str(sec.Name) == ".data":
                    data_section = sec
                    break

            if not data_section:
                break

            base = sec.VirtualAddress + mod.DllBase
            size = sec.Misc.VirtualSize

            # Looking for the Length member, DWORD-aligned
            ints = obj.Object("Array", targetType="int", offset=base, count=size / 4, vm=addr_space)

            for length in ints:
                # Min and max passphrase lengths
                if length >= self._config.MIN_LENGTH and length <= 64:
                    offset = length.obj_offset + 4
                    passphrase = addr_space.read(offset, length)
                    if not passphrase:
                        continue
                    # All characters in the range must be ASCII
                    chars = [c for c in passphrase if ord(c) >= 0x20 and ord(c) <= 0x7F]
                    if len(chars) != length:
                        continue
                    # At least three zero-bad bytes must follow
                    if addr_space.read(offset + length, 3) != "\x00" * 3:
                        continue
                    yield offset, passphrase
Beispiel #38
0
 def __init__(self,
              start,
              stack_base,
              stack_limit,
              eproc,
              modules=None,
              module_addrs=None,
              *args,
              **kwargs):
     EBP.__init__(self, start, stack_base, stack_limit, eproc, *args,
                  **kwargs)
     if modules == None:
         self.modules = dict(
             (m.DllBase, m) for m in
             list(sysmods.lsmod(eproc.get_process_address_space())) +
             list(eproc.get_load_modules()))
         self.module_addrs = sorted(self.modules.keys())
     else:
         self.modules = modules
         self.module_addrs = module_addrs
     mod = tasks.find_module(self.modules, self.module_addrs, self.eip)
     self.security_cookie = None
     self.cookie = None
     security_cookie_addr = None
     if mod != None:
         load_config = mod.get_load_config_directory()
         if load_config == None:
             # Attempt to use PDB symbols to locate this module's ___security_cookie
             addrs = eproc.lookup("{0}/.data!___security_cookie".format(
                 str(mod.BaseDllName)))
             if len(addrs) > 0:
                 security_cookie_addr = addrs[0]
         else:
             # Use _IMAGE_LOAD_CONFIG_DIRECTORY to locate this module's ___security_cookie
             security_cookie_addr = load_config.SecurityCookie
         if security_cookie_addr != None and self.addrspace.is_valid_address(
                 security_cookie_addr):
             self.security_cookie = self.addrspace.read_long_phys(
                 self.addrspace.vtop(security_cookie_addr))
         if self.addrspace.is_valid_address(self.ebp - self.alignment):
             self.cookie = self.addrspace.read_long_phys(
                 self.addrspace.vtop(self.ebp - self.alignment))
Beispiel #39
0
    def gather_exports_symbols_values(self):

        symbols_values = []
        addr_space = utils.load_as(self._config)
        
        #############################
        # collect kernel mode exports
        if self._config.PID == None:         
            all_mods = list(modules.lsmod(addr_space))            
            for mod in all_mods:
                if mod.DllBase != self._config.BASE:
                    dllBaseAppended = False
                    for ordinal, func_addr, func_name in mod.exports():
                        if func_addr != None:
                            name = func_name or ordinal or ''
                            if self._config.AGGRESIVE or ("%s" % mod.BaseDllName).lower() in self.kernel_common_mods:
                                if self._config.DLLBASES and not dllBaseAppended: 
                                    symbols_values.append((mod.DllBase, ("dllbase_%s" % mod.BaseDllName).replace(".","_").lower()))
                                    dllBaseAppended = True
                                symbols_values.append((mod.DllBase + func_addr, str(name))) #"%s_%s" % (mod.BaseDllName, name))
        
        ###########################
        # collect user mode exports 
        # for specified process        
        else:
            for prc in tasks.pslist(addr_space):
                if prc.UniqueProcessId == self._config.PID:
                    #addr_space = prc.get_process_address_space()
                    for mod in prc.get_load_modules():
                        if mod.DllBase != self._config.BASE:
                            dllBaseAppended = False
                            for ordinal, func_addr, func_name in mod.exports():                                
                                if func_addr != None:
                                    name = func_name or ordinal or ''
                                    if self._config.AGGRESIVE or ("%s" % mod.BaseDllName).lower() in self.user_common_mods:
                                        if self._config.DLLBASES and not dllBaseAppended: 
                                            symbols_values.append((mod.DllBase, ("dllbase_%s" % mod.BaseDllName).replace(".","_").lower()))
                                            dllBaseAppended = True
                                        symbols_values.append((mod.DllBase + func_addr, str(name))) #"%s_%s" % (mod.BaseDllName, name)))
                    break
        
        return symbols_values
Beispiel #40
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)
Beispiel #41
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        modlist = list(modules.lsmod(addr_space))
        mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in modlist)
        mod_addrs = sorted(mods.keys())
            
        drivers = dtree.DriverIrp(self._config).calculate()    
        found_driver = "UNKNOWN"

        if self._config.ADDR:
            find_address = self._config.ADDR
            
            found_module = tasks.find_module(mods, mod_addrs, mods.values()[0].obj_vm.address_mask(find_address))
            if found_module:
                found_module = found_module.BaseDllName or found_module.FullDllName
            else:
                found_module = "UNKNOWN"

            for driver in drivers:
                if driver.DriverStart <= find_address < driver.DriverStart + driver.DriverSize:
                    header = driver.get_object_header()
                    found_driver = header.NameInfo.Name
                    break
            
            yield (found_module, found_driver)

        else:                
            for driver in drivers:
                driver_name = driver.get_object_header().NameInfo.Name
                owning_module = tasks.find_module(mods, mod_addrs, mods.values()[0].obj_vm.address_mask(driver.DriverStart))

                if owning_module:
                    module_name = owning_module.BaseDllName or owning_module.FullDllName
                else:
                    module_name = "UNKNOWN"

                yield (module_name, driver_name)
    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))
Beispiel #43
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        bits32 = addr_space.profile.metadata.get("memory_model", "32bit") == "32bit"

        # 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())

        # Valid for Vista and later
        if version >= (6, 0):
            self.scanners.append(PoolScanDbgPrintCallback)
            self.scanners.append(PoolScanRegistryCallback)
            self.scanners.append(PoolScanPnp9)
            self.scanners.append(PoolScanPnpD)
            self.scanners.append(PoolScanPnpC)
        
        for objct in self.scan_results(addr_space):
            name = objct.obj_name
            if name == "_REGISTRY_CALLBACK":
                info = "CmRegisterCallback", objct.Function, None
                yield info, mods, mod_addrs
            elif name == "_DBGPRINT_CALLBACK":
                info = "DbgSetDebugPrintCallback", objct.Function, None
                yield info, mods, mod_addrs
            elif name == "_SHUTDOWN_PACKET":
                driver = objct.DeviceObject.dereference().DriverObject
                index = devicetree.MAJOR_FUNCTIONS.index('IRP_MJ_SHUTDOWN')
                address = driver.MajorFunction[index]
                details = str(driver.DriverName or "-")
                info = "IoRegisterShutdownNotification", address, details
                yield info, mods, mod_addrs
            elif name == "_GENERIC_CALLBACK":
                info = "GenericKernelCallback", objct.Callback, None
                yield info, mods, mod_addrs
            elif name == "_NOTIFY_ENTRY_HEADER":
                # Dereference the driver object pointer
                driver = objct.DriverObject.dereference()
                # Instantiate an object header for the driver name 
                header = driver.get_object_header()
                # Grab the object name 
                driver_name = header.NameInfo.Name.v()
                info = objct.EventCategory, objct.CallbackRoutine, driver_name
                yield info, mods, mod_addrs
            elif name == "_NOTIFICATION_PACKET":
                info = "IoRegisterFsRegistrationChange", objct.NotificationRoutine, None
                yield info, mods, mod_addrs
            
        for info in self.get_kernel_callbacks(modlist[0]):
            yield info, mods, mod_addrs

        for info in self.get_bugcheck_callbacks(addr_space):
            yield info, mods, mod_addrs

        for info in self.get_bugcheck_reason_callbacks(modlist[0]):
            yield info, mods, mod_addrs

        # Valid for XP 
        if bits32 and version == (5, 1):
            for info in self.get_registry_callbacks_legacy(modlist[0]):
                yield info, mods, mod_addrs
Beispiel #44
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
Beispiel #45
0
    def calculate(self):

        if not has_distorm:
            debug.error("You must install distorm3")

        addr_space = utils.load_as(self._config)

        all_tasks = list(tasks.pslist(addr_space))
        all_mods = list(modules.lsmod(addr_space))

        # Operate in kernel mode if pid is not supplied
        if not self._config.PID:
            if not self._config.BASE:
                debug.error("You must specify --BASE")

            base_address = self._config.BASE
            size_to_read = self._config.SIZE

            # Get the size from the module list if its not supplied
            if not size_to_read:
                for module in all_mods:
                    if module.DllBase == base_address:
                        size_to_read = module.SizeOfImage
                        break
                # Alternately, try the size from the PE header 
                if not size_to_read:
                    pefile = obj.Object("_IMAGE_DOS_HEADER", 
                                        offset = base_address, 
                                        vm = addr_space)
                    try:
                        nt_header = pefile.get_nt_header()
                        size_to_read = nt_header.OptionalHeader.SizeOfImage
                    except ValueError:
                        pass

                    if not size_to_read:
                        debug.error("You must specify --SIZE")

            kernel_space = tasks.find_space(addr_space,
                                    all_tasks, base_address)

            if not kernel_space:
                debug.error("Cannot read supplied address")

            data = kernel_space.zread(base_address, size_to_read)
            apis = self.enum_apis(all_mods)
            addr_space = kernel_space
        else:
            # In process mode, we find the process by PID
            task = None

            for atask in all_tasks:
                if atask.UniqueProcessId == self._config.PID:
                    task = atask
                    break

            if not task:
                debug.error("You must supply an active PID")

            task_space = task.get_process_address_space()

            if not task_space:
                debug.error("Cannot acquire process AS")

            all_mods = list(task.get_load_modules())

            # PEB is paged or no DLLs loaded 
            if not all_mods:
                debug.error("Cannot load DLLs in process AS")

            # If an address is supplied with a size, try to get
            # the size from the vad node. If neither are supplied, 
            # assume we should carve the main process executable. 
            if self._config.BASE:
                base_address = self._config.BASE
                size_to_read = self._config.SIZE

                if not size_to_read:
                    for vad in task.VadRoot.traverse():
                        if base_address >= vad.Start and base_address <= vad.End:
                            size_to_read = vad.Length
                    if not size_to_read:
                        debug.error("You must specify --SIZE")
            else:
                # Its OK to blindly take the 0th element because the 
                # executable is always the first module to load. 
                base_address = all_mods[0].DllBase
                size_to_read = all_mods[0].SizeOfImage

            if not task_space.is_valid_address(base_address):
                debug.error("Address is not valid in process AS")

            data = task_space.zread(base_address, size_to_read)
            apis = self.enum_apis(all_mods)
            addr_space = task_space

        # This is a dictionary of confirmed API calls.
        calls_imported = dict(
                (iat, call)
                for (_, iat, call) in self.call_scan(addr_space, base_address, data)
                if call in apis
                )

        # Scan forward 
        self._vicinity_scan(addr_space,
                calls_imported, apis, base_address, len(data),
                forward = True)

        # Scan reverse 
        self._vicinity_scan(addr_space,
                calls_imported, apis, base_address, len(data),
                forward = False)

        for iat, call in sorted(calls_imported.items()):
            yield iat, call, apis[call][0], apis[call][1]
Beispiel #46
0
    def get_json(self, data):
        results = {}

        addr_space = utils.load_as(self._config)

        # Compile the regular expression for filtering by driver name
        if self._config.regex != None:
            mod_re = re.compile(self._config.regex, re.I)
        else:
            mod_re = None

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

        bits = addr_space.profile.metadata.get('memory_model', '32bit')

        for driver in data:
            header = driver.get_object_header()

            driver_name = str(header.NameInfo.Name or '')

            # Continue if a regex was supplied and it doesn't match
            if mod_re != None:
                if not (mod_re.search(driver_name) or
                        mod_re.search(driver_name)): continue

            row = {'DriverName':driver_name,
                   'DriverStart':int(driver.DriverStart),
                   'DriverSize':int(driver.DriverSize),
                   'DriverStartIo':int(driver.DriverStartIo),
                   'IrpFunctions':[],
                   'Devices':[],
                   }

            # Write the address and owner of each IRP function
            for i, function in enumerate(driver.MajorFunction):
                function = driver.MajorFunction[i]
                module = tasks.find_module(mods, mod_addrs, function)
                irp = {'index':int(i),
                        'FunctionName':str(MAJOR_FUNCTIONS[i]),
                        'FunctionAddress':int(function),
                        'Disassembly':[]
                        }
                if module:
                    irp['BaseDllName'] = str(module.BaseDllName or '')
                else:
                    irp['BaseDllName'] = ''


                if self._config.verbose:
                    data = addr_space.zread(function, 64)
                    irp["Disassembly"] = [{'Address':int(o), "Bytes":str(h), "Instruction":str(i)}
                        for o, i, h in malfind.Disassemble(data = data,
                            start = function, bits = bits, stoponret = True)
                    ]
                row['IrpFunctions'].append(irp)

            for device in driver.devices():

                device_header = obj.Object("_OBJECT_HEADER", offset = device.obj_offset -
                        device.obj_vm.profile.get_obj_offset("_OBJECT_HEADER", "Body"),
                        vm = device.obj_vm,
                        native_vm = device.obj_native_vm
                        )

                device_name = str(device_header.NameInfo.Name or '')

                dev = {'Offset': int(device.obj_offset),
                          'DeviceName': device_name,
                          'DeviceCodes': DEVICE_CODES.get(device.DeviceType.v(), "UNKNOWN"),
                          'AttachedDevices': []}

                level = 0

                for att_device in device.attached_devices():

                    device_header = obj.Object("_OBJECT_HEADER", offset = att_device.obj_offset -
                        att_device.obj_vm.profile.get_obj_offset("_OBJECT_HEADER", "Body"),
                        vm = att_device.obj_vm,
                        native_vm = att_device.obj_native_vm
                        )

                    device_name = str(device_header.NameInfo.Name or '')
                    name = (device_name + " - " +
                           str(att_device.DriverObject.DriverName or ''))

                    attached_device = {'Offset': att_device.obj_offset,
                                       'DeviceName': name,
                                       'DeviceCodes': DEVICE_CODES.get(att_device.DeviceType.v(), "UNKNOWN"),
                                       'Level': level}

                    level += 1
                    dev['AttachedDevices'].append(attached_device)
                row['Devices'].append(dev)

            _addr = str(row['DriverStart'])
            results [_addr ] = row

        return results
    def calculate(self):
        if self._config.BASELINEIMG == None:
            print "Baseline image required!"
            sys.exit()
        
        if self._config.ONLYKNOWN and self._config.ONLYUNKNOWN:
            print "Select only one of the options (-K, -U)!"
            sys.exit(-1)
        
        #######################################
        #Searching for drivers in baseline image
        ######################################
        # Saving original image
        orig_img = self._config.LOCATION
        # Setting up baseline image
        self._config.LOCATION = "file://" + self._config.BASELINEIMG

        # Instantiating DriverScan plugin
        addr_space = utils.load_as(self._config)
        drv_scan = DriverScan(self._config)
        
        if volatility.constants.VERSION != "2.4":
            for obj, drv, ext  in drv_scan.calculate():
                if ext.ServiceKeyName != None:
                    service_key_name = str(ext.ServiceKeyName).lower()
                else:
                    service_key_name = None
                
                if obj.NameInfo.Name != None:
                    name = str(obj.NameInfo.Name).lower()
                else:
                    name = None
                
                if drv.DriverName != None:
                    driver_name = str(drv.DriverName).lower()
                else:
                    driver_name = None
                
                if drv.DriverSize != None:
                    driver_size = drv.DriverSize
                else:
                    driver_size = None
                
                if drv.DriverStart != None:
                    driver_start = drv.DriverStart
                else:
                    driver_start = None
                
                mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in lsmod(addr_space))
                mod_addrs = sorted(mods.keys())
                
                IRPs = {}
                for i, function in enumerate(drv.MajorFunction):
                    function = drv.MajorFunction[i]
                    module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(function))
                    if module:
                        module_name = str(module.BaseDllName or '').lower()
                    else:
                        module_name = "unknown"
                    IRPs[MAJOR_FUNCTIONS[i]] = module_name               
                
                self.baseline_drv_list.append({
                                                'service_key_name': service_key_name,
                                                'name': name,
                                                'driver_name': driver_name,
                                                'driver_size': driver_size,
                                                'driver_start': driver_start,
                                                'irps': IRPs
                                            })
        else:
            for driver in drv_scan.calculate():
                header = driver.get_object_header()
                if driver.DriverExtension.ServiceKeyName != None:
                    service_key_name = str(driver.DriverExtension.ServiceKeyName).lower()
                else:
                    service_key_name = None
                
                if header.NameInfo.Name != None:
                    name = str(header.NameInfo.Name).lower()
                else:
                    name = None
                
                if driver.DriverName != None:
                    driver_name = str(driver.DriverName).lower()
                else:
                    driver_name = None
                
                if driver.DriverSize != None:
                    driver_size = driver.DriverSize
                else:
                    driver_size = None
                
                if driver.DriverStart != None:
                    driver_start = driver.DriverStart
                else:
                    driver_start = None
                
                mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in lsmod(addr_space))
                mod_addrs = sorted(mods.keys())
                
                IRPs = {}
                for i, function in enumerate(driver.MajorFunction):
                    function = driver.MajorFunction[i]
                    module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(function))
                    if module:
                        module_name = str(module.BaseDllName or '').lower()
                    else:
                        module_name = "unknown"
                    IRPs[MAJOR_FUNCTIONS[i]] = module_name               
                
                self.baseline_drv_list.append({
                                                'service_key_name': service_key_name,
                                                'name': name,
                                                'driver_name': driver_name,
                                                'driver_size': driver_size,
                                                'driver_start': driver_start,
                                                'irps': IRPs
                                            })
        
        # Instantiating Modules plugin
        for m in lsmod(addr_space):
            self.baseline_mod_list.append({
                                            'full_dll_name': str(m.FullDllName).lower(),
                                            'base_dll_name': str(m.BaseDllName).lower(),
                                            'dll_base': m.DllBase
                                        })
            
            for drv in self.baseline_drv_list:
                if drv['driver_start'] == m.DllBase:
                    if m.FullDllName != None:
                        drv['full_dll_name'] = str(m.FullDllName).lower()
                    else:
                        drv['full_dll_name'] = None
                    if m.BaseDllName != None:
                        drv['base_dll_name'] = str(m.BaseDllName).lower()
                    else:
                        drv['base_dll_name'] = None
        
        # Fixing entries that are not in the list of loaded modules list
        for drv in self.baseline_drv_list:
            f = False
            for m in self.baseline_mod_list:
                if m['dll_base'] == drv['driver_start']:
                    f = True
            if not f:
                drv['full_dll_name'] = None
                drv['base_dll_name'] = None
        
        ####################################
        #Searching for drivers in the image to be analyzed
        ##################################
        # Restoring original image
        self._config.LOCATION = orig_img
        
        # Instantiating DriverScan plugin
        addr_space = utils.load_as(self._config)
        drv_scan = DriverScan(self._config)
        if volatility.constants.VERSION != "2.4":
            for obj, drv, ext  in drv_scan.calculate():
                if ext.ServiceKeyName != None:
                    service_key_name = str(ext.ServiceKeyName).lower()
                else:
                    service_key_name = None
                
                if obj.NameInfo.Name != None:
                    name = str(obj.NameInfo.Name).lower()
                else:
                    name = None
                
                if drv.DriverName != None:
                    driver_name = str(drv.DriverName).lower()
                else:
                    driver_name = None
                
                if drv.DriverSize != None:
                    driver_size = drv.DriverSize
                else:
                    driver_size = None
                
                if drv.DriverStart != None:
                    driver_start = drv.DriverStart
                else:
                    driver_start = None
                
                mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in lsmod(addr_space))
                mod_addrs = sorted(mods.keys())
                
                IRPs = {}
                for i, function in enumerate(drv.MajorFunction):
                    function = drv.MajorFunction[i]
                    module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(function))
                    if module:
                        module_name = str(module.BaseDllName or '').lower()
                    else:
                        module_name = "unknown"
                    IRPs[MAJOR_FUNCTIONS[i]] = module_name
                
                self.image_drv_list.append({
                                                'service_key_name': service_key_name,
                                                'name': name,
                                                'driver_name': driver_name,
                                                'driver_size': driver_size,
                                                'driver_start': driver_start,
                                                'irps': IRPs,
                                                'obj': obj,
                                                'drv': drv,
                                                'ext': ext
                                            })
        else:
            for driver in drv_scan.calculate():
                header = driver.get_object_header()
                if driver.DriverExtension.ServiceKeyName != None:
                    service_key_name = str(driver.DriverExtension.ServiceKeyName).lower()
                else:
                    service_key_name = None
                
                if header.NameInfo.Name != None:
                    name = str(header.NameInfo.Name).lower()
                else:
                    name = None
                
                if driver.DriverName != None:
                    driver_name = str(driver.DriverName).lower()
                else:
                    driver_name = None
                
                if driver.DriverSize != None:
                    driver_size = driver.DriverSize
                else:
                    driver_size = None
                
                if driver.DriverStart != None:
                    driver_start = driver.DriverStart
                else:
                    driver_start = None
                
                mods = dict((addr_space.address_mask(mod.DllBase), mod) for mod in lsmod(addr_space))
                mod_addrs = sorted(mods.keys())
                
                IRPs = {}
                for i, function in enumerate(driver.MajorFunction):
                    function = driver.MajorFunction[i]
                    module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(function))
                    if module:
                        module_name = str(module.BaseDllName or '').lower()
                    else:
                        module_name = "unknown"
                    IRPs[MAJOR_FUNCTIONS[i]] = module_name
                
                self.image_drv_list.append({
                                                'service_key_name': service_key_name,
                                                'name': name,
                                                'driver_name': driver_name,
                                                'driver_size': driver_size,
                                                'driver_start': driver_start,
                                                'irps': IRPs,
                                                'obj': header,
                                                'drv': driver,
                                                'ext': driver.DriverExtension
                                            })
        
        for m in lsmod(addr_space):
            self.image_mod_list.append({
                                            'full_dll_name': str(m.FullDllName).lower(),
                                            'base_dll_name': str(m.BaseDllName).lower(),
                                            'dll_base': m.DllBase
                                        })
            for drv in self.image_drv_list:
                if drv['driver_start'] == m.DllBase:
                    if m.FullDllName != None:
                        drv['full_dll_name'] = str(m.FullDllName).lower()
                    else:
                        drv['full_dll_name'] = None
                    if m.BaseDllName != None:
                        drv['base_dll_name'] = str(m.BaseDllName).lower()
                    else:
                        drv['base_dll_name'] = None
        
        # Fixing up entries that are not in the list of loaded modules list
        for drv in self.image_drv_list:
            f = False
            for m in self.image_mod_list:
                if m['dll_base'] == drv['driver_start']:
                    f = True
            if not f:
                drv['full_dll_name'] = None
                drv['base_dll_name'] = None
        
        # Compare the lists
        for drv in self.image_drv_list:
            known = False
            d_name = False
            drv_name = False
            drv_size = False
            drv_mod = False
            drv_irp = False
            drv_bl = None
            for bl_drv in self.baseline_drv_list:
                
                if drv['service_key_name'] == bl_drv['service_key_name']:
                    known = True
                    
                    if drv['name'] == bl_drv['name']:
                        d_name = True
                    elif self._config.VERBOSE:
                        print "Name:"
                        print "Baseline: " + bl_drv['name']
                        print "Image:    " + drv['name']
                    
                    if drv['driver_name'] == bl_drv['driver_name']:
                        drv_name = True
                    elif self._config.VERBOSE:
                        print "Driver Name:"
                        print "Baseline: " + str(bl_drv['driver_name'])
                        print "Image:    " + str(drv['driver_name'])
                    
                    if drv['driver_size'] == bl_drv['driver_size']:
                        drv_size = True
                    elif self._config.VERBOSE:
                        print "Driver Size:"
                        print "Baseline: " + str(bl_drv['driver_size'])
                        print "Image:    " + str(drv['driver_size'])
                    
                    if drv['full_dll_name'] == bl_drv['full_dll_name']:
                        drv_mod = True
                    elif self._config.VERBOSE:
                        print "Module:"
                        print "Baseline: " + str(bl_drv['full_dll_name'])
                        print "Image:    " + str(drv['full_dll_name'])
                        
                    drv_irp = True
                    for m in drv['irps']:
                        if drv['irps'][m] != bl_drv['irps'][m]:
                            drv_irp = False
                    
                if known:
                    drv_bl = bl_drv
                    break
            
            if self._config.ONLYKNOWN:
                if known:
                    yield (drv['obj'], drv['drv'], drv['ext'], known, d_name, drv_name, drv_mod, drv_size, drv['full_dll_name'], drv_irp, drv['irps'], drv_bl['irps'])
            if self._config.ONLYUNKNOWN:
                if not known:
                    yield (drv['obj'], drv['drv'], drv['ext'], known, d_name, drv_name, drv_mod, drv_size, drv['full_dll_name'], drv_irp, drv['irps'], None)
            if not self._config.ONLYKNOWN and not self._config.ONLYUNKNOWN:
                if drv_bl:
                    yield (drv['obj'], drv['drv'], drv['ext'], known, d_name, drv_name, drv_mod, drv_size, drv['full_dll_name'], drv_irp, drv['irps'], drv_bl['irps'])
                else:
                    yield (drv['obj'], drv['drv'], drv['ext'], known, d_name, drv_name, drv_mod, drv_size, drv['full_dll_name'], drv_irp, drv['irps'], None)
Beispiel #48
0
    def get_json(self, data):
        results = {}

        addr_space = utils.load_as(self._config)

        # Compile the regular expression for filtering by driver name
        if self._config.regex != None:
            mod_re = re.compile(self._config.regex, re.I)
        else:
            mod_re = None

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

        bits = addr_space.profile.metadata.get('memory_model', '32bit')

        for driver in data:
            header = driver.get_object_header()

            driver_name = str(header.NameInfo.Name or '')

            # Continue if a regex was supplied and it doesn't match
            if mod_re != None:
                if not (mod_re.search(driver_name)
                        or mod_re.search(driver_name)):
                    continue

            row = {
                'DriverName': driver_name,
                'DriverStart': int(driver.DriverStart),
                'DriverSize': int(driver.DriverSize),
                'DriverStartIo': int(driver.DriverStartIo),
                'IrpFunctions': [],
                'Devices': [],
            }

            # Write the address and owner of each IRP function
            for i, function in enumerate(driver.MajorFunction):
                function = driver.MajorFunction[i]
                module = tasks.find_module(mods, mod_addrs, function)
                irp = {
                    'index': int(i),
                    'FunctionName': str(MAJOR_FUNCTIONS[i]),
                    'FunctionAddress': int(function),
                    'Disassembly': []
                }
                if module:
                    irp['BaseDllName'] = str(module.BaseDllName or '')
                else:
                    irp['BaseDllName'] = ''

                if self._config.verbose:
                    data = addr_space.zread(function, 64)
                    irp["Disassembly"] = [{
                        'Address': int(o),
                        "Bytes": str(h),
                        "Instruction": str(i)
                    } for o, i, h in malfind.Disassemble(
                        data=data, start=function, bits=bits, stoponret=True)]
                row['IrpFunctions'].append(irp)

            for device in driver.devices():

                device_header = obj.Object(
                    "_OBJECT_HEADER",
                    offset=device.obj_offset -
                    device.obj_vm.profile.get_obj_offset(
                        "_OBJECT_HEADER", "Body"),
                    vm=device.obj_vm,
                    native_vm=device.obj_native_vm)

                device_name = str(device_header.NameInfo.Name or '')

                dev = {
                    'Offset':
                    int(device.obj_offset),
                    'DeviceName':
                    device_name,
                    'DeviceCodes':
                    DEVICE_CODES.get(device.DeviceType.v(), "UNKNOWN"),
                    'AttachedDevices': []
                }

                level = 0

                for att_device in device.attached_devices():

                    device_header = obj.Object(
                        "_OBJECT_HEADER",
                        offset=att_device.obj_offset -
                        att_device.obj_vm.profile.get_obj_offset(
                            "_OBJECT_HEADER", "Body"),
                        vm=att_device.obj_vm,
                        native_vm=att_device.obj_native_vm)

                    device_name = str(device_header.NameInfo.Name or '')
                    name = (device_name + " - " +
                            str(att_device.DriverObject.DriverName or ''))

                    attached_device = {
                        'Offset':
                        att_device.obj_offset,
                        'DeviceName':
                        name,
                        'DeviceCodes':
                        DEVICE_CODES.get(att_device.DeviceType.v(), "UNKNOWN"),
                        'Level':
                        level
                    }

                    level += 1
                    dev['AttachedDevices'].append(attached_device)
                row['Devices'].append(dev)

            _addr = str(row['DriverStart'])
            results[_addr] = row

        return results
    def calculate(self):

        # 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 list(checks.items()):
                sys.stdout.write("{0:<20} {1}\n".format(
                    cls_name, pydoc.getdoc(cls)))
            return

        addr_space = utils.load_as(self._config)

        # Only show threads owned by particular processes
        if self._config.PID:
            pidlist = [int(p) for p in self._config.PID.split(',')]
        else:
            pidlist = []

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

        # Gather processes
        all_tasks = list(tasks.pslist(addr_space))

        # 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 self.filter_tasks(all_tasks):
            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 thread.obj_offset not in seen_threads:
                seen_threads[thread.obj_offset] = (True, thread)

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

            # Skip processes the user doesn't want to see
            if pidlist and thread.Cid.UniqueProcess not in pidlist:
                continue

            # Replace the dummy class with an instance
            for cls_name, cls in list(checks.items()):

                instances = dict((cls_name,
                                  cls(thread, mods, mod_addrs, hooked_tables,
                                      found_by_scanner))
                                 for cls_name, cls in list(checks.items()))

            yield thread, addr_space, mods, mod_addrs, instances, hooked_tables
Beispiel #50
0
    def render_text(self, outfd, data):
        
        
        outfd.write("\n")
        outfd.write("------- driver IRP check -------- \n\n")
        

        addr_space = utils.load_as(self._config)

        # Compile the regular expression for filtering by driver name 
        if self._config.regex != None:
            mod_re = re.compile(self._config.regex, re.I)
        else:
            mod_re = None

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

        bits = addr_space.profile.metadata.get('memory_model', '32bit')

        self.table_header(None, [('i', ">4"),
                                 ('Funcs', "36"),
                                 ('addr', '[addrpad]'),
                                 ('name', '')
                                 ])
       
       
        drivers = dict()
        numberOfDrivers = 0
        for driver in data:
            
            header = driver.get_object_header()

            driver_name = str(header.NameInfo.Name or '')
            # Continue if a regex was supplied and it doesn't match 
            if mod_re != None:
                if not (mod_re.search(driver_name) or
                        mod_re.search(driver_name)): continue

            # Write the standard header for each driver object 
            #outfd.write("{0}\n".format("-" * 50))
            #outfd.write("DriverName: {0}\n".format(driver_name))
            #outfd.write("DriverStart: {0:#x}\n".format(driver.DriverStart))
            #outfd.write("DriverSize: {0:#x}\n".format(driver.DriverSize))
            #outfd.write("DriverStartIo: {0:#x}\n".format(driver.DriverStartIo))

            #print driver_name
            numberOfDrivers += 1
            drivers[driver_name] = {}
        
            #functions = []

            # Write the address and owner of each IRP function 
            for ii, function in enumerate(driver.MajorFunction):
                functions = []
                function = driver.MajorFunction[ii]
                module = tasks.find_module(mods, mod_addrs, addr_space.address_mask(function))
                if module:
                    module_name = str(module.BaseDllName or '')
                else:
                    module_name = "Unknown"
                
                # This is where we check for inline hooks once the 
                # ApiHooks plugin is ported to 2.1. 
                #self.table_row(outfd, i, MAJOR_FUNCTIONS[i], fnction, module_name)
                
                currentFunction = MAJOR_FUNCTIONS[ii]
                currentFunctionNr = ii
                #print "1337 - " + str(ii) + " - " + str(currentFunction)
                data = addr_space.zread(function, 64)
                #outfd.write("\n".join(
                #    ["{0:#x} {1:<16} {2}".format(o, h, i)
                #    for o, i, h in malfind.Disassemble(data = data, 
                #        start = function, bits = bits, stoponret = True)
                #]))
                nameFunction = currentFunction
                
                #outfd.write("instruksjon \n")
                #for o, i, h in malfind.Disassemble(data = data, start = function, bits = bits, stoponret = True):
                    
                    #outfd.write(i + "\n")
                    #if "0x" in str(i):
                    #    i = "--"
                    #i = re.sub('([0x])\w+', '0x000', i)    
                    #instructions.append(i)
                functions.append(module_name)
                    
                drivers[driver_name][str(currentFunctionNr) + " - " + str(nameFunction)] = functions
                #outfd.write("instruksjon slutt \n")
                #functions[str(str(currentFunctionNr) + " - "+ currentFunction)].append(instructions)
                #print functions.keys()
            #drivers[driver_name].append(functions)
            
        outfd.write("# of drivers collected: " + str(numberOfDrivers) +"\n\n" )
        
        locationString = str(conf.ConfObject.opts["location"]).rsplit('/',1)[1] + "_DriverList"
        outfd.write("Storing DriverList as \"" + locationString + "\"\n")
        #print drivers
        with open(locationString + '.p', 'wb') as fp:
            pickle.dump(drivers, fp)
                
                
            
Beispiel #51
0
    def calculate(self):

        addr_space = utils.load_as(self._config)

        if not has_distorm3:
            debug.error("Install distorm3 code.google.com/p/distorm/")

        if not self._config.SKIP_PROCESS:
            for proc in self.filter_tasks(tasks.pslist(addr_space)):
                process_name = str(proc.ImageFileName).lower()

                if (self._config.QUICK and
                        process_name not in self.critical_process):
                    #debug.debug("Skipping non-critical process {0} ({1})".format(
                    #    process_name, proc.UniqueProcessId))
                    continue

                process_space = proc.get_process_address_space()
                if not process_space:
                    #debug.debug("Cannot acquire process AS for {0} ({1})".format(
                    #    process_name, proc.UniqueProcessId))
                    continue

                module_group = ModuleGroup(proc.get_load_modules())

                for dll in module_group.mods:

                    if not process_space.is_valid_address(dll.DllBase):
                        continue

                    dll_name = str(dll.BaseDllName or '').lower()

                    if (self._config.QUICK and
                            dll_name not in self.critical_dlls and
                            dll.DllBase != proc.Peb.ImageBaseAddress):
                        #debug.debug("Skipping non-critical dll {0} at {1:#x}".format(
                        #    dll_name, dll.DllBase))
                        continue

                    #debug.debug("Analyzing {0}!{1}".format(process_name, dll_name))

                    for hook in self.get_hooks(HOOK_MODE_USER, process_space, dll, module_group):
                        if not self._config.NO_WHITELIST:
                            if self.whitelist(hook.hook_mode | hook.hook_type, str(proc.ImageFileName), hook.VictimModule, hook.HookModule, hook.Function):
                                continue
                        yield proc, dll, hook

        if not self._config.SKIP_KERNEL:
            process_list = list(tasks.pslist(addr_space))
            module_group = ModuleGroup(modules.lsmod(addr_space))

            for mod in module_group.mods:

                #module_name = str(mod.BaseDllName or '')
                #debug.debug("Analyzing {0}".format(module_name))

                kernel_space = tasks.find_space(addr_space,
                    process_list, mod.DllBase)

                if not kernel_space:
                    #debug.debug("No kernel AS for {0} at {1:#x}".format(
                    #    module_name, mod.DllBase))
                    continue

                for hook in self.get_hooks(HOOK_MODE_KERNEL, kernel_space, mod, module_group):
                    if not self._config.NO_WHITELIST:
                        if self.whitelist(hook.hook_mode | hook.hook_type, "", hook.VictimModule, hook.HookModule, hook.Function):
                            continue
                    yield None, mod, hook
Beispiel #52
0
    def calculate(self):

        # 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)

        # Only show threads owned by particular processes
        if self._config.PID:
            pidlist = [int(p) for p in self._config.PID.split(',')]
        else:
            pidlist = []

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

        # Gather processes 
        all_tasks = list(tasks.pslist(addr_space))

        # 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 self.filter_tasks(all_tasks):
            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)

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

            # Skip processes the user doesn't want to see
            if pidlist and thread.Cid.UniqueProcess not in pidlist:
                continue

            # Replace the dummy class with an instance 
            for cls_name, cls in checks.items():

                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
Beispiel #53
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        # we currently don't use this on x64 because for some reason the 
        # x64 version actually doesn't create a DisplayVersion value 
        memory_model = addr_space.profile.metadata.get('memory_model')
        if memory_model == '32bit':
            regapi = registryapi.RegistryApi(self._config)
            regapi.reset_current()
            regapi.set_current(hive_name = "software")
            x86key = "Microsoft\\Windows\\CurrentVersion\\Uninstall"
            x64key = "Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
            for subkey in regapi.reg_get_all_subkeys(None, key = x86key):
                if str(subkey.Name) == "TrueCrypt":
                    subpath = x86key + "\\" + subkey.Name
                    version = regapi.reg_get_value("software", 
                                            key = subpath, 
                                            value = "DisplayVersion")
                    if version:
                        yield "Registry Version", "{0} Version {1}".format(
                            str(subkey.Name),
                            version)

        scanner = TrueCryptPassphrase(self._config)
        for offset, passphrase in scanner.calculate():
            yield "Password", "{0} at offset {1:#x}".format(
                        passphrase, offset)

        for proc in tasks.pslist(addr_space):
            if str(proc.ImageFileName).lower() == "truecrypt.exe":     
                yield "Process", "{0} at {1:#x} pid {2}".format(
                        proc.ImageFileName,
                        proc.obj_offset, 
                        proc.UniqueProcessId)   

        scanner = svcscan.SvcScan(self._config)
        for service in scanner.calculate():
            name = str(service.ServiceName.dereference())
            if name == "truecrypt":
                yield "Service", "{0} state {1}".format(
                        name, 
                        service.State)

        for mod in modules.lsmod(addr_space):
            basename = str(mod.BaseDllName or '').lower()
            fullname = str(mod.FullDllName or '').lower()
            if (basename.endswith("truecrypt.sys") or 
                        fullname.endswith("truecrypt.sys")):
                yield "Kernel Module",  "{0} at {1:#x} - {2:#x}".format(
                        mod.BaseDllName, 
                        mod.DllBase, 
                        mod.DllBase + mod.SizeOfImage)

        scanner = filescan.SymLinkScan(self._config)
        for symlink in scanner.calculate():
            object_header = symlink.get_object_header()
            if "TrueCryptVolume" in str(symlink.LinkTarget or ''):
                yield "Symbolic Link", "{0} -> {1} mounted {2}".format(
                        str(object_header.NameInfo.Name or ''), 
                        str(symlink.LinkTarget or ''), 
                        str(symlink.CreationTime or ''))

        scanner = filescan.FileScan(self._config)
        for fileobj in scanner.calculate():
            filename = str(fileobj.file_name_with_device() or '')
            if "TrueCryptVolume" in filename:
                yield "File Object", "{0} at {1:#x}".format(
                        filename,
                        fileobj.obj_offset)
        
        scanner = filescan.DriverScan(self._config)
        for driver in scanner.calculate():
            object_header = driver.get_object_header() 
            driverext = driver.DriverExtension
            drivername = str(driver.DriverName or '')
            servicekey = str(driverext.ServiceKeyName or '')
            if (drivername.endswith("truecrypt") or 
                        servicekey.endswith("truecrypt")):
                yield "Driver", "{0} at {1:#x} range {2:#x} - {3:#x}".format(
                        drivername, 
                        driver.obj_offset, 
                        driver.DriverStart, 
                        driver.DriverStart + driver.DriverSize)
                for device in driver.devices():
                    header = device.get_object_header()
                    devname = str(header.NameInfo.Name or '')
                    type = devicetree.DEVICE_CODES.get(device.DeviceType.v())
                    yield "Device", "{0} at {1:#x} type {2}".format(
                        devname or "<HIDDEN>", 
                        device.obj_offset, 
                        type or "UNKNOWN")
                    if type == "FILE_DEVICE_DISK":
                        data = addr_space.read(device.DeviceExtension, 2000)
                        ## the file-hosted container path. no other fields in
                        ## the struct are character based, so we should not 
                        ## hit false positives on this scan. 
                        offset = data.find("\\\x00?\x00?\x00\\\x00")
                        if offset == -1:
                            container = "<HIDDEN>"
                        else:
                            container = obj.Object("String", length = 255, 
                                        offset = device.DeviceExtension + offset, 
                                        encoding = "utf16",
                                        vm = addr_space)
                        yield "Container", "Path: {0}".format(container)
Beispiel #54
0
    def calculate(self):
        if self._config.BASELINEIMG == None:
            print "Baseline image required!"
            sys.exit()

        if self._config.ONLYKNOWN and self._config.ONLYUNKNOWN:
            print "Select only one of the options (-K, -U)!"
            sys.exit(-1)

        #######################################
        #Searching for drivers in baseline image
        ######################################
        # Saving original image
        orig_img = self._config.LOCATION
        # Setting up baseline image
        self._config.LOCATION = "file://" + self._config.BASELINEIMG

        # Instantiating DriverScan plugin
        addr_space = utils.load_as(self._config)
        drv_scan = DriverScan(self._config)

        if volatility.constants.VERSION == "2.6" or volatility.constants.VERSION == "2.4":
            for driver in drv_scan.calculate():
                header = driver.get_object_header()
                if driver.DriverExtension.ServiceKeyName != None:
                    service_key_name = str(
                        driver.DriverExtension.ServiceKeyName).lower()
                else:
                    service_key_name = None

                if header.NameInfo.Name != None:
                    name = str(header.NameInfo.Name).lower()
                else:
                    name = None

                if driver.DriverName != None:
                    driver_name = str(driver.DriverName).lower()
                else:
                    driver_name = None

                if driver.DriverSize != None:
                    driver_size = driver.DriverSize
                else:
                    driver_size = None

                if driver.DriverStart != None:
                    driver_start = driver.DriverStart
                else:
                    driver_start = None

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

                IRPs = {}
                for i, function in enumerate(driver.MajorFunction):
                    function = driver.MajorFunction[i]
                    module = tasks.find_module(
                        mods, mod_addrs, addr_space.address_mask(function))
                    if module:
                        module_name = str(module.BaseDllName or '').lower()
                    else:
                        module_name = "unknown"
                    IRPs[MAJOR_FUNCTIONS[i]] = module_name

                self.baseline_drv_list.append({
                    'service_key_name': service_key_name,
                    'name': name,
                    'driver_name': driver_name,
                    'driver_size': driver_size,
                    'driver_start': driver_start,
                    'irps': IRPs
                })

        else:
            for obj, drv, ext in drv_scan.calculate():
                if ext.ServiceKeyName != None:
                    service_key_name = str(ext.ServiceKeyName).lower()
                else:
                    service_key_name = None

                if obj.NameInfo.Name != None:
                    name = str(obj.NameInfo.Name).lower()
                else:
                    name = None

                if drv.DriverName != None:
                    driver_name = str(drv.DriverName).lower()
                else:
                    driver_name = None

                if drv.DriverSize != None:
                    driver_size = drv.DriverSize
                else:
                    driver_size = None

                if drv.DriverStart != None:
                    driver_start = drv.DriverStart
                else:
                    driver_start = None

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

                IRPs = {}
                for i, function in enumerate(drv.MajorFunction):
                    function = drv.MajorFunction[i]
                    module = tasks.find_module(
                        mods, mod_addrs, addr_space.address_mask(function))
                    if module:
                        module_name = str(module.BaseDllName or '').lower()
                    else:
                        module_name = "unknown"
                    IRPs[MAJOR_FUNCTIONS[i]] = module_name

                self.baseline_drv_list.append({
                    'service_key_name': service_key_name,
                    'name': name,
                    'driver_name': driver_name,
                    'driver_size': driver_size,
                    'driver_start': driver_start,
                    'irps': IRPs
                })

        # Instantiating Modules plugin
        for m in lsmod(addr_space):
            self.baseline_mod_list.append({
                'full_dll_name':
                str(m.FullDllName).lower(),
                'base_dll_name':
                str(m.BaseDllName).lower(),
                'dll_base':
                m.DllBase
            })

            for drv in self.baseline_drv_list:
                if drv['driver_start'] == m.DllBase:
                    if m.FullDllName != None:
                        drv['full_dll_name'] = str(m.FullDllName).lower()
                    else:
                        drv['full_dll_name'] = None
                    if m.BaseDllName != None:
                        drv['base_dll_name'] = str(m.BaseDllName).lower()
                    else:
                        drv['base_dll_name'] = None

        # Fixing entries that are not in the list of loaded modules list
        for drv in self.baseline_drv_list:
            f = False
            for m in self.baseline_mod_list:
                if m['dll_base'] == drv['driver_start']:
                    f = True
            if not f:
                drv['full_dll_name'] = None
                drv['base_dll_name'] = None

        ####################################
        #Searching for drivers in the image to be analyzed
        ##################################
        # Restoring original image
        self._config.LOCATION = orig_img

        # Instantiating DriverScan plugin
        addr_space = utils.load_as(self._config)
        drv_scan = DriverScan(self._config)

        if volatility.constants.VERSION == "2.6" or volatility.constants.VERSION == "2.4":
            for driver in drv_scan.calculate():
                header = driver.get_object_header()
                if driver.DriverExtension.ServiceKeyName != None:
                    service_key_name = str(
                        driver.DriverExtension.ServiceKeyName).lower()
                else:
                    service_key_name = None

                if header.NameInfo.Name != None:
                    name = str(header.NameInfo.Name).lower()
                else:
                    name = None

                if driver.DriverName != None:
                    driver_name = str(driver.DriverName).lower()
                else:
                    driver_name = None

                if driver.DriverSize != None:
                    driver_size = driver.DriverSize
                else:
                    driver_size = None

                if driver.DriverStart != None:
                    driver_start = driver.DriverStart
                else:
                    driver_start = None

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

                IRPs = {}
                for i, function in enumerate(driver.MajorFunction):
                    function = driver.MajorFunction[i]
                    module = tasks.find_module(
                        mods, mod_addrs, addr_space.address_mask(function))
                    if module:
                        module_name = str(module.BaseDllName or '').lower()
                    else:
                        module_name = "unknown"
                    IRPs[MAJOR_FUNCTIONS[i]] = module_name

                self.image_drv_list.append({
                    'service_key_name': service_key_name,
                    'name': name,
                    'driver_name': driver_name,
                    'driver_size': driver_size,
                    'driver_start': driver_start,
                    'irps': IRPs,
                    'obj': header,
                    'drv': driver,
                    'ext': driver.DriverExtension
                })

        else:
            for obj, drv, ext in drv_scan.calculate():
                if ext.ServiceKeyName != None:
                    service_key_name = str(ext.ServiceKeyName).lower()
                else:
                    service_key_name = None

                if obj.NameInfo.Name != None:
                    name = str(obj.NameInfo.Name).lower()
                else:
                    name = None

                if drv.DriverName != None:
                    driver_name = str(drv.DriverName).lower()
                else:
                    driver_name = None

                if drv.DriverSize != None:
                    driver_size = drv.DriverSize
                else:
                    driver_size = None

                if drv.DriverStart != None:
                    driver_start = drv.DriverStart
                else:
                    driver_start = None

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

                IRPs = {}
                for i, function in enumerate(drv.MajorFunction):
                    function = drv.MajorFunction[i]
                    module = tasks.find_module(
                        mods, mod_addrs, addr_space.address_mask(function))
                    if module:
                        module_name = str(module.BaseDllName or '').lower()
                    else:
                        module_name = "unknown"
                    IRPs[MAJOR_FUNCTIONS[i]] = module_name

                self.image_drv_list.append({
                    'service_key_name': service_key_name,
                    'name': name,
                    'driver_name': driver_name,
                    'driver_size': driver_size,
                    'driver_start': driver_start,
                    'irps': IRPs,
                    'obj': obj,
                    'drv': drv,
                    'ext': ext
                })

        for m in lsmod(addr_space):
            self.image_mod_list.append({
                'full_dll_name':
                str(m.FullDllName).lower(),
                'base_dll_name':
                str(m.BaseDllName).lower(),
                'dll_base':
                m.DllBase
            })
            for drv in self.image_drv_list:
                if drv['driver_start'] == m.DllBase:
                    if m.FullDllName != None:
                        drv['full_dll_name'] = str(m.FullDllName).lower()
                    else:
                        drv['full_dll_name'] = None
                    if m.BaseDllName != None:
                        drv['base_dll_name'] = str(m.BaseDllName).lower()
                    else:
                        drv['base_dll_name'] = None

        # Fixing up entries that are not in the list of loaded modules list
        for drv in self.image_drv_list:
            f = False
            for m in self.image_mod_list:
                if m['dll_base'] == drv['driver_start']:
                    f = True
            if not f:
                drv['full_dll_name'] = None
                drv['base_dll_name'] = None

        # Compare the lists
        for drv in self.image_drv_list:
            known = False
            d_name = False
            drv_name = False
            drv_size = False
            drv_mod = False
            drv_irp = False
            drv_bl = None
            for bl_drv in self.baseline_drv_list:

                if drv['service_key_name'] == bl_drv['service_key_name']:
                    known = True

                    if drv['name'] == bl_drv['name']:
                        d_name = True
                    elif self._config.VERBOSE:
                        print "Name:"
                        print "Baseline: " + bl_drv['name']
                        print "Image:    " + drv['name']

                    if drv['driver_name'] == bl_drv['driver_name']:
                        drv_name = True
                    elif self._config.VERBOSE:
                        print "Driver Name:"
                        print "Baseline: " + str(bl_drv['driver_name'])
                        print "Image:    " + str(drv['driver_name'])

                    if drv['driver_size'] == bl_drv['driver_size']:
                        drv_size = True
                    elif self._config.VERBOSE:
                        print "Driver Size:"
                        print "Baseline: " + str(bl_drv['driver_size'])
                        print "Image:    " + str(drv['driver_size'])

                    if drv['full_dll_name'] == bl_drv['full_dll_name']:
                        drv_mod = True
                    elif self._config.VERBOSE:
                        print "Module:"
                        print "Baseline: " + str(bl_drv['full_dll_name'])
                        print "Image:    " + str(drv['full_dll_name'])

                    drv_irp = True
                    for m in drv['irps']:
                        if drv['irps'][m] != bl_drv['irps'][m]:
                            drv_irp = False

                if known:
                    drv_bl = bl_drv
                    break

            if self._config.ONLYKNOWN:
                if known:
                    yield (drv['obj'], drv['drv'], drv['ext'], known, d_name,
                           drv_name, drv_mod, drv_size, drv['full_dll_name'],
                           drv_irp, drv['irps'], drv_bl['irps'])
            if self._config.ONLYUNKNOWN:
                if not known:
                    yield (drv['obj'], drv['drv'], drv['ext'], known, d_name,
                           drv_name, drv_mod, drv_size, drv['full_dll_name'],
                           drv_irp, drv['irps'], None)
            if not self._config.ONLYKNOWN and not self._config.ONLYUNKNOWN:
                if drv_bl:
                    yield (drv['obj'], drv['drv'], drv['ext'], known, d_name,
                           drv_name, drv_mod, drv_size, drv['full_dll_name'],
                           drv_irp, drv['irps'], drv_bl['irps'])
                else:
                    yield (drv['obj'], drv['drv'], drv['ext'], known, d_name,
                           drv_name, drv_mod, drv_size, drv['full_dll_name'],
                           drv_irp, drv['irps'], None)
Beispiel #55
0
    def calculate(self):

        addr_space = utils.load_as(self._config)

        if not has_distorm3:
            debug.error("Install distorm3 code.google.com/p/distorm/")

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

        if not self._config.SKIP_PROCESS:
            for proc in self.filter_tasks(tasks.pslist(addr_space)):
                process_name = str(proc.ImageFileName).lower()

                if (self._config.QUICK
                        and process_name not in self.critical_process):
                    #debug.debug("Skipping non-critical process {0} ({1})".format(
                    #    process_name, proc.UniqueProcessId))
                    continue

                process_space = proc.get_process_address_space()
                if not process_space:
                    #debug.debug("Cannot acquire process AS for {0} ({1})".format(
                    #    process_name, proc.UniqueProcessId))
                    continue

                module_group = ModuleGroup(proc.get_load_modules())

                for dll in module_group.mods:

                    if not process_space.is_valid_address(dll.DllBase):
                        continue

                    dll_name = str(dll.BaseDllName or '').lower()

                    if (self._config.QUICK
                            and dll_name not in self.critical_dlls
                            and dll.DllBase != proc.Peb.ImageBaseAddress):
                        #debug.debug("Skipping non-critical dll {0} at {1:#x}".format(
                        #    dll_name, dll.DllBase))
                        continue

                    #debug.debug("Analyzing {0}!{1}".format(process_name, dll_name))

                    for hook in self.get_hooks(HOOK_MODE_USER, process_space,
                                               dll, module_group):
                        yield proc, dll, hook

        if not self._config.SKIP_KERNEL:
            process_list = list(tasks.pslist(addr_space))
            module_group = ModuleGroup(modules.lsmod(addr_space))

            for mod in module_group.mods:

                #module_name = str(mod.BaseDllName or '')
                #debug.debug("Analyzing {0}".format(module_name))

                kernel_space = tasks.find_space(addr_space, process_list,
                                                mod.DllBase)

                if not kernel_space:
                    #debug.debug("No kernel AS for {0} at {1:#x}".format(
                    #    module_name, mod.DllBase))
                    continue

                for hook in self.get_hooks(HOOK_MODE_KERNEL, kernel_space, mod,
                                           module_group):
                    yield None, mod, hook
Beispiel #56
0
    def calculate(self):
        addr_space = utils.load_as(self._config)

        # we currently don't use this on x64 because for some reason the 
        # x64 version actually doesn't create a DisplayVersion value 
        memory_model = addr_space.profile.metadata.get('memory_model')
        if memory_model == '32bit':
            regapi = registryapi.RegistryApi(self._config)
            regapi.reset_current()
            regapi.set_current(hive_name = "software")
            x86key = "Microsoft\\Windows\\CurrentVersion\\Uninstall"
            x64key = "Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
            for subkey in regapi.reg_get_all_subkeys(None, key = x86key):
                if str(subkey.Name) == "TrueCrypt":
                    subpath = x86key + "\\" + subkey.Name
                    version = regapi.reg_get_value("software", 
                                            key = subpath, 
                                            value = "DisplayVersion")
                    if version:
                        yield "Registry Version", "{0} Version {1}".format(
                            str(subkey.Name),
                            version)

        scanner = TrueCryptPassphrase(self._config)
        for offset, passphrase in scanner.calculate():
            yield "Password", "{0} at offset {1:#x}".format(
                        passphrase, offset)

        for proc in tasks.pslist(addr_space):
            if str(proc.ImageFileName).lower() == "truecrypt.exe":     
                yield "Process", "{0} at {1:#x} pid {2}".format(
                        proc.ImageFileName,
                        proc.obj_offset, 
                        proc.UniqueProcessId)   

        scanner = svcscan.SvcScan(self._config)
        for service in scanner.calculate():
            name = str(service.ServiceName.dereference())
            if name == "truecrypt":
                yield "Service", "{0} state {1}".format(
                        name, 
                        service.State)

        for mod in modules.lsmod(addr_space):
            basename = str(mod.BaseDllName or '').lower()
            fullname = str(mod.FullDllName or '').lower()
            if (basename.endswith("truecrypt.sys") or 
                        fullname.endswith("truecrypt.sys")):
                yield "Kernel Module",  "{0} at {1:#x} - {2:#x}".format(
                        mod.BaseDllName, 
                        mod.DllBase, 
                        mod.DllBase + mod.SizeOfImage)

        scanner = filescan.SymLinkScan(self._config)
        for symlink in scanner.calculate():
            object_header = symlink.get_object_header()
            if "TrueCryptVolume" in str(symlink.LinkTarget or ''):
                yield "Symbolic Link", "{0} -> {1} mounted {2}".format(
                        str(object_header.NameInfo.Name or ''), 
                        str(symlink.LinkTarget or ''), 
                        str(symlink.CreationTime or ''))

        scanner = filescan.FileScan(self._config)
        for fileobj in scanner.calculate():
            filename = str(fileobj.file_name_with_device() or '')
            if "TrueCryptVolume" in filename:
                yield "File Object", "{0} at {1:#x}".format(
                        filename,
                        fileobj.obj_offset)
        
        scanner = filescan.DriverScan(self._config)
        for driver in scanner.calculate():
            object_header = driver.get_object_header() 
            driverext = driver.DriverExtension
            drivername = str(driver.DriverName or '')
            servicekey = str(driverext.ServiceKeyName or '')
            if (drivername.endswith("truecrypt") or 
                        servicekey.endswith("truecrypt")):
                yield "Driver", "{0} at {1:#x} range {2:#x} - {3:#x}".format(
                        drivername, 
                        driver.obj_offset, 
                        driver.DriverStart, 
                        driver.DriverStart + driver.DriverSize)
                for device in driver.devices():
                    header = device.get_object_header()
                    devname = str(header.NameInfo.Name or '')
                    type = devicetree.DEVICE_CODES.get(device.DeviceType.v())
                    yield "Device", "{0} at {1:#x} type {2}".format(
                        devname or "<HIDDEN>", 
                        device.obj_offset, 
                        type or "UNKNOWN")
                    if type == "FILE_DEVICE_DISK":
                        data = addr_space.read(device.DeviceExtension, 2000)
                        ## the file-hosted container path. no other fields in
                        ## the struct are character based, so we should not 
                        ## hit false positives on this scan. 
                        offset = data.find("\\\x00?\x00?\x00\\\x00")
                        if offset == -1:
                            container = "<HIDDEN>"
                        else:
                            container = obj.Object("String", length = 255, 
                                        offset = device.DeviceExtension + offset, 
                                        encoding = "utf16",
                                        vm = addr_space)
                        yield "Container", "Path: {0}".format(container)
Beispiel #57
0
    def calculate(self):

        if not has_distorm:
            debug.error("You must install distorm3")

        addr_space = utils.load_as(self._config)

        all_tasks = list(tasks.pslist(addr_space))
        all_mods = list(modules.lsmod(addr_space))

        # Operate in kernel mode if pid is not supplied
        if not self._config.PID:
            if not self._config.BASE:
                debug.error("You must specify --BASE")

            base_address = self._config.BASE
            size_to_read = self._config.SIZE

            # Get the size from the module list if its not supplied
            if not size_to_read:
                for module in all_mods:
                    if module.DllBase == base_address:
                        size_to_read = module.SizeOfImage
                        break
                # Alternately, try the size from the PE header
                if not size_to_read:
                    pefile = obj.Object("_IMAGE_DOS_HEADER",
                                        offset=base_address,
                                        vm=addr_space)
                    try:
                        nt_header = pefile.get_nt_header()
                        size_to_read = nt_header.OptionalHeader.SizeOfImage
                    except ValueError:
                        pass

                    if not size_to_read:
                        debug.error("You must specify --SIZE")

            kernel_space = tasks.find_space(addr_space, all_tasks,
                                            base_address)

            if not kernel_space:
                debug.error("Cannot read supplied address")

            data = kernel_space.zread(base_address, size_to_read)
            apis = self.enum_apis(all_mods)
            addr_space = kernel_space
        else:
            # In process mode, we find the process by PID
            task = None

            for atask in all_tasks:
                if atask.UniqueProcessId == self._config.PID:
                    task = atask
                    break

            if not task:
                debug.error("You must supply an active PID")

            task_space = task.get_process_address_space()

            if not task_space:
                debug.error("Cannot acquire process AS")

            all_mods = list(task.get_load_modules())

            # PEB is paged or no DLLs loaded
            if not all_mods:
                debug.error("Cannot load DLLs in process AS")

            # If an address is supplied with a size, try to get
            # the size from the vad node. If neither are supplied,
            # assume we should carve the main process executable.
            if self._config.BASE:
                base_address = self._config.BASE
                size_to_read = self._config.SIZE

                if not size_to_read:
                    for vad in task.VadRoot.traverse():
                        if base_address >= vad.Start and base_address <= vad.End:
                            size_to_read = vad.Length
                    if not size_to_read:
                        debug.error("You must specify --SIZE")
            else:
                # Its OK to blindly take the 0th element because the
                # executable is always the first module to load.
                base_address = all_mods[0].DllBase
                size_to_read = all_mods[0].SizeOfImage

            data = task_space.zread(base_address, size_to_read)
            apis = self.enum_apis(all_mods)
            addr_space = task_space

        # This is a dictionary of confirmed API calls.
        calls_imported = dict(
            (iat, call)
            for (_, iat,
                 call) in self.call_scan(addr_space, base_address, data)
            if call in apis)

        # Scan forward
        self._vicinity_scan(addr_space,
                            calls_imported,
                            apis,
                            base_address,
                            len(data),
                            forward=True)

        # Scan reverse
        self._vicinity_scan(addr_space,
                            calls_imported,
                            apis,
                            base_address,
                            len(data),
                            forward=False)

        for iat, call in sorted(calls_imported.items()):
            yield iat, call, apis[call][0], apis[call][1]
Beispiel #58
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