def calculate(self):
        linux_common.set_plugin_members(self)
        # Automatically initialize task_struct offsets
        task_struct.init_offsets(self.addr_space)
        if not all([task_struct.is_offset_defined(memname) for memname in ['comm', 'tasks', 'mm']]):
            debug.warning("Some of required members of 'task_struct' structure were not found.")
            return

        ksymbol_command = linux_auto_ksymbol(self._config)
        init_task_addr = ksymbol_command.get_symbol('init_task')
        if init_task_addr is None:
            debug.warning("Can't locate the first process (swapper).")
            return
        init_task = obj.Object('task_struct', offset=init_task_addr, vm=self.addr_space)
        tasks_dtb_list = []
        for task in init_task.tasks:
            if mm_struct.is_offset_defined('pgd'):
                pgd = task.mm.pgd
                if pgd:
                    tasks_dtb_list.append(self.addr_space.vtop(pgd))
            yield task
        # List unnamed potentially hidden or terminated processes
        # auto-discovered by dtblist command.
        dtblist_command = linux_auto_dtblist(self._config)
        for dtb in dtblist_command.calculate():
            if dtb not in tasks_dtb_list:
                yield dtb
Esempio n. 2
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        knl_addr = self.addr_space.profile.get_symbol("keyboard_notifier_list")
        
        if not knl_addr:
            debug.error("Symbol keyboard_notifier_list not found in kernel")
            
        knl = obj.Object("atomic_notifier_head", offset = knl_addr, vm = self.addr_space)
        
        symbol_cache = {}
        
        for call_back in linux_common.walk_internal_list("notifier_block", "next", knl.head):
            call_addr = call_back.notifier_call
            
            if symbol_cache.has_key(call_addr):
                sym_name = symbol_cache[call_addr]
                hooked = 0

            else:
                sym_name = self.profile.get_symbol_by_address("kernel", call_addr)
                if not sym_name:
                    sym_name = "HOOKED"
                    
                    module = obj.Object("module", offset = 0xffffffffa03a15d0, vm = self.addr_space)
                    sym = module.get_symbol_for_address(call_addr)
     
                    sym_name = "%s: %s/%s" % (sym_name, module.name, sym)

                hooked = 1            
        
            symbol_cache[call_addr] = sym_name

            yield call_addr, sym_name, hooked
Esempio n. 3
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        for cache in self.get_all_kmem_caches():
            if cache.get_type() == "slab":
                active_objs = 0
                active_slabs = 0
                num_slabs = 0
                # shared_avail = 0

                for slab in cache._get_full_list():
                    active_objs += cache.num
                    active_slabs += 1

                for slab in cache._get_partial_list():
                    active_objs += slab.inuse
                    active_slabs += 1

                for slab in cache._get_free_list():
                    num_slabs += 1

                num_slabs += active_slabs
                num_objs = num_slabs * cache.num

                yield [cache.get_name(),
                        active_objs,
                        num_objs,
                        cache.buffer_size,
                        cache.num,
                        1 << cache.gfporder,
                        active_slabs,
                        num_slabs]
Esempio n. 4
0
    def calculate(self):
        """
        Get all the python strings for a task, and assume those strings
        might be keys of a dictionary entry.  Return the valid dictionary
        entries from that pool of maybes.

        This repeats a lot of linux_python_strings's code, but we want to get
        python strings per task, so we can optimize the bytstring search.
        """
        linux_common.set_plugin_members(self)

        tasks = [task for task in linux_pslist.linux_pslist.calculate(self)
                 if _is_python_task(task)]

        for task in tasks:
            addr_space = task.get_process_address_space()
            memory_model = addr_space.profile.metadata.get('memory_model',
                                                           '32bit')
            pack_format = "I" if memory_model == '32bit' else "Q"

            bytestrings = [
                # the hash as bytes
                struct.pack(pack_format.lower(), py_string.ob_shash) +
                # the pointer the PyStringObject as bytes
                struct.pack(pack_format, py_string.obj_offset)
                for py_string in find_python_strings(task)
            ]

            for address in task.search_process_memory(bytestrings,
                                                      heap_only=True):
                py_dict_entry = obj.Object("_PyDictEntry",
                                           offset=address,
                                           vm=addr_space)
                if py_dict_entry.is_valid():
                    yield task, py_dict_entry
Esempio n. 5
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        tasks = linux_pslist.linux_pslist.calculate(self)

        for task in tasks:
            for elf, elf_start, elf_end, soname, needed in task.elfs():
                yield task, elf, elf_start, elf_end, soname, needed
Esempio n. 6
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        
        modules  = linux_lsmod.linux_lsmod(self._config).get_modules()
        op_members  = self.profile.types['file_operations'].keywords["members"].keys()
        seq_members = self.profile.types['seq_operations'].keywords["members"].keys()       

        tcp = ("tcp_seq_afinfo", ["tcp6_seq_afinfo", "tcp4_seq_afinfo"])
        udp = ("udp_seq_afinfo", ["udplite6_seq_afinfo", "udp6_seq_afinfo", "udplite4_seq_afinfo", "udp4_seq_afinfo"])
        protocols = [tcp, udp]

        for proto in protocols:
            
            struct_type = proto[0]

            for global_var_name in proto[1]:
                
                global_var_addr = self.addr_space.profile.get_symbol(global_var_name)

                if not global_var_addr:
                    continue

                global_var = obj.Object(struct_type, offset = global_var_addr, vm = self.addr_space)

                for (name, member, address) in self.check_afinfo(global_var_name, global_var, op_members, seq_members, modules):
                    yield (name, member, address)
Esempio n. 7
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        modules_addr = self.get_profile_symbol("modules")

        modules = obj.Object("list_head", vm = self.addr_space, offset = modules_addr)

        # walk the modules list
        for module in modules.list_of_type("module", "list"):

            #if str(module.name) == "rootkit":
            #    continue

            if self._config.PARAMS:

                if not hasattr(module, "kp"):
                    debug.error("Gathering module parameters is not supported in this profile.")

                params = self.get_params(module)
            else:
                params = ""

            if self._config.SECTIONS:
                sections = self.get_sections(module)
            else:
                sections = []

            yield (module, sections, params)
Esempio n. 8
0
    def render_text(self, outfd, data):
        linux_common.set_plugin_members(self)
        self.edir = self._config.DUMP_DIR

        if not self.edir:
            debug.error("No output directory given.")

        if not os.path.isdir(self.edir):
            debug.error(self.edir + " is not a directory")

        for task in linux_netstat.linux_netstat(self._config).calculate():
            sfop = task.obj_vm.profile.get_symbol("socket_file_ops")
            dfop = task.obj_vm.profile.get_symbol("sockfs_dentry_operations")

            for (filp, fdnum) in task.lsof():
                if filp.f_op == sfop or filp.dentry.d_op == dfop:
                    iaddr = filp.dentry.d_inode
                    skt = task.SOCKET_I(iaddr)
                    sk = skt.sk

                    for msg in self.process_queue(
                            "receive", task.pid, fdnum, sk.sk_receive_queue):
                        outfd.write(msg + "\n")

                    for msg in self.process_queue(
                            "write", task.pid, fdnum, sk.sk_write_queue):
                        outfd.write(msg + "\n")
Esempio n. 9
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        find_file  = self._config.FIND
        inode_addr = self._config.inode        
        outfile    = self._config.outfile
        listfiles  = self._config.LISTFILES

        if listfiles:
             for (_, _, file_path, file_dentry) in self.walk_sbs():
                yield (file_path, file_dentry.d_inode)

        elif find_file and len(find_file):
            for (_, _, file_path, file_dentry) in self.walk_sbs():
                if file_path == find_file:
                    yield (file_path, file_dentry.d_inode)
                    break

        elif inode_addr and inode_addr > 0 and outfile and len(outfile) > 0:
            inode = obj.Object("inode", offset = inode_addr, vm = self.addr_space)
            
            f = open(outfile, "wb")
            
            for page in self.get_file_contents(inode):        
                f.write(page)

            f.close()

        else:
            debug.error("Incorrect command line parameters given.")
Esempio n. 10
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        for dentry_offset in self._compare_filps():
            dentry = obj.Object("dentry", offset = dentry_offset, vm = self.addr_space)
            if dentry.d_count > 0 and dentry.d_inode.is_reg() and dentry.d_flags == 128:
                yield dentry
Esempio n. 11
0
    def get_file_contents(self, inode):
        linux_common.set_plugin_members(self)
        data = ""
        file_size = inode.i_size

        if not inode.is_valid() or file_size == None:
            raise StopIteration

        extra = file_size % 4096
        idxs = file_size / 4096

        if extra > 0:
            extra = 4096 - extra
            idxs = idxs + 1

        if idxs > 1000000000:
            raise StopIteration

        for idx in range(0, idxs):
            data = self.get_page_contents(inode, idx)
                
            # this is to chop off any extra data on the last page
            if idx == idxs - 1:
                if extra > 0:
                    extra = extra * -1
                    data = data[:extra]
            
            yield data
Esempio n. 12
0
    def get_file_contents(self, inode):
        linux_common.set_plugin_members(self)
        if self.addr_space.profile.metadata.get('memory_model', '32bit') == "32bit":
            self.ptr_size = 4
        else:
            self.ptr_size = 8

        data = ""
        file_size = inode.i_size

        if not inode.is_valid() or file_size == None:
            raise StopIteration

        extra = file_size % 4096
        idxs = file_size / 4096

        if extra > 0:
            extra = 4096 - extra
            idxs = idxs + 1

        if idxs > 1000000000:
            raise StopIteration
            
        for idx in range(0, idxs):
            data = self.get_page_contents(inode, idx)
                
            # this is to chop off any extra data on the last page
            if idx == idxs - 1:
                if extra > 0:
                    extra = extra * -1
                    data = data[:extra]
            
            yield data
Esempio n. 13
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        for (_, _, file_path, file_dentry)in linux_find_file.linux_find_file(self._config).walk_sbs():
            inode = file_dentry.d_inode

            yield inode, inode.i_ino, file_path
Esempio n. 14
0
    def _walk_xarray_pids(self):
        ff = find_file.linux_find_file(self._config)
        linux_common.set_plugin_members(ff)

        self.XARRAY_TAG_MASK     = 3
        self.XARRAY_TAG_INTERNAL = 2

        self.XA_CHUNK_SHIFT = 6
        self.XA_CHUNK_SIZE  = 1 << self.XA_CHUNK_SHIFT
        self.XA_CHUNK_MASK  = self.XA_CHUNK_SIZE - 1

        ns_addr = self.addr_space.profile.get_symbol("init_pid_ns")
        ns = obj.Object("pid_namespace", offset = ns_addr, vm = self.addr_space)
 
        xarray = ns.idr.idr_rt

        if not xarray.is_valid():
            return

        root = xarray.xa_head.v()

        is_internal = ff.xa_is_internal(root)

        if root & self.XARRAY_TAG_MASK != 0:
            root = root & ~self.XARRAY_TAG_MASK

        height = 0
        node   = obj.Object("xa_node", offset = root, vm = self.addr_space)
        
        if is_internal and hasattr(node, "shift"):
            height = (node.shift / self.XA_CHUNK_SHIFT) + 1

        for node in self._do_walk_xarray(ff, node, height, 0):
            if node and node.is_valid():
                yield node
 def calculate(self):
 
     ## we need this module imported
     if not has_yara:
         debug.error("Please install Yara from https://plusvic.github.io/yara/")
         
     ## leveraged from the windows yarascan plugin
     rules = self._compile_rules()
         
     ## set the linux plugin address spaces 
     linux_common.set_plugin_members(self)
 
     if self._config.KERNEL:
         ## the start of kernel memory taken from VolatilityLinuxIntelValidAS
         if self.addr_space.profile.metadata.get('memory_model', '32bit') == "32bit":
             kernel_start = 0xc0000000
         else:
             kernel_start = 0xffffffff80000000
         
         scanner = malfind.DiscontigYaraScanner(rules = rules,
                                                address_space = self.addr_space)
                                                
         for hit, address in scanner.scan(start_offset = kernel_start):
             yield (None, address - self._config.REVERSE, hit,
                     scanner.address_space.zread(address - self._config.REVERSE, self._config.SIZE))
     else:
         tasks = self.filter_tasks()
         for task in tasks: 
             scanner = VmaYaraScanner(task = task, rules = rules)
             for hit, address in scanner.scan():
                 yield (task, address - self._config.REVERSE, hit,
                             scanner.address_space.zread(address - self._config.REVERSE, self._config.SIZE))
Esempio n. 16
0
 def calculate(self):
 
     ## we need this module imported
     if not has_yara:
         debug.error("Please install Yara from code.google.com/p/yara-project")
         
     ## leveraged from the windows yarascan plugin
     rules = self._compile_rules()
         
     ## set the linux plugin address spaces 
     linux_common.set_plugin_members(self)
 
     if self._config.KERNEL:
         ## the start of kernel memory taken from VolatilityLinuxIntelValidAS
         if self.addr_space.profile.metadata.get('memory_model', '32bit') == "32bit":
             kernel_start = 0xc0000000
         else:
             kernel_start = 0xffffffff80000000
         
         scanner = malfind.DiscontigYaraScanner(rules = rules,
                                                address_space = self.addr_space)
                                                
         for hit, address in scanner.scan(start_offset = kernel_start):
             yield (None, address, hit, 
                     scanner.address_space.zread(address, 64))
     else:
         for task in pslist.linux_pslist(self._config).calculate():
             scanner = VmaYaraScanner(task = task, rules = rules)
             for hit, address in scanner.scan():
                 yield (task, address, hit, 
                             scanner.address_space.zread(address, 64))
Esempio n. 17
0
    def calculate(self):
        """ 
        This works by walking the system call table 
        and verifies that each is a symbol in the kernel
        """
        linux_common.set_plugin_members(self)
        
        num_syscalls = self._get_syscall_table_size()
        syscall_addr = self._get_syscall_table_address()
        
        sym_addrs = self.profile.get_all_addresses()
        
        
        table = obj.Object("Array", offset = syscall_addr, vm = self.addr_space, targetType = "unsigned int", count = num_syscalls)
        
        for (i, call_addr) in enumerate(table):
            
            if not call_addr:
                continue

            # have to treat them as 'long' so need to mask
            call_addr = call_addr & 0xffffffff
                
            if not call_addr in sym_addrs:
                yield(i, call_addr, 1)
            else:
                yield(i, call_addr, 0)
Esempio n. 18
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        find_file  = self._config.FIND
        inode_addr = self._config.inode        
        outfile    = self._config.outfile
        listfiles  = self._config.LISTFILES

        if listfiles:
             for (_, _, file_path, file_dentry) in self.walk_sbs():
                yield (file_path, file_dentry.d_inode)

        elif find_file and len(find_file):
            for (_, _, file_path, file_dentry) in self.walk_sbs():
                if file_path == find_file:
                    yield (file_path, file_dentry.d_inode)
                    break

        elif inode_addr and inode_addr > 0 and outfile and len(outfile) > 0:
            inode = obj.Object("inode", offset = inode_addr, vm = self.addr_space)
           
            try: 
                f = open(outfile, "wb")
            except IOError, e:
                debug.error("Unable to open output file (%s): %s" % (outfile, str(e)))

            for page in self.get_file_contents(inode):        
                f.write(page)

            f.close()
Esempio n. 19
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        fs_types = self._get_filesystem_types()

        # newer kernels
        if self.profile.has_type("mount"):
            mnttype = "mount"

            cache = linux_slabinfo(self._config).get_kmem_cache(mnttype, self._config.UNALLOCATED)

            for task in linux_pslist.linux_pslist(self._config).calculate():
                if task.pid == 1:
                    ns = task.nsproxy.mnt_ns
                    break
        else:
            cache = linux_slabinfo(self._config).get_kmem_cache(
                "mnt_cache", self._config.UNALLOCATED, struct_name="vfsmount"
            )
            ns = None

        for mnt in cache:
            ret = self._parse_mnt(mnt, ns, fs_types)

            if ret:
                (mnt_sb, dev_name, path, fstype, rr, mnt_string) = ret

                if not (dev_name == "devtmpfs" and path == "/"):
                    yield (mnt_sb, dev_name, path, fstype, rr, mnt_string)
Esempio n. 20
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        io_ptr = self.addr_space.profile.get_symbol("iomem_resource")

        for r in self.yield_resource(io_ptr):
            yield r
Esempio n. 21
0
    def render_text(self, outfd, data):
        linux_common.set_plugin_members(self)
        
        self.table_header(outfd, [("Task", "10"), 
                                  ("ELF Start", "[addrpad]"), 
                                  ("ELF Name", "24"),
                                  ("Symbol", "24"),
                                  ("Resolved Address", "[addrpad]"),
                                  ("H", "1"),
                                  ("Target Info", "")])
            
        ignore = frozenset(self._config.IGNORE)

        for task in data:
            for soname, elf, elf_start, elf_end, addr, symbol_name, hookdesc, hooked in task.plt_hook_info():
                if not hooked and not self._config.ALL:
                    continue

                if hookdesc in ignore:
                    continue

                if hookdesc == '[RTLD_LAZY]' and not self._config.ALL:
                    continue

                self.table_row(outfd, task.pid, elf_start, soname if soname else '[main]', \
                    symbol_name, addr, '!' if hooked else ' ', hookdesc)
Esempio n. 22
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        hook_names = ["PRE_ROUTING", "LOCAL_IN", "FORWARD", "LOCAL_OUT", "POST_ROUTING"]
        proto_names = ["", "", "IPV4", "", "", "", "", "", "", "", "" , "", "", ""]

        # struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS]
        # NFPROTO_NUMPROTO = 12
        # NF_MAX_HOOKS = 7
     
        nf_hooks_addr = self.addr_space.profile.get_symbol("nf_hooks")

        if nf_hooks_addr == None:
            debug.error("Unable to analyze NetFilter. It is either disabled or compiled as a module.")

        modules  = linux_lsmod.linux_lsmod(self._config).get_modules()
         
        list_head_size = self.addr_space.profile.get_obj_size("list_head")
        
        for outer in range(13):
            arr = nf_hooks_addr + (outer * (list_head_size * 8))
           
            for inner in range(7):
                list_head = obj.Object("list_head", offset = arr + (inner * list_head_size), vm = self.addr_space)
        
                for hook_ops in list_head.list_of_type("nf_hook_ops", "list"):
                    if self.is_known_address(hook_ops.hook.v(), modules):
                        hooked = "False"
                    else:
                        hooked = "True"

                    yield proto_names[outer], hook_names[inner], hook_ops.hook.v(), hooked
Esempio n. 23
0
    def get_file_contents(self, inode):
        linux_common.set_plugin_members(self)
        data = ""
        file_size = inode.i_size

        extra = file_size % 4096

        idxs = file_size / 4096

        if extra != 0:
            extra = 4096 - extra
            idxs = idxs + 1

        for idx in range(0, idxs):

            data = data + self.get_page_contents(inode, idx)

        # this is chop off any extra data on the last page

        if extra != 0:
            extra = extra * -1

            data = data[:extra]

        return data
Esempio n. 24
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        ps_sources = {}

        # The keys are names of process sources
        # The values are the virtual offset of the task_struct

        ps_sources['pslist']     = self._get_pslist()
        ps_sources['pid_hash']   = self._get_pid_hash()
        ps_sources['kmem_cache'] = self._get_kmem_cache()
        ps_sources['parents']    = self._get_task_parents()
        ps_sources['thread_leaders'] = self._get_thread_leaders()

        # Build a list of offsets from all sources
        seen_offsets = []
        for source in ps_sources:

            tasks = ps_sources[source]

            for offset in tasks:

                if offset not in seen_offsets:
                    seen_offsets.append(offset)
                    yield offset, obj.Object("task_struct", offset = offset, vm = self.addr_space), ps_sources
Esempio n. 25
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        ntables_ptr = obj.Object("Pointer", offset = self.get_profile_symbol("neigh_tables"), vm = self.addr_space)

        for ntable in linux_common.walk_internal_list("neigh_table", "next", ntables_ptr):
            yield self.handle_table(ntable)
Esempio n. 26
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        modules = linux_lsmod.linux_lsmod(self._config).get_modules()

        f_op_members = self.profile.types["file_operations"].keywords["members"].keys()
        f_op_members.remove("owner")

        if self._config.INODE:
            inode = obj.Object("inode", offset=self._config.INODE, vm=self.addr_space)
            if not inode.is_valid():
                debug.error(
                    "Invalid inode address given. Please use linux_find_file to determine valid inode addresses."
                )

            for (hooked_member, hook_address) in self.verify_ops(inode.i_fop, f_op_members, modules):
                yield ("inode at {0:x}".format(inode.obj_offset), hooked_member, hook_address)

        else:
            funcs = [self.check_open_files_fop, self.check_proc_fop, self.check_proc_root_fops, self.check_file_cache]

            for func in funcs:

                for (name, member, address) in func(f_op_members, modules):
                    yield (name, member, address)
Esempio n. 27
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        find_file  = self._config.FIND
        inode_addr = self._config.inode        
        outfile    = self._config.outfile

        if find_file and len(find_file):

            wanted_dentry = self.walk_sbs(find_file)

            if wanted_dentry:
                yield wanted_dentry

        elif inode_addr and inode_addr > 0 and outfile and len(outfile) > 0:
        
            inode = obj.Object("inode", offset=inode_addr, vm=self.addr_space)
            
            contents = self.get_file_contents(inode)

            f = open(outfile, "wb")
            f.write(contents)
            f.close()

        else:
            debug.error("Incorrect command line parameters given.")
Esempio n. 28
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        init_task_addr = self.get_profile_symbol("init_task")

        init_task = obj.Object("task_struct", vm = self.addr_space, offset = init_task_addr)

        pidlist = self._config.PID
	pnamelist = self._config.PROCNAMES
        #pdb.set_trace	

        if pidlist:
            pidlist = [int(p) for p in self._config.PID.split(',')]
	if pnamelist:
	    pnamelist = [str(q) for q in self._config.PROCNAMES.split(',')]

	print pidlist
	print pnamelist
        # walk the ->tasks list, note that this will *not* display "swapper"
        for task in init_task.tasks:
	  type(task.comm)
	  #print task.comm 
	  if not pidlist and not pnamelist:
		yield task
	  else: 
		if pidlist and task.pid in pidlist:
			yield task
	        if pnamelist and str(task.comm) in pnamelist:
			yield task
Esempio n. 29
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        phys_addr_space = utils.load_as(self._config, astype="physical")

        if phys_addr_space.profile.metadata.get("memory_model", "32bit") == "32bit":
            fmt = "<I"
        else:
            fmt = "<Q"

        needles = []

        for sym in phys_addr_space.profile.get_all_symbol_names("kernel"):
            if sym.find("_sched_class") != -1:
                addr = phys_addr_space.profile.get_symbol(sym)
                needles.append(struct.pack(fmt, addr))

        if len(needles) == 0:
            debug.error("Unable to scan for processes. Please file a bug report.")

        back_offset = phys_addr_space.profile.get_obj_offset("task_struct", "sched_class")

        scanner = poolscan.MultiPoolScanner(needles)

        for _, offset in scanner.scan(phys_addr_space):
            ptask = obj.Object("task_struct", offset=offset - back_offset, vm=phys_addr_space)

            if not ptask.exit_state.v() in [0, 16, 32, 16 | 32]:
                continue

            if not (0 < ptask.pid < 66000):
                continue

            yield ptask
Esempio n. 30
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        # a list of root directory entries
        if self._config.DUMP_DIR and self._config.SB:

            if not os.path.isdir(self._config.DUMP_DIR):
                debug.error(self._config.DUMP_DIR + " is not a directory")

            # this path never 'yield's, just writes the filesystem to disk
            tmpfs_sbs = self.get_tmpfs_sbs()
            sb_idx = self._config.SB - 1

            if sb_idx >= len(tmpfs_sbs):
                debug.error("Invalid superblock number given. Please use the -L option to determine valid numbers.")
        
            root_dentry = tmpfs_sbs[sb_idx][0].s_root
            self.walk_sb(root_dentry)

        elif self._config.LIST_SBS:

            # vfsmnt.mnt_sb.s_root
            tmpfs_sbs = self.get_tmpfs_sbs()

            for (i, (_sb, path)) in enumerate(tmpfs_sbs):
                yield (i + 1, path)
        else:
            debug.error("No sb number/output directory combination given and list superblocks not given")
Esempio n. 31
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        func = self.determine_func()

        for task in func():
            yield task
Esempio n. 32
0
    def calculate(self):
        global PAGE_SIZE
        self.read_logs()
        linux_common.set_plugin_members(self)
        tasks = linux_pslist.linux_pslist.calculate(self)
        phys_addr_space = utils.load_as(self._config, astype = 'physical')

        for task in tasks:
            if task.mm:
                for vma in task.get_proc_maps():
                  (fname, major, minor, ino, pgoff) = vma.info(task)
                  t_start, t_end = vma.vm_start, vma.vm_end
                  cur_start, cur_end = None, None
                  p_res, p_all = 0, 0
                  file_offset_start, file_offset_end = 0x0, 0x0
                  proc_as = task.get_process_address_space()

                  # ##########################################################
                  # Ooutput vectors and running parameters
                  vma_one_hot = ""
                  vma_trans_offsets = []
                  vma_trans_range = []
                  vma_to_file = []
                  matched_files = matched_set()

                  # ##########################################################
                  # We process the ranges on page-size
                  while t_start < t_end:
                    p_all += 1
                    temp = proc_as.translate(t_start)
                    if temp != None:
                      p_res += 1
                      temp_file = proc_as.base.translate(temp)
                      vma_trans_offsets.append((t_start,temp,temp_file))
                      vma_to_file.append(temp_file)
                      vma_one_hot += "1"
                      
                      result = self.bin_search(self.comp_list,temp_file)
                      if result:
                        matched_files.insert(result)

                      # First Start
                      if cur_start == None:
                        cur_start = temp
                        cur_end = temp
                      else:
                        cur_end = temp
                    else:
                      vma_one_hot += "0"
                      if cur_start != None:
                        vma_trans_range.append((cur_start,cur_end))
                        cur_start, cur_end = None, None
                    t_start += PAGE_SIZE

                  if cur_start != None:
                    vma_trans_range.append((cur_start,cur_end))
                  
                  vma_file = {}
                  matched_files.do_sort()
                  vma_file["FOffsets"] = str(matched_files)
                  vma_file["PAllocs"]  = str(p_res)+"/"+str(p_all)
                  yield task, vma, vma_file
Esempio n. 33
0
    def calculate(self):
        """ 
        This works by walking the system call table 
        and verifies that each is a symbol in the kernel
        """
        linux_common.set_plugin_members(self)

        if not has_distorm:
            debug.warning(
                "distorm not installed. The best method to calculate the system call table size will not be used."
            )

        if self._config.SYSCALL_INDEXES:
            if not os.path.exists(self._config.SYSCALL_INDEXES):
                debug.error("Given syscall indexes file does not exist!")

            index_names = {}

            for line in open(self._config.SYSCALL_INDEXES, "r").readlines():
                ents = line.split()
                if len(ents) == 3 and ents[0] == "#define":
                    name = ents[1].replace("__NR_", "")

                    # "(__NR_timer_create+1)"
                    index = ents[2]
                    if index[0] == "(":
                        index = self._find_index(index_names, index)
                    else:
                        index = int(index)

                    index_names[index] = name
        else:
            index_names = None

        hidden_mods = list(
            linux_hidden_modules.linux_hidden_modules(
                self._config).calculate())
        visible_mods = linux_lsmod.linux_lsmod(self._config).calculate()

        table_name = self.addr_space.profile.metadata.get(
            'memory_model', '32bit')
        sym_addrs = self.profile.get_all_addresses()
        sys_call_info = self._get_table_info("sys_call_table")
        addrs = [(table_name, sys_call_info)]

        # 64 bit systems with 32 bit emulation
        ia32 = self.addr_space.profile.get_symbol("ia32_sys_call_table")
        if ia32:
            ia32_info = self._get_table_info("ia32_sys_call_table")
            addrs.append(("32bit", ia32_info))

        for (table_name, (tableaddr, tblsz)) in addrs:
            table = obj.Object(theType='Array',
                               offset=tableaddr,
                               vm=self.addr_space,
                               targetType='unsigned long',
                               count=tblsz)

            for (i, call_addr) in enumerate(table):
                if not call_addr:
                    continue

                if index_names:
                    idx_name = self._index_name(index_names, i)
                else:
                    idx_name = ""

                call_addr = int(call_addr)

                if not call_addr in sym_addrs:
                    hooked = 1

                    sym_name = self._compute_hook_sym_name(
                        visible_mods, hidden_mods, call_addr)
                else:
                    hooked = 0
                    sym_name = self.profile.get_symbol_by_address(
                        "kernel", call_addr)

                yield (tableaddr, table_name, i, idx_name, call_addr, sym_name,
                       hooked)
Esempio n. 34
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        tasks = linux_pslist.linux_pslist(self._config).calculate()

        for task in tasks:
            if self.init_for_task(task):

                if self.profile.metadata.get('memory_model') == '64bit':
                    self.profile.vtypes.update(ZshProfile64().zshprofile)

                else:
                    # default/fallback profile
                    self.profile.vtypes.update(ZshProfile32().zshprofile)

                self.profile.compile()

                chunks_dict = dict()
                chunk_data_pointers = list()
                chunk_size = self.get_aligned_size(
                    self.profile.get_obj_size('histent'))
                data_offset = self.profile.get_obj_offset("malloc_chunk", "fd")

                for chunk in self.get_all_allocated_chunks():
                    chunks_dict[chunk.v() + data_offset] = chunk
                    chunk_data_pointers.append(chunk.v() + data_offset)

                commands_dict = dict()

                valid_histentry = None

                # we first try to find a chunk that most probably contains a
                # histent struct
                for chunk in self.get_all_allocated_chunks():

                    if not chunk.chunksize() == chunk_size:
                        continue

                    histent = obj.Object('histent',
                                         offset=chunk.v() + data_offset,
                                         vm=self.process_as)

                    # we test if the current histent struct seems to be valid
                    # first test: do we know the chunks where relevant
                    # pointers point to
                    pointers = [
                        histent.node.nam.v(),
                        histent.down.v(),
                        histent.up.v()
                    ]
                    if not len(set(pointers) & set(chunk_data_pointers)) \
                            == len(pointers):
                        continue

                    # second test: points the previous/next histent entry to
                    # this histent entry?
                    if not histent.up.down == histent or not histent.down.up \
                            == histent:
                        continue

                    # we hopefully found one
                    valid_histentry = histent
                    break

                if valid_histentry:
                    debug.debug(
                        "We probably found a valid histent chunk and now "
                        "start walking.")

                    # entries are linked circular so walking in one direction
                    # should be sufficient
                    for histent in heap_analysis.iterate_through_linked_list(
                            valid_histentry, lambda x: x.down):

                        command = ''

                        try:
                            command = chunks_dict[histent.node.nam.v()]
                            command = command.to_string()
                            command = command[:command.index("\x00")]

                        except KeyError:
                            debug.warning(
                                "Unexpected error: chunk for given "
                                "command-reference does not seem to exist.")

                        except ValueError:
                            pass

                        if histent.stim == histent.ftim == 0 and command == '':
                            histent_vma = heap_analysis.get_vma_for_offset(
                                self.vmas, histent.v())

                            if histent_vma not in self.heap_vmas:
                                # we most probably found the "curline" histent
                                # struct located in zsh's .bss section. as it
                                # doesn't contain an actual executed command,
                                # we are skipping it
                                continue

                        command_number = histent.histnum
                        start = obj.Object('UnixTimeStamp',
                                           offset=histent.stim.obj_offset,
                                           vm=self.process_as)
                        end = obj.Object('UnixTimeStamp',
                                         offset=histent.stim.obj_offset,
                                         vm=self.process_as)

                        commands_dict[command_number] = [
                            start, end, repr(command)
                        ]

                for key, value in sorted(commands_dict.items()):
                    yield (task.pid, key, value[0], value[1], value[2])
Esempio n. 35
0
 def __init__(self, config, *args, **kwargs):
     linux_pslist.linux_pslist.__init__(self, config, *args, **kwargs)
     linux_common.set_plugin_members(self)
     self.thread_offset = self.profile.vtypes['task_struct'][1][
         'thread_group'][0]
Esempio n. 36
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        for mod in self.walk_modules_address_space(self.addr_space):
            yield mod
Esempio n. 37
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        mntptr = obj.Object(
            "Pointer",
            offset=self.addr_space.profile.get_symbol("mount_hashtable"),
            vm=self.addr_space)
        mnt_list = obj.Object(theType="Array",
                              offset=mntptr,
                              vm=self.addr_space,
                              targetType="list_head",
                              count=8200)

        if self.profile.has_type("mount"):
            mnttype = "mount"
        else:
            mnttype = "vfsmount"

        ns = None
        fs_types = self._get_filesystem_types()

        hash_mnts = {}
        seen_outer = {}
        for (idx, outerlist) in enumerate(mnt_list):
            if outerlist == None or outerlist.next == None:
                continue

            if outerlist.next.v() in seen_outer:
                continue

            seen_outer[outerlist.next.v()] = 1

            if outerlist == outerlist.next or not outerlist.m(
                    "next").is_valid():
                continue

            seen = {}
            mseen = {}
            for mnt in outerlist.list_of_type(mnttype, "mnt_hash"):
                if mnt.v() in seen:
                    break

                seen[mnt.v()] = 1

                if len(seen.keys()) > 1024:
                    break

                if mnt.is_valid():
                    mkey = mnt.v()
                    if not mkey in mseen:
                        hash_mnts[mnt] = 1
                        mseen[mkey] = 1
                else:
                    break

                if mnt.mnt_parent.is_valid():
                    mkey = mnt.mnt_parent.v()
                    if not mkey in mseen:
                        hash_mnts[mnt.mnt_parent] = 1
                        mseen[mkey] = 1

                if mnt.mnt_parent.mnt_parent.is_valid():
                    mkey = mnt.mnt_parent.mnt_parent.v()
                    if not mkey in mseen:
                        hash_mnts[mnt.mnt_parent.mnt_parent] = 1
                        mseen[mkey] = 1

        child_mnts = {}
        for mnt in hash_mnts:
            cseen = {}
            for child_mnt in mnt.mnt_child.list_of_type(mnttype, "mnt_child"):

                if not child_mnt.is_valid():
                    break

                child_mnts[child_mnt] = 1

                if child_mnt.v() in cseen:
                    break

                if len(child_mnts.keys()) > 1024:
                    break

                cseen[child_mnt.v()] = 1

                if child_mnt.mnt_parent.is_valid():
                    child_mnts[child_mnt.mnt_parent] = 1

                if child_mnt.mnt_parent.mnt_parent.is_valid():
                    child_mnts[child_mnt.mnt_parent.mnt_parent] = 1

        tmp_mnts = list(set(hash_mnts.keys() + child_mnts.keys()))
        all_mnts = []

        for t in tmp_mnts:
            tt = t.mnt_devname.dereference_as(
                "String", length=linux_common.MAX_STRING_LENGTH)
            if tt:
                if len(str(tt)) > 2 or (len(str(tt)) > 1
                                        and str(tt)[0] == '/'):
                    all_mnts.append(t)

        list_mnts = {}
        seen_m = {}
        for mnt in all_mnts:
            if mnt.v() in seen_m:
                continue
            else:
                seen_m[mnt.v()] = 1

            for (idx, child_mnt) in enumerate(
                    mnt.mnt_list.list_of_type(mnttype, "mnt_list")):
                if idx > 20:
                    break

                if child_mnt.is_valid():
                    list_mnts[child_mnt] = 1

                if child_mnt.mnt_parent.is_valid():
                    list_mnts[child_mnt.mnt_parent] = 1

                if child_mnt.mnt_parent.mnt_parent.is_valid():
                    list_mnts[child_mnt.mnt_parent.mnt_parent] = 1

        all_mnts = list(set(all_mnts + list_mnts.keys()))

        seen = {}
        for (idx, mnt) in enumerate(all_mnts):
            if mnt.mnt_sb.v() not in seen:
                ret = self._parse_mnt(mnt, ns, fs_types)

                mark = False

                if ret:
                    (mnt_sb, dev_name, path, fstype, rr, mnt_string) = ret

                    if not (dev_name == "devtmpfs" and path == "/"):
                        yield (mnt_sb, dev_name, path, fstype, rr, mnt_string)
                        mark = True

                if mark:
                    seen[mnt.mnt_sb.v()] = 1
Esempio n. 38
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        tasks = linux_pslist.linux_pslist(self._config).calculate()

        for task in tasks:
            if self.init_for_task(task):

                chunks_dict = dict()

                data_offset = self.profile.get_obj_offset("malloc_chunk", "fd")

                for chunk in self.get_all_allocated_chunks():
                    chunks_dict[chunk.v() + data_offset] = chunk

                if self.profile.metadata.get('memory_model') == '64bit':
                    string_offset = 26
                    relevant_chunk_size = 192
                    pointer_offsets = [16, 24, 32, 64]

                else:
                    string_offset = 18
                    relevant_chunk_size = 96
                    pointer_offsets = [12, 16, 20, 36]

                entry_number = 1

                for chunk in chunks_dict.values():

                    try:
                        # chunks containing refs to password entries typically
                        # have a size of 96 in the tested 32 bit environment
                        if not chunk.chunksize() == relevant_chunk_size:
                            continue

                        p_entry_data = chunk.to_string()

                        field_strings = []

                        # the pointers to title, username and so on are at
                        # these offsets
                        for i in pointer_offsets:
                            if self.profile.metadata.get(
                                    'memory_model') == '32bit':
                                pointer = struct.unpack(
                                    'I', p_entry_data[i:i + 4])[0]
                            else:
                                pointer = struct.unpack(
                                    'Q', p_entry_data[i:i + 8])[0]

                            # if there is no chunk for the given pointer, we
                            # most probably have a wrong chunk. this will
                            # throw a KeyError exception and we proceed with
                            # the next chunk
                            curr_chunk_data = chunks_dict[pointer].to_string()

                            string_size = struct.unpack(
                                'I', curr_chunk_data[8:12])[0]

                            string_size *= 2

                            curr_string = curr_chunk_data[
                                string_offset:string_offset + string_size]

                            curr_string = curr_string.decode('utf-16-le')

                            field_strings.append(repr(curr_string))

                        yield (task.pid, entry_number, field_strings[0],
                               field_strings[1], field_strings[2],
                               field_strings[3])

                        entry_number += 1

                    except (KeyError, UnicodeDecodeError):
                        # a password entry struct not containing a pointer to
                        # a chunk => out of scope
                        pass
Esempio n. 39
0
    def get_syscalls(self, index_lines=None, get_hidden=False):
        linux_common.set_plugin_members(self)

        if get_hidden:
            hidden_mods = list(
                linux_hidden_modules.linux_hidden_modules(
                    self._config).calculate())
        else:
            hidden_mods = []

        visible_mods = linux_lsmod.linux_lsmod(self._config).calculate()

        if not index_lines:
            index_lines = self._find_and_parse_index_file()

        if index_lines:
            index_names = {}
            for line in index_lines.split("\n"):
                ents = line.split()

                if len(ents) == 3 and ents[0] == "#define":
                    name = ents[1].replace("__NR_", "")

                    # "(__NR_timer_create+1)"
                    index = ents[2]
                    if index[0] == "(":
                        index = self._find_index(index_names, index)
                    else:
                        index = int(index)

                    index_names[index] = name
        else:
            index_names = None

        table_name = self.addr_space.profile.metadata.get(
            'memory_model', '32bit')
        sym_addrs = self.profile.get_all_addresses()
        sys_call_info = self._get_table_info("sys_call_table")
        addrs = [(table_name, sys_call_info)]

        # 64 bit systems with 32 bit emulation
        ia32 = self.addr_space.profile.get_symbol("ia32_sys_call_table")
        if ia32:
            ia32_info = self._get_table_info("ia32_sys_call_table")
            addrs.append(("32bit", ia32_info))

        for (table_name, (tableaddr, tblsz)) in addrs:
            table = obj.Object(theType='Array',
                               offset=tableaddr,
                               vm=self.addr_space,
                               targetType='unsigned long',
                               count=tblsz)

            for (i, call_addr) in enumerate(table):
                if not call_addr:
                    continue

                if index_names:
                    idx_name = self._index_name(index_names, i)
                else:
                    idx_name = ""

                call_addr = int(call_addr)

                if not call_addr in sym_addrs:
                    hooked = 1

                    sym_name = self._compute_hook_sym_name(
                        visible_mods, hidden_mods, call_addr)
                else:
                    hooked = 0
                    sym_name = self.profile.get_symbol_by_address(
                        "kernel", call_addr)

                yield (tableaddr, table_name, i, idx_name, call_addr, sym_name,
                       hooked)
Esempio n. 40
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        tasks = linux_pslist.linux_pslist(self._config).calculate()

        for task in tasks:
            proc_as = task.get_process_address_space()

            # In cases when mm is an invalid pointer
            if not proc_as:
                continue

            if not self._config.HISTORY_LIST:
                # Do we scan everything or just /bin/bash instances?
                if not (self._config.SCAN_ALL or str(task.comm) == "bash"):
                    continue

                # Keep a bucket of history objects so we can order them
                history_entries = []

                # Brute force the history list of an address isn't provided
                ts_offset = proc_as.profile.get_obj_offset(
                    "_hist_entry", "timestamp")

                # Are we dealing with 32 or 64-bit pointers
                if proc_as.profile.metadata.get('memory_model',
                                                '32bit') == '32bit':
                    pack_format = "I"
                else:
                    pack_format = "Q"

                # Look for strings that begin with pound/hash on the process heap
                for ptr_hash in task.search_process_memory(["#"],
                                                           heap_only=True):

                    # Find pointers to this strings address, also on the heap
                    addr = struct.pack(pack_format, ptr_hash)

                    for ptr_string in task.search_process_memory(
                        [addr], heap_only=True):

                        # Check if we found a valid history entry object
                        hist = obj.Object("_hist_entry",
                                          offset=ptr_string - ts_offset,
                                          vm=proc_as)

                        if hist.is_valid():
                            history_entries.append(hist)
                            # We can terminate this inner loop now
                            break

                # Report everything we found in order
                for hist in sorted(history_entries,
                                   key=attrgetter('time_as_integer')):
                    yield task, hist
            else:
                the_history_addr = the_history_addr = self._config.HISTORY_LIST
                the_history = obj.Object("Pointer",
                                         vm=proc_as,
                                         offset=the_history_addr)
                max_ents = 2001
                the_history = obj.Object(theType='Array',
                                         offset=the_history,
                                         vm=proc_as,
                                         targetType='Pointer',
                                         count=max_ents)

                for ptr in the_history:
                    if not ptr:
                        if self._config.PRINTUNALLOC:
                            continue
                        else:
                            break

                    hist = ptr.dereference_as("_hist_entry")

                    if hist.is_valid():
                        yield task, hist
Esempio n. 41
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        for (_, _, file_path,
             _) in linux_find_file.linux_find_file(self._config).walk_sbs():
            yield file_path
Esempio n. 42
0
 def __init__(self, config, *args, **kwargs):
     linux_common.AbstractLinuxCommand.__init__(self, config, *args,
                                                **kwargs)
     linux_common.set_plugin_members(self)
Esempio n. 43
0
    def get_syscalls(self,
                     index_info=None,
                     get_hidden=False,
                     compute_name=True):
        linux_common.set_plugin_members(self)

        if get_hidden:
            hidden_mods = list(
                linux_hidden_modules.linux_hidden_modules(
                    self._config).calculate())
        else:
            hidden_mods = []

        if compute_name:
            visible_mods = linux_lsmod.linux_lsmod(self._config).calculate()
        else:
            visible_mods = []

        if index_info == None:
            index_info = self._find_and_parse_index_file()

        table_name = self.addr_space.profile.metadata.get(
            'memory_model', '32bit')
        sym_addrs = self.profile.get_all_addresses()
        sys_call_info = self._get_table_info("sys_call_table")
        addrs = [(table_name, sys_call_info)]

        # 64 bit systems with 32 bit emulation
        ia32 = self.addr_space.profile.get_symbol("ia32_sys_call_table")
        if ia32:
            ia32_info = self._get_table_info("ia32_sys_call_table")
            addrs.append(("32bit", ia32_info))

        for (table_name, (tableaddr, tblsz)) in addrs:
            table = obj.Object(
                theType='Array',
                offset=tableaddr,
                vm=self.addr_space,
                targetType='unsigned long',
                count=tblsz + 1,
            )

            for (i, call_addr) in enumerate(table):
                if not call_addr:
                    continue

                idx_name = self._index_name(table_name, index_info, i)

                call_addr = int(call_addr)

                if not call_addr in sym_addrs:
                    hooked = 1
                    sym_name = self._compute_hook_sym_name(
                        visible_mods, hidden_mods, call_addr)
                else:
                    hooked = 0
                    sym_name = self.profile.get_symbol_by_address(
                        "kernel", call_addr)

                yield (
                    tableaddr,
                    table_name,
                    i,
                    idx_name,
                    call_addr,
                    sym_name,
                    hooked,
                )
Esempio n. 44
0
    def calculate(self):
        if not has_yara:
            debug.error(
                "Please install Yara from https://plusvic.github.io/yara/")

        linux_common.set_plugin_members(self)

        ## the start of kernel memory taken from VolatilityLinuxIntelValidAS
        if (self.addr_space.profile.metadata.get('memory_model',
                                                 '32bit') == "32bit"):
            kernel_start = 0xC0000000
            pack_size = 4
            pack_fmt = "<I"
        else:
            kernel_start = 0xFFFF880000000000
            pack_size = 8
            pack_fmt = "<Q"

        checks = [
            self.check_family,
            self.check_proto,
            self.check_socket_back_pointer,
            self.check_pointers,
        ]

        destruct_offset = self.addr_space.profile.get_obj_offset(
            "sock", "sk_destruct")

        # sk_destruct pointer value of sock
        func_addr = self.addr_space.profile.get_symbol("inet_sock_destruct")

        vals = struct.pack(pack_fmt, func_addr)

        s = "{ " + " ".join(["%.02x" % v for v in vals]) + " }"

        rules = yara.compile(
            sources={'n': 'rule r1 {strings: $a = ' + s + ' condition: $a}'})

        scanner = malfind.DiscontigYaraScanner(rules=rules,
                                               address_space=self.addr_space)
        for _, address in scanner.scan(start_offset=kernel_start):
            base_address = address - destruct_offset

            i = obj.Object("inet_sock",
                           offset=base_address,
                           vm=self.addr_space)

            valid = True
            for check in checks:
                if check(i) == False:
                    valid = False
                    break

            if valid:
                state = i.state if i.protocol == "TCP" else ""
                family = (i.sk.__sk_common.skc_family
                          )  # pylint: disable-msg=W0212

                sport = i.src_port
                dport = i.dst_port
                saddr = i.src_addr
                daddr = i.dst_addr

                if (str(saddr) == "0.0.0.0" and str(daddr) == "0.0.0.0"
                        and sport == 6 and dport == 0):
                    continue

                yield (i, i.protocol, saddr, sport, daddr, dport, state)
Esempio n. 45
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        mntptr = obj.Object(
            "Pointer",
            offset=self.addr_space.profile.get_symbol("mount_hashtable"),
            vm=self.addr_space)
        mnt_list = obj.Object(theType="Array",
                              offset=mntptr,
                              vm=self.addr_space,
                              targetType="list_head",
                              count=8200)

        if self.profile.has_type("mount"):
            mnttype = "mount"
        else:
            mnttype = "vfsmount"

        ns = None
        fs_types = self._get_filesystem_types()

        hash_mnts = {}
        for (idx, outerlist) in enumerate(mnt_list):
            if outerlist == outerlist.next or not outerlist.m(
                    "next").is_valid():
                continue

            for mnt in outerlist.list_of_type(mnttype, "mnt_hash"):
                if mnt.is_valid():
                    hash_mnts[mnt] = 1
                else:
                    break

                if mnt.mnt_parent.is_valid():
                    hash_mnts[mnt.mnt_parent] = 1

                if mnt.mnt_parent.mnt_parent.is_valid():
                    hash_mnts[mnt.mnt_parent.mnt_parent] = 1

        child_mnts = {}
        for mnt in hash_mnts:
            for child_mnt in mnt.mnt_child.list_of_type(mnttype, "mnt_child"):
                if not child_mnt.is_valid():
                    break

                child_mnts[child_mnt] = 1

                if child_mnt.mnt_parent.is_valid():
                    child_mnts[child_mnt.mnt_parent] = 1

                if child_mnt.mnt_parent.mnt_parent.is_valid():
                    child_mnts[child_mnt.mnt_parent.mnt_parent] = 1

        all_mnts = list(set(hash_mnts.keys() + child_mnts.keys()))

        list_mnts = {}
        seen_m = {}
        for mnt in all_mnts:
            if mnt.v() in seen_m:
                continue
            else:
                seen_m[mnt.v()] = 1

            for (idx, child_mnt) in enumerate(
                    mnt.mnt_list.list_of_type(mnttype, "mnt_list")):
                if idx > 20:
                    break

                if child_mnt.is_valid():
                    list_mnts[child_mnt] = 1

                if child_mnt.mnt_parent.is_valid():
                    list_mnts[child_mnt.mnt_parent] = 1

                if child_mnt.mnt_parent.mnt_parent.is_valid():
                    list_mnts[child_mnt.mnt_parent.mnt_parent] = 1

        all_mnts = list(set(all_mnts + list_mnts.keys()))

        seen = {}
        for (idx, mnt) in enumerate(all_mnts):
            if mnt.mnt_sb.v() not in seen:
                ret = self._parse_mnt(mnt, ns, fs_types)

                mark = False

                if ret:
                    (mnt_sb, dev_name, path, fstype, rr, mnt_string) = ret

                    if not (dev_name == "devtmpfs" and path == "/"):
                        yield (mnt_sb, dev_name, path, fstype, rr, mnt_string)
                        mark = True

                if mark:
                    seen[mnt.mnt_sb.v()] = 1
Esempio n. 46
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        if not self._config.BASE:
            debug.error("No base address specified.")

        if not self._config.PATH:
            debug.error("No known-good path specified.")

        fd = open(self._config.PATH, "rb")
        known_good = fd.read()
        fd.close()

        bufferas = addrspace.BufferAddressSpace(self._config, data=known_good)
        elf_hdr = obj.Object("elf_hdr", offset=0, vm=bufferas)

        tasks = linux_pslist.linux_pslist.calculate(self)

        for task in tasks:
            proc_as = task.get_process_address_space()

            for vma in task.get_proc_maps():
                if self._config.BASE != vma.vm_start:
                    continue

                for sym in elf_hdr.symbols():
                    if sym.st_value == 0 or (sym.st_info & 0xF) != 2:
                        continue

                    symname = elf_hdr.symbol_name(sym)

                    sym_offset = sym.st_value

                    # in the same vma
                    if vma.vm_start < sym.st_value < vma.vm_end:
                        vm_start = vma.vm_start
                        sym_offset = sym_offset - vm_start
                        full_address = sym.st_value
                    else:
                        next_vma = vma.vm_next
                        if next_vma.vm_start < sym.st_value < next_vma.vm_end:
                            vm_start = next_vma.vm_start
                            sym_offset = sym.st_value - vm_start
                            full_address = sym.st_value
                        else:
                            full_address = vma.vm_start + sym.st_value

                    mem_buffer = proc_as.read(vm_start + sym_offset,
                                              sym.st_size)

                    if sym.st_value > vma.vm_start:
                        disk_off = sym.st_value - vm_start
                    else:
                        disk_off = sym.st_value

                    disk_buffer = bufferas.read(disk_off, sym.st_size)

                    # bad
                    if mem_buffer != None and disk_buffer != mem_buffer:
                        yield task, symname, full_address
                    elif mem_buffer == None:
                        print(f"Function {symname} paged out in memory")
Esempio n. 47
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        ## the start of kernel memory taken from VolatilityLinuxIntelValidAS
        if self.addr_space.profile.metadata.get('memory_model',
                                                '32bit') == "32bit":
            kernel_start = 0xc0000000
            pack_size = 4
            pack_fmt = "<I"
        else:
            kernel_start = 0xffffffff80000000
            pack_size = 8
            pack_fmt = "<Q"

        checks = [
            self.check_family, self.check_proto,
            self.check_socket_back_pointer, self.check_pointers
        ]

        destruct_offset = self.addr_space.profile.get_obj_offset(
            "sock", "sk_destruct")

        # sk_destruct pointer value of sock
        func_addr = self.addr_space.profile.get_symbol("inet_sock_destruct")

        vals = []

        # convert address into a yara hex rule
        for bit in range(pack_size):
            idx = (pack_size - bit - 1) * 8
            mask = 0xff << idx
            val = ((func_addr & mask) >> idx) & 0xff

            vals.insert(0, val)

        s = "{" + " ".join(["%.02x" % v for v in vals]) + " }"

        rules = yara.compile(
            sources={'n': 'rule r1 {strings: $a = ' + s + ' condition: $a}'})

        scanner = malfind.DiscontigYaraScanner(rules=rules,
                                               address_space=self.addr_space)
        for _, address in scanner.scan(start_offset=kernel_start):
            base_address = address - destruct_offset

            i = obj.Object("inet_sock",
                           offset=base_address,
                           vm=self.addr_space)

            valid = True
            for check in checks:
                if check(i) == False:
                    valid = False
                    break

            if valid:
                state = i.state if i.protocol == "TCP" else ""
                family = i.sk.__sk_common.skc_family  #pylint: disable-msg=W0212

                sport = i.src_port
                dport = i.dst_port
                saddr = i.src_addr
                daddr = i.dst_addr

                yield (i, i.protocol, saddr, sport, daddr, dport, state)
Esempio n. 48
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        # Get instructions executed when an inturrupt exception occurs
        swi = obj.Object("unsigned int",
                         offset=self.SWI_BASE,
                         vm=self.addr_space)

        # Get offset of address to vector_swi
        offset = (swi & 0x0FFF) + 8

        # Verify that instruction hasn't been modified (should be: ldr pc, [pc, #???] (e59ff???))
        if (swi & 0xFFFFF000) == 0xE59FF000:
            yield (
                "SWI Offset Instruction",
                "PASS",
                "Offset: {0}".format(offset),
            )
        else:
            yield ("SWI Offset Instruction", "FAIL", "{0:X}".format(swi))
            return

        # Get vector_swi_addr from table
        vector_swi_addr = obj.Object("unsigned int",
                                     offset=self.SWI_BASE + (offset),
                                     vm=self.addr_space)

        # Check to see if vector_swi handler has been hooked
        if vector_swi_addr == self.addr_space.profile.get_symbol("vector_swi"):
            yield (
                "vector_swi address",
                "PASS",
                "0x{0:X}".format(vector_swi_addr),
            )
        else:
            yield (
                "vector_swi address",
                "FAIL",
                "0x{0:X}".format(vector_swi_addr),
            )
            return

        # Check for hooking of sys_call table pointer
        sc_opcode = None
        max_opcodes_to_check = 1024
        while max_opcodes_to_check:
            opcode = obj.Object("unsigned int",
                                offset=vector_swi_addr,
                                vm=self.addr_space)
            if (opcode & 0xFFFFFF00) == 0xE28F8000:
                sc_opcode = opcode
                break
            vector_swi_addr += 4
            max_opcodes_to_check -= 1

        if sc_opcode:
            yield (
                "vector_swi code modification",
                "PASS",
                "{0:X}".format(sc_opcode),
            )
        else:
            yield (
                "vector_swi code modification",
                "FAIL",
                "Opcode E28F80?? not found",
            )
            return
Esempio n. 49
0
    def calculate(self):
        linux_common.set_plugin_members(self)

        tasks = linux_pslist.linux_pslist(self._config).calculate()

        # Are we dealing with 32 or 64-bit pointers
        if self.addr_space.profile.metadata.get('memory_model',
                                                '32bit') == '32bit':
            pack_format = "<I"
            addr_sz = 4
        else:
            pack_format = "<Q"
            addr_sz = 8

        for task in tasks:
            proc_as = task.get_process_address_space()

            # In cases when mm is an invalid pointer
            if not proc_as:
                continue

            procvars = []
            for vma in task.get_proc_maps():
                if not (vma.vm_file and str(vma.vm_flags) == "rw-"
                        and linux_common.get_path(
                            task, vma.vm_file).find("bash") != -1):
                    continue

                env_start = 0
                for off in range(vma.vm_start, vma.vm_end):
                    # check the first index
                    addrstr = proc_as.read(off, addr_sz)
                    if not addrstr or len(addrstr) != addr_sz:
                        continue
                    addr = struct.unpack(pack_format, addrstr)[0]
                    # check first idx...
                    if addr:
                        firstaddrstr = proc_as.read(addr, addr_sz)
                        if not firstaddrstr or len(firstaddrstr) != addr_sz:
                            continue
                        firstaddr = struct.unpack(pack_format, firstaddrstr)[0]
                        buf = proc_as.read(firstaddr, 64)
                        if not buf:
                            continue
                        eqidx = buf.find("=")
                        if eqidx > 0:
                            nullidx = buf.find("\x00")
                            # single char name, =
                            if nullidx >= eqidx:
                                env_start = addr

                if env_start == 0:
                    continue

                envars = obj.Object(theType="Array",
                                    targetType="Pointer",
                                    vm=proc_as,
                                    offset=env_start,
                                    count=256)
                for var in envars:
                    if var:
                        varstr = proc_as.read(var, 1600)
                        eqidx = varstr.find("=")
                        idx = varstr.find("\x00")

                        if idx == -1 or eqidx == -1 or idx < eqidx:
                            break

                        varstr = varstr[:idx]

                        procvars.append(varstr)

                yield task, " ".join(procvars)

                break
Esempio n. 50
0
    def calculate(self):
        """ 
        This works by walking the IDT table for the entries that Linux uses
        and verifies that each is a symbol in the kernel
        """
        linux_common.set_plugin_members(self)

        if self.profile.metadata['arch'] not in ["x64", "x86"]:
            debug.error(
                "This plugin is only supported on Intel-based memory captures")

        tblsz = 256

        sym_addrs = self.profile.get_all_addresses()

        # hw handlers + system call
        check_idxs = list(range(0, 20)) + [128]

        if self.profile.metadata.get('memory_model', '32bit') == "32bit":
            idt_type = "desc_struct"
        else:
            if self.profile.has_type("gate_struct64"):
                idt_type = "gate_struct64"
            else:
                idt_type = "idt_desc"

        # this is written as a list b/c there are supposdly kernels with per-CPU IDTs
        # but I haven't found one yet...
        addrs = [self.addr_space.profile.get_symbol("idt_table")]

        for tableaddr in addrs:
            table = obj.Object(theType='Array',
                               offset=tableaddr,
                               vm=self.addr_space,
                               targetType=idt_type,
                               count=tblsz)

            for i in check_idxs:
                ent = table[i]

                if not ent:
                    continue

                if hasattr(ent, "Address"):
                    idt_addr = ent.Address
                else:
                    low = ent.offset_low
                    middle = ent.offset_middle
                    high = ent.offset_high

                    idt_addr = (high << 32) | (middle << 16) | low

                if idt_addr != 0:
                    if not idt_addr in sym_addrs:
                        hooked = 1
                        sym_name = "HOOKED"
                    else:
                        hooked = 0
                        sym_name = self.profile.get_symbol_by_address(
                            "kernel", idt_addr)

                    yield (i, ent, idt_addr, sym_name, hooked)
Esempio n. 51
0
    def calculate(self):
        def read_rel(offset, len_):
            return obj.Object(
                "list_head",
                offset=device_private__device__ptr__addr - 152 + offset,
                vm=self.addr_space).obj_vm.read(
                    addr=device_private__device__ptr__addr - 152 + offset,
                    length=len_)

        def read_abs(offset, len_):
            return obj.Object("list_head", offset=offset,
                              vm=self.addr_space).obj_vm.read(addr=offset,
                                                              length=len_)

        linux_common.set_plugin_members(self)

        io_ptr = self.addr_space.profile.get_symbol("iomem_resource")
        io_res = obj.Object("resource", offset=io_ptr, vm=self.addr_space)

        io_pci_ptr = self.addr_space.profile.get_symbol("pci_bus_type")
        io_pci_res = obj.Object("bus_type",
                                offset=io_pci_ptr,
                                vm=self.addr_space)
        import struct

        # readin klist_devices->k_list->next pointer from SUBSYS_PRIVATE struct
        #---------------------------------------|------------------------------------------------------------------|----------------------------------------------|------|---|
        subsys__klist_devices__k_list__next__addr = struct.unpack(
            'L',
            obj.Object("bus_type",
                       offset=io_pci_res.p + 168 + 8,
                       vm=self.addr_space).obj_vm.read(addr=io_pci_res.p +
                                                       168 + 8,
                                                       length=8))[0]
        print "subsys__klist_devices__k_list__next__addr relies at--\t" + str(
            subsys__klist_devices__k_list__next__addr) + ";\thex =\t" + str(
                hex(subsys__klist_devices__k_list__next__addr))

        # so now we can get list_head *next pointer
        # get pointers
        device_private__n_node__next__addr = struct.unpack(
            'L',
            obj.Object("list_head",
                       offset=subsys__klist_devices__k_list__next__addr,
                       vm=self.addr_space).obj_vm.read(
                           addr=subsys__klist_devices__k_list__next__addr,
                           length=8))[0]
        print "device_private__n_node__next__addr list_head next relies at--\t" + str(
            device_private__n_node__next__addr) + ";\thex =\t" + str(
                hex(device_private__n_node__next__addr))
        device_private__n_node__prev__addr = struct.unpack(
            'L',
            obj.Object("list_head",
                       offset=subsys__klist_devices__k_list__next__addr + 8,
                       vm=self.addr_space).obj_vm.read(
                           addr=subsys__klist_devices__k_list__next__addr + 8,
                           length=8))[0]
        print "device_private__n_node__prev__addr prev relies at--\t" + str(
            device_private__n_node__prev__addr) + ";\thex =\t" + str(
                hex(device_private__n_node__prev__addr))
        start = device_private__n_node__next__addr
        resource_data = []
        #========== start cycle of lookin at the devices classes ====look through the list==
        for i in range(150):
            print "\nRound {0}".format(i)

            # so now we can get list_head *next pointer

            # so now we can get struct device *device of a device_private structure

            device_private__device__ptr__addr = struct.unpack(
                'L',
                obj.Object("list_head",
                           offset=device_private__n_node__next__addr + 40,
                           vm=self.addr_space).obj_vm.read(
                               addr=device_private__n_node__next__addr + 40,
                               length=8))[0]
            print "device_private__device__ptr__addr relies at--\t" + str(
                device_private__device__ptr__addr) + ";\thex =\t" + str(
                    hex(device_private__device__ptr__addr))

            #so now we can extract class
            pci_dev__class__ptr = struct.unpack(
                'I',
                obj.Object(
                    "list_head",
                    offset=device_private__device__ptr__addr - 152 + 68,
                    vm=self.addr_space).obj_vm.read(
                        addr=device_private__device__ptr__addr - 152 + 68,
                        length=4))[0]
            print "class device\t" + str(
                hex(pci_dev__class__ptr)
            )  #struct.unpack('I', obj.Object("list_head", offset = device_private__device__ptr__addr - 152 + 68, vm = self.addr_space).obj_vm.read(addr = device_private__device__ptr__addr - 152 + 68, length = 4)[0];

            for i in range(17):
                resource_data.append((struct.unpack('L', read_rel(888 + i*56, 8))[0],\
                                      struct.unpack('L', read_rel(888 + i*56 + 8, 8))[0],\
                                      struct.unpack('L', read_rel(888 + i*56 + 16, 8))[0] ))
                print resource_data[i]

            print "pointer to name " + str(
                struct.unpack('L', read_rel(152 + 80, 8))[0])
            # print obj.Object("list_head", offset = struct.unpack('L', read_rel(152+80, 8))[0], vm = self.addr_space).obj_vm.read(addr = struct.unpack('L', read_rel(152+80, 8))[0], length = 8)

            # resource_data.append(obj.Object("list_head", offset = device_private__n_node__next__addr - 152, vm = self.addr_space).obj_vm.read(addr = device_private__n_node__next__addr - 152, length = 2272))
            # print "device resources --\t" + str(resource_data) + ";\thex =\t" + str(hex(resource_data)) + "\n\n"

            # io_res
            device_private__n_node__next__addr = struct.unpack(
                'L',
                obj.Object("list_head",
                           offset=device_private__n_node__next__addr,
                           vm=self.addr_space).obj_vm.read(
                               addr=device_private__n_node__next__addr,
                               length=8))[0]
            print "next device_private struct pointer --\t" + str(
                device_private__n_node__next__addr) + ";\thex =\t" + str(
                    hex(device_private__n_node__next__addr)) + "\n\n"
            if start == device_private__n_node__next__addr:
                break

        # import ipdb
        # ipdb.set_trace()

        # io_pci_dat

        # print "pci_bus_type output"
        #
        # print len(s)
        # dir(io_res)
        # dir(io_res.child)

        for r in self.yield_resource(io_res.child):
            yield r
Esempio n. 52
0
    def calculate(self):
        # load the address space
        linux_common.set_plugin_members(self)
        # update the vtypes
        self._add_vtyptes()

        name_buckets = self.addr_space.profile.get_symbol("_name_buckets")

        for i in range(64):
            # compute the location in the array of our list_head
            nb_offset = i * self.addr_space.profile.get_obj_size(
                "list_head") + name_buckets

            # instantiate the list_head
            listHead = obj.Object("list_head",
                                  offset=nb_offset,
                                  vm=self.addr_space)

            cur = obj.Object("list_head",
                             offset=listHead.next,
                             vm=self.addr_space)

            # if list_head.next == list_head, the list is empty
            while cur != listHead:
                # get the hash_cell struct that this list_head is embedded in
                hc = obj.Object("hash_cell",
                                offset=cur.obj_offset,
                                vm=self.addr_space)

                hc_name = str(
                    obj.Object("String",
                               offset=hc.name.v(),
                               vm=self.addr_space,
                               length=32))

                type_name = str(
                    obj.Object("String",
                               offset=hc.md.map.targets.type.name.v(),
                               vm=self.addr_space,
                               length=16))

                # we use these fields in every case to get the start and size
                # of the mapping
                start = hc.md.map.targets.begin
                ssize = hc.md.map.targets.len

                if type_name == "crypt":
                    c = obj.Object("crypt_config",
                                   offset=hc.md.map.targets.private.v(),
                                   vm=self.addr_space)

                    device = self._dev_name(c.dev)

                    # turn the key into ASCII hex
                    key = binascii.hexlify(
                        bytearray(
                            self.addr_space.read(addr=c.key.obj_offset,
                                                 length=c.key_size)))

                    cipher_string = str(
                        obj.Object("String",
                                   offset=c.cipher_string.v(),
                                   vm=self.addr_space,
                                   length=16))

                    # format is:
                    # start size target cipher_string key iv_offset device offset
                    # start is always 0, offset = c.start
                    yield "{}: {} {} crypt {} {} {} {} {}".format(
                        hc_name,
                        start,
                        ssize,
                        cipher_string,
                        key,
                        c.iv_offset,
                        device,
                        c.start,
                    )

                elif type_name == "linear":
                    l = obj.Object("linear_c",
                                   offset=hc.md.map.targets.private.v(),
                                   vm=self.addr_space)

                    device = self._dev_name(l.dev)

                    # format is:
                    # start size target device offset
                    yield "{}: {} {} {} {} {}".format(hc_name, start, ssize,
                                                      type_name, device,
                                                      l.start)

                # generic type
                else:
                    yield "{}: {} {} {}".format(hc_name, start, ssize,
                                                type_name)

                cur = obj.Object("list_head",
                                 offset=cur.next,
                                 vm=self.addr_space)
Esempio n. 53
0
    def calculate(self):
        linux_common.set_plugin_members(self)
        elfs = dict()
        ignore = frozenset(self._config.IGNORE)

        for task, elf, elf_start, elf_end, soname, needed in linux_elfs.linux_elfs.calculate(
                self):
            elfs[(task, soname)] = (elf, elf_start, elf_end, needed)

        for k, v in elfs.iteritems():
            task, soname = k
            elf, elf_start, elf_end, needed = v

            if elf._get_typename("hdr") == "elf32_hdr":
                elf_arch = 32
            else:
                elf_arch = 64

            needed_expanded = set([soname])
            if (task, None) in elfs:
                needed_expanded.add(None)
            # jmp slot can point to ELF itself if the fn hasn't been called yet (RTLD_LAZY)
            # can point to main binary (None above) if this is a plugin-style symbol
            while len(needed) > 0:
                dep = needed.pop(0)
                needed_expanded.add(dep)
                try:
                    needed += set(elfs[(task, dep)][3]) - needed_expanded
                except KeyError:
                    needed_expanded.remove(dep)

            for reloc in elf.relocations():
                rsym = elf.relocation_symbol(reloc)

                if rsym == None:
                    continue

                symbol_name = elf.symbol_name(rsym)
                if symbol_name == None:
                    symbol_name = "<N/A>"

                offset = reloc.r_offset

                if offset < elf_start:
                    offset = elf_start + offset

                if elf_arch == 32:
                    addr = obj.Object("unsigned int",
                                      offset=offset,
                                      vm=elf.obj_vm)
                else:
                    addr = obj.Object("unsigned long long",
                                      offset=offset,
                                      vm=elf.obj_vm)

                match = False
                for dep in needed_expanded:
                    _, dep_start, dep_end, _ = elfs[(task, dep)]
                    if addr >= dep_start and addr < dep_end:
                        match = dep

                hookdesc = ''
                vma = None
                for i in task.get_proc_maps():
                    if addr >= i.vm_start and addr < i.vm_end:
                        vma = i
                        break
                if vma:
                    if vma.vm_file:
                        hookdesc = linux_common.get_path(task, vma.vm_file)

                        if hookdesc in ignore:
                            continue
                    else:
                        hookdesc = '[{0:x}:{1:x},{2}]'.format(
                            vma.vm_start, vma.vm_end, vma.vm_flags)

                if hookdesc == "":
                    hookdesc = 'invalid memory'

                if match != False:
                    if self._config.ALL and match == soname:
                        hookdesc = '[RTLD_LAZY]'
                    hooked = False

                else:
                    hooked = True

                yield task, soname, elf, elf_start, elf_end, addr, symbol_name, hookdesc, hooked