Beispiel #1
0
    def _generator(self, procs):

        type_map = self.get_type_map(context=self.context,
                                     layer_name=self.config["primary"],
                                     symbol_table=self.config["nt_symbols"])

        cookie = self.find_cookie(context=self.context,
                                  layer_name=self.config["primary"],
                                  symbol_table=self.config["nt_symbols"])

        for proc in procs:
            try:
                object_table = proc.ObjectTable
            except exceptions.InvalidAddressException:
                vollog.log(
                    constants.LOGLEVEL_VVV,
                    "Cannot access _EPROCESS.ObjectType at {0:#x}".format(
                        proc.vol.offset))
                continue

            process_name = utility.array_to_string(proc.ImageFileName)

            for entry in self.handles(object_table):
                try:
                    obj_type = entry.get_object_type(type_map, cookie)
                    if obj_type is None:
                        continue
                    if obj_type == "File":
                        item = entry.Body.cast("_FILE_OBJECT")
                        obj_name = item.file_name_with_device()
                    elif obj_type == "Process":
                        item = entry.Body.cast("_EPROCESS")
                        obj_name = "{} Pid {}".format(
                            utility.array_to_string(proc.ImageFileName),
                            item.UniqueProcessId)
                    elif obj_type == "Thread":
                        item = entry.Body.cast("_ETHREAD")
                        obj_name = "Tid {} Pid {}".format(
                            item.Cid.UniqueThread, item.Cid.UniqueProcess)
                    elif obj_type == "Key":
                        item = entry.Body.cast("_CM_KEY_BODY")
                        obj_name = item.get_full_key_name()
                    else:
                        try:
                            obj_name = entry.NameInfo.Name.String
                        except (ValueError,
                                exceptions.InvalidAddressException):
                            obj_name = ""

                except (exceptions.InvalidAddressException):
                    vollog.log(
                        constants.LOGLEVEL_VVV,
                        "Cannot access _OBJECT_HEADER at {0:#x}".format(
                            entry.vol.offset))
                    continue

                yield (0, (proc.UniqueProcessId, process_name,
                           format_hints.Hex(entry.Body.vol.offset),
                           format_hints.Hex(entry.HandleValue), obj_type,
                           format_hints.Hex(entry.GrantedAccess), obj_name))
Beispiel #2
0
    def _generator(self):
        for mount in self.list_mounts(self.context, self.config['primary'], self.config['darwin']):
            vfs = mount.mnt_vfsstat
            device_name = utility.array_to_string(vfs.f_mntonname)
            mount_point = utility.array_to_string(vfs.f_mntfromname)
            mount_type = utility.array_to_string(vfs.f_fstypename)

            yield 0, (device_name, mount_point, mount_type)
    def probe_address(self, ptr):
        sshenc = self.context.object(self.openssh_table_name + constants.BANG +
                                     "sshenc_61p2",
                                     offset=ptr,
                                     layer_name=self.proc_layer_name)
        name_valid = sshenc.name.is_readable()
        cipher_valid = sshenc.cipher.is_readable()

        if not (name_valid and cipher_valid):
            return None

        enc_name = sshenc.name.dereference()
        enc_name = utility.array_to_string(enc_name)
        enc_properties = lookup_enc(enc_name)
        if not enc_properties:
            return None

        expected_key_len = enc_properties[2]
        key_len_valid = expected_key_len == sshenc.key_len
        if not key_len_valid:
            return None

        cipher_name = sshenc.cipher.name.dereference()
        cipher_name = utility.array_to_string(cipher_name)
        if cipher_name != enc_name:
            return None

        vollog.debug("Found possible candidate at address 0x{:x}.".format(ptr))

        #At this point we know pretty certain this is the sshenc struct. Let's figure out which version...
        expected_block_size = enc_properties[1]
        block_size_valid = expected_block_size == sshenc.block_size

        if not block_size_valid:
            vollog.warning(
                "Detected structure misaslignment. Trying sshenc_61p1 structure.."
            )
            sshenc = self.context.object(self.openssh_table_name +
                                         constants.BANG + "sshenc_61p1",
                                         offset=ptr,
                                         layer_name=self.proc_layer_name)

        block_size_valid = expected_block_size == sshenc.block_size
        if not block_size_valid:
            vollog.error("Detected sshenc structure but can't seem to align!")
            # Bugger we can't seem to properly align the structure
            return None

        key_valid = sshenc.key.is_readable()
        iv_valid = sshenc.iv.is_readable()
        if key_valid and iv_valid:
            return sshenc

        vollog.error("Detected sshenc structure but invalid key/IV address!")
        return None
    def _generator(self, tasks):
        result = []
        is_32bit = not symbols.symbol_table_is_64bit(self.context,
                                                     self.config["vmlinux"])
        if is_32bit:
            openssh_json_file = "openssh32"
        else:
            openssh_json_file = "openssh64"

        openssh_table_name = intermed.IntermediateSymbolTable.create(
            self.context, self.config_path, 'linux', openssh_json_file)

        for task in tasks:
            if not task.mm:
                continue

            name = utility.array_to_string(task.comm)
            vollog.info("Scanning process #{} ({} {})".format(
                task.pid, name, ""))
            proc_layer_name = task.add_process_layer()
            extractor = SSHKeyExtractor(self.context, openssh_table_name,
                                        proc_layer_name, task,
                                        self._progress_callback)
            keys = extractor.extract()
            result.extend(keys)
        return result
Beispiel #5
0
        def yield_processes(pid):
            proc = self._processes[pid]
            row = (proc.pid, proc.parent.pid, utility.array_to_string(proc.comm))

            yield (self._levels[pid] - 1, row)
            for child_pid in self._children.get(pid, []):
                yield from yield_processes(child_pid)
Beispiel #6
0
    def _generator(self, tasks):
        for task in tasks:
            if not task.mm:
                continue

            name = utility.array_to_string(task.comm)

            for vma in task.mm.get_mmap_iter():
                flags = vma.get_protection()
                page_offset = vma.get_page_offset()
                major = 0
                minor = 0
                inode = 0

                if vma.vm_file != 0:
                    dentry = vma.vm_file.get_dentry()
                    if dentry != 0:
                        inode_object = dentry.d_inode
                        major = inode_object.i_sb.major
                        minor = inode_object.i_sb.minor
                        inode = inode_object.i_ino

                path = vma.get_name(self.context, task)

                yield (0, (task.pid, name, format_hints.Hex(vma.vm_start),
                           format_hints.Hex(vma.vm_end), flags,
                           format_hints.Hex(page_offset), major, minor, inode,
                           path))
Beispiel #7
0
    def list_kernel_events(cls,
                           context: interfaces.context.ContextInterface,
                           layer_name: str,
                           darwin_symbols: str,
                           filter_func: Callable[[int], bool] = lambda _: False) -> \
            Iterable[Tuple[interfaces.objects.ObjectInterface,
                           interfaces.objects.ObjectInterface,
                           interfaces.objects.ObjectInterface]]:
        """
        Returns the kernel event filters registered

        Return values:
            A tuple of 3 elements:
                1) The name of the process that registered the filter
                2) The process ID of the process that registered the filter
                3) The object of the associated kernel event filter
        """
        kernel = contexts.Module(context, darwin_symbols, layer_name, 0)

        list_tasks = pslist.PsList.get_list_tasks(
            pslist.PsList.pslist_methods[0])

        for task in list_tasks(context, layer_name, darwin_symbols,
                               filter_func):
            task_name = utility.array_to_string(task.p_comm)
            pid = task.p_pid

            for kn in cls._get_task_kevents(kernel, task):
                yield task_name, pid, kn
    def is_valid(self):
        try:
            cmd = self.get_command()
            ts = utility.array_to_string(self.timestamp.dereference())
        except exceptions.InvalidAddressException:
            return False

        if not cmd or len(cmd) == 0:
            return False

        if not ts or len(ts) == 0:
            return False

        # At this point in time, the epoc integer size will
        # never be less than 10 characters, and the stamp is
        # always preceded by a pound/hash character.
        if len(ts) < 10 or str(ts)[0] != "#":
            return False

        # The final check is to make sure the entire string
        # is composed of numbers. Try to convert to an int.
        try:
            int(str(ts)[1:])
        except ValueError:
            return False

        return True
Beispiel #9
0
    def _generator(self, tasks):
        # determine if we're on a 32 or 64 bit kernel
        if self.context.symbol_space.get_type(self.config["vmlinux"] +
                                              constants.BANG +
                                              "pointer").size == 4:
            is_32bit_arch = True
        else:
            is_32bit_arch = False

        for task in tasks:
            process_name = utility.array_to_string(task.comm)

            for vma, data in self._list_injections(task):
                if is_32bit_arch:
                    architecture = "intel"
                else:
                    architecture = "intel64"

                disasm = interfaces.renderers.Disassembly(
                    data, vma.vm_start, architecture)

                yield (0, (task.pid, process_name,
                           format_hints.Hex(vma.vm_start),
                           format_hints.Hex(vma.vm_end), vma.get_protection(),
                           format_hints.HexBytes(data), disasm))
Beispiel #10
0
    def _generator(self, tasks: Iterator[Any]) -> Generator[Tuple[int, Tuple[int, str, int, str]], None, None]:
        for task in tasks:
            proc_layer_name = task.add_process_layer()
            if proc_layer_name is None:
                continue

            proc_layer = self.context.layers[proc_layer_name]

            argsstart = task.user_stack - task.p_argslen

            if not proc_layer.is_valid(argsstart) or task.p_argslen == 0 or task.p_argc == 0:
                continue

            # Add one because the first two are usually duplicates
            argc = task.p_argc + 1

            # smear protection
            if argc > 1024:
                continue

            task_name = utility.array_to_string(task.p_comm)

            args = []  # type: List[bytes]

            while argc > 0:
                try:
                    arg = proc_layer.read(argsstart, 256)
                except exceptions.InvalidAddressException:
                    break

                idx = arg.find(b'\x00')
                if idx != -1:
                    arg = arg[:idx]

                argsstart += len(str(arg)) + 1

                # deal with the stupid alignment (leading nulls) and arg duplication
                if len(args) == 0:
                    while argsstart < task.user_stack:
                        try:
                            check = proc_layer.read(argsstart, 1)
                        except exceptions.InvalidAddressException:
                            break

                        if check != b"\x00":
                            break

                        argsstart = argsstart + 1

                    args.append(arg)

                # also check for initial duplicates since OS X is painful
                elif arg != args[0]:
                    args.append(arg)

                argc = argc - 1

            args_str = " ".join([s.decode("utf-8") for s in args])

            yield (0, (task.p_pid, task_name, task.p_argc, args_str))
Beispiel #11
0
    def _generator(self, procs):

        for proc in procs:
            process_name = utility.array_to_string(proc.ImageFileName)
            try:
                proc_layer_name = proc.add_process_layer()
            except exceptions.InvalidAddressException:
                continue

            try:
                peb = self._context.object(self.config["nt_symbols"] +
                                           constants.BANG + "_PEB",
                                           layer_name=proc_layer_name,
                                           offset=proc.Peb)

                result_text = peb.ProcessParameters.CommandLine.get_string()

            except exceptions.SwappedInvalidAddressException as exp:
                result_text = "Required memory at {0:#x} is inaccessible (swapped)".format(
                    exp.invalid_address)

            except exceptions.PagedInvalidAddressException as exp:
                result_text = "Required memory at {0:#x} is not valid (process exited?)".format(
                    exp.invalid_address)

            except exceptions.InvalidAddressException as exp:
                result_text = "Required memory at {0:#x} is not valid (incomplete layer {1}?)".format(
                    exp.invalid_address, exp.layer_name)

            yield (0, (proc.UniqueProcessId, process_name, result_text))
Beispiel #12
0
    def _generator(self, procs):
        def passthrough(_: 'interfaces.objects.ObjectInterface') -> bool:
            return False

        filter_func = passthrough
        if self.config.get('address', None) is not None:

            def filter_function(
                    x: 'interfaces.objects.ObjectInterface') -> bool:
                return x.get_start() not in [self.config['address']]

            filter_func = filter_function

        for proc in procs:
            process_name = utility.array_to_string(proc.ImageFileName)

            for vad in self.list_vads(proc, filter_func=filter_func):
                yield (0, (proc.UniqueProcessId, process_name,
                           format_hints.Hex(vad.vol.offset),
                           format_hints.Hex(vad.get_start()),
                           format_hints.Hex(vad.get_end()), vad.get_tag(),
                           vad.get_protection(
                               self.protect_values(self.context,
                                                   self.config['primary'],
                                                   self.config['nt_symbols']),
                               winnt_protections), vad.get_commit_charge(),
                           vad.get_private_memory(),
                           format_hints.Hex(vad.get_parent()),
                           vad.get_file_name()))
Beispiel #13
0
    def list_sockets(cls,
                     context: interfaces.context.ContextInterface,
                     layer_name: str,
                     darwin_symbols: str,
                     filter_func: Callable[[int], bool] = lambda _: False) -> \
                Iterable[interfaces.objects.ObjectInterface]:
        """
        Returns the open socket descriptors of a process

        Return values:
            A tuple of 3 elements:
                1) The name of the process that opened the socket
                2) The process ID of the processed that opened the socket
                3) The address of the associated socket structure
        """
        for task in tasks.Tasks.list_tasks(context, layer_name, darwin_symbols, filter_func):

            task_name = utility.array_to_string(task.p_comm)
            pid = task.p_pid

            for filp, _, _ in mac.MacUtilities.files_descriptors_for_process(context, darwin_symbols, task):
                try:
                    ftype = filp.f_fglob.get_fg_type()
                except exceptions.InvalidAddressException:
                    continue

                if ftype != 'SOCKET':
                    continue

                try:
                    socket = filp.f_fglob.fg_data.dereference().cast("socket")
                except exceptions.InvalidAddressException:
                    continue

                yield task_name, pid, socket
Beispiel #14
0
    def _generator(self):
        filter_func = tasks.Tasks.create_pid_filter([self.config.get('pid', None)])

        for task_name, pid, socket in self.list_sockets(self.context,
                                                        self.config['primary'],
                                                        self.config['darwin'],
                                                        filter_func = filter_func):

            family = socket.get_family()

            if family == 1:
                try:
                    upcb = socket.so_pcb.dereference().cast("unpcb")
                    path = utility.array_to_string(upcb.unp_addr.sun_path)
                except exceptions.InvalidAddressException:
                    continue

                yield (0, (format_hints.Hex(socket.vol.offset), "UNIX", path, 0, "", 0, "",
                           "{}/{:d}".format(task_name, pid)))

            elif family in [2, 30]:
                state = socket.get_state()
                proto = socket.get_protocol_as_string()

                vals = socket.get_converted_connection_info()

                if vals:
                    (lip, lport, rip, rport) = vals

                    yield (0, (format_hints.Hex(socket.vol.offset), proto, lip, lport, rip, rport, state,
                               "{}/{:d}".format(task_name, pid)))
Beispiel #15
0
    def _generator(self, procs):

        pe_table_name = intermed.IntermediateSymbolTable.create(
            self.context,
            self.config_path,
            "windows",
            "pe",
            class_types=pe.class_types)

        for proc in procs:
            try:
                proc_id = proc.UniqueProcessId
                process_name = utility.array_to_string(proc.ImageFileName)
                filedata = self.process_dump(self.context,
                                             self.config["nt_symbols"],
                                             pe_table_name, proc)
                self.produce_file(filedata)
                result_text = "Stored {}".format(filedata.preferred_filename)
            except ValueError:
                result_text = "PE parsing error"
            except exceptions.SwappedInvalidAddressException as exp:
                result_text = "Process {}: Required memory at {:#x} is inaccessible (swapped)".format(
                    proc_id, exp.invalid_address)

            except exceptions.PagedInvalidAddressException as exp:
                result_text = "Process {}: Required memory at {:#x} is not valid (process exited?)".format(
                    proc_id, exp.invalid_address)

            except exceptions.InvalidAddressException as exp:
                result_text = "Process {}: Required memory at {:#x} is not valid (incomplete layer {}?)".format(
                    proc_id, exp.invalid_address, exp.layer_name)

            yield (0, (proc.UniqueProcessId, process_name, result_text))
Beispiel #16
0
    def _generator(self):
        """
        Lists the registered VFS event watching processes
        Also lists which event(s) a process is registered for
        """

        kernel = contexts.Module(self.context, self.config['darwin'], self.config['primary'], 0)

        watcher_table = kernel.object_from_symbol("watcher_table")

        for watcher in watcher_table:
            if watcher == 0:
                continue

            task_name = utility.array_to_string(watcher.proc_name)
            task_pid = watcher.pid

            events = []

            try:
                event_array = kernel.object(object_type = "array",
                                            offset = watcher.event_list,
                                            count = 13,
                                            subtype = kernel.get_type("unsigned char"))

            except exceptions.InvalidAddressException:
                continue

            for i, event in enumerate(event_array):
                if event == 1:
                    events.append(self.event_types[i])

            if events != []:
                yield (0, (task_name, task_pid, ",".join(events)))
Beispiel #17
0
    def _generator(self, procs):

        def passthrough(_: interfaces.objects.ObjectInterface) -> bool:
            return False

        filter_func = passthrough
        if self.config.get('address', None) is not None:

            def filter_function(x: interfaces.objects.ObjectInterface) -> bool:
                return x.get_start() not in [self.config['address']]

            filter_func = filter_function

        for proc in procs:
            process_name = utility.array_to_string(proc.ImageFileName)

            for vad in self.list_vads(proc, filter_func = filter_func):

                file_output = "Disabled"
                if self.config['dump']:
                    file_handle = self.vad_dump(self.context, proc, vad, self.open)
                    file_output = "Error outputting file"
                    if file_handle:
                        file_handle.close()
                        file_output = file_handle.preferred_filename

                yield (0, (proc.UniqueProcessId, process_name, format_hints.Hex(vad.vol.offset),
                           format_hints.Hex(vad.get_start()), format_hints.Hex(vad.get_end()), vad.get_tag(),
                           vad.get_protection(
                               self.protect_values(self.context, self.config['primary'], self.config['nt_symbols']),
                               winnt_protections), vad.get_commit_charge(), vad.get_private_memory(),
                           format_hints.Hex(vad.get_parent()), vad.get_file_name(), file_output))
Beispiel #18
0
    def _generator(self, procs):
        # determine if we're on a 32 or 64 bit kernel
        is_32bit_arch = not symbols.symbol_table_is_64bit(
            self.context, self.config["nt_symbols"])

        for proc in procs:
            process_name = utility.array_to_string(proc.ImageFileName)

            for vad, data in self.list_injections(self.context,
                                                  self.config["nt_symbols"],
                                                  proc):

                # if we're on a 64 bit kernel, we may still need 32 bit disasm due to wow64
                if is_32bit_arch or proc.get_is_wow64():
                    architecture = "intel"
                else:
                    architecture = "intel64"

                disasm = interfaces.renderers.Disassembly(
                    data, vad.get_start(), architecture)

                yield (0, (proc.UniqueProcessId, process_name,
                           format_hints.Hex(vad.get_start()),
                           format_hints.Hex(vad.get_end()), vad.get_tag(),
                           vad.get_protection(
                               vadinfo.VadInfo.protect_values(
                                   self.context, proc.vol.layer_name,
                                   self.config["nt_symbols"]),
                               vadinfo.winnt_protections),
                           vad.get_commit_charge(), vad.get_private_memory(),
                           format_hints.HexBytes(data), disasm))
 def __init__(self, task, sshenc, addr):
     self.task = task
     self.task_name = utility.array_to_string(task.comm)
     self.sshenc_addr = addr
     self.enc_name = None
     self.key = None
     self.iv = None
     self.sshenc = sshenc
    def _generator(self, tasks):
        for task in tasks:
            name = utility.array_to_string(task.comm)
            pid = int(task.pid)

            for fd_num, _, full_path in linux.LinuxUtilities.files_descriptors_for_process(
                    self.config, self.context, task):
                yield (0, (pid, name, fd_num, full_path))
Beispiel #21
0
    def _generator(self):
        for module in self.list_modules(self.context, self.config['primary'],
                                        self.config['darwin']):

            mod_name = utility.array_to_string(module.name)
            mod_size = module.size

            yield 0, (format_hints.Hex(module.vol.offset), mod_name, mod_size)
Beispiel #22
0
    def _generator(self, tasks):
        is_32bit = not symbols.symbol_table_is_64bit(self.context,
                                                     self.config["darwin"])
        if is_32bit:
            pack_format = "I"
            bash_json_file = "bash32"
        else:
            pack_format = "Q"
            bash_json_file = "bash64"

        bash_table_name = BashIntermedSymbols.create(self.context,
                                                     self.config_path, "linux",
                                                     bash_json_file)

        ts_offset = self.context.symbol_space.get_type(
            bash_table_name + constants.BANG +
            "hist_entry").relative_child_offset("timestamp")

        for task in tasks:
            task_name = utility.array_to_string(task.p_comm)
            if task_name not in ["bash", "sh", "dash"]:
                continue

            proc_layer_name = task.add_process_layer()
            if proc_layer_name is None:
                continue

            proc_layer = self.context.layers[proc_layer_name]

            bang_addrs = []

            # find '#' values on the heap
            for address in proc_layer.scan(
                    self.context,
                    scanners.BytesScanner(b"#"),
                    sections=task.get_process_memory_sections(
                        self.context, self.config['darwin'], rw_no_file=True)):
                bang_addrs.append(struct.pack(pack_format, address))

            history_entries = []

            for address, _ in proc_layer.scan(
                    self.context,
                    scanners.MultiStringScanner(bang_addrs),
                    sections=task.get_process_memory_sections(
                        self.context, self.config['darwin'], rw_no_file=True)):
                hist = self.context.object(bash_table_name + constants.BANG +
                                           "hist_entry",
                                           offset=address - ts_offset,
                                           layer_name=proc_layer_name)

                if hist.is_valid():
                    history_entries.append(hist)

            for hist in sorted(history_entries,
                               key=lambda x: x.get_time_as_integer()):
                yield (0, (int(task.p_pid), task_name, hist.get_time_object(),
                           hist.get_command()))
Beispiel #23
0
    def _generator(self, tasks):
        for task in tasks:
            task_name = utility.array_to_string(task.p_comm)
            pid = task.p_pid

            for filp, _, _ in mac.MacUtilities.files_descriptors_for_process(
                    self.config, self.context, task):
                try:
                    ftype = filp.f_fglob.get_fg_type()
                except exceptions.InvalidAddressException:
                    continue

                if ftype != 'DTYPE_SOCKET':
                    continue

                try:
                    socket = filp.f_fglob.fg_data.dereference().cast("socket")
                except exceptions.InvalidAddressException:
                    continue

                family = socket.get_family()

                if family == 1:
                    try:
                        upcb = socket.so_pcb.dereference().cast("unpcb")
                        path = utility.array_to_string(upcb.unp_addr.sun_path)
                    except exceptions.InvalidAddressException:
                        continue

                    yield (0,
                           (format_hints.Hex(socket.vol.offset), "UNIX", path,
                            0, "", 0, "", "{}/{:d}".format(task_name, pid)))

                elif family in [2, 30]:
                    state = socket.get_state()
                    proto = socket.get_protocol_as_string()

                    vals = socket.get_converted_connection_info()

                    if vals:
                        (lip, lport, rip, rport) = vals

                        yield (0, (format_hints.Hex(socket.vol.offset), proto,
                                   lip, lport, rip, rport, state,
                                   "{}/{:d}".format(task_name, pid)))
Beispiel #24
0
    def _generator(self):
        for module in self.list_modules(self.context, self.config['primary'],
                                        self.config['vmlinux']):

            mod_size = module.get_init_size() + module.get_core_size()

            mod_name = utility.array_to_string(module.name)

            yield 0, (format_hints.Hex(module.vol.offset), mod_name, mod_size)
 def __init__(self, context, openssh_table_name, proc_layer_name, task,
              progress_callback):
     self.context = context
     self.openssh_table_name = openssh_table_name
     self.proc_layer_name = proc_layer_name
     self.proc_layer = self.context.layers[proc_layer_name]
     self.task = task
     self.task_name = utility.array_to_string(task.comm)
     self.openssh_symbols = self.context.symbol_space[openssh_table_name]
     self.progress_callback = progress_callback
Beispiel #26
0
 def _check_header(self) -> Optional[Tuple[str, interfaces.objects.ObjectInterface]]:
     """Verifies the header of the PDB file and returns the version of the
     file."""
     for header in self._headers:
         header_type = self.pdb_symbol_table + constants.BANG + header
         current_header = self.context.object(header_type, self._base_layer, 0)
         if utility.array_to_string(current_header.Magic) == self._headers[header]:
             if not (current_header.PageSize < 0x100 or current_header.PageSize > (128 * 0x10000)):
                 return header, current_header
     return None
Beispiel #27
0
 def _generator(self):
     for task in self.list_tasks(self.context,
                                 self.config['primary'],
                                 self.config['darwin'],
                                 filter_func=self.create_pid_filter(
                                     [self.config.get('pid', None)])):
         pid = task.p_pid
         ppid = task.p_ppid
         name = utility.array_to_string(task.p_comm)
         yield (0, (pid, ppid, name))
Beispiel #28
0
    def _generator(self, mods: Iterator[Any]):
        mac.MacUtilities.aslr_mask_symbol_table(self.context,
                                                self.config['darwin'],
                                                self.config['primary'])

        kernel = contexts.Module(self._context, self.config['darwin'],
                                 self.config['primary'], 0)

        policy_list = kernel.object_from_symbol(
            symbol_name="mac_policy_list").cast("mac_policy_list")

        entries = kernel.object(
            object_type="array",
            offset=policy_list.entries.dereference().vol.offset,
            subtype=kernel.get_type('mac_policy_list_element'),
            count=policy_list.staticmax + 1)

        mask = self.context.layers[self.config['primary']].address_mask
        mods_list = [(mod.name, mod.address & mask,
                      (mod.address & mask) + mod.size) for mod in mods]

        for i, ent in enumerate(entries):
            # I don't know how this can happen, but the kernel makes this check all over the place
            # the policy isn't useful without any ops so a rootkit can't abuse this
            try:
                mpc = ent.mpc.dereference()
                ops = mpc.mpc_ops.dereference()
            except exceptions.InvalidAddressException:
                continue

            try:
                ent_name = utility.pointer_to_string(mpc.mpc_name, 255)
            except exceptions.InvalidAddressException:
                ent_name = "N/A"

            for check in ops.vol.members:
                call_addr = getattr(ops, check)

                if call_addr is None or call_addr == 0:
                    continue

                found_module = None

                for mod_name_info, mod_base, mod_end in mods_list:
                    if call_addr >= mod_base and call_addr <= mod_end:
                        found_module = mod_name_info
                        break

                if found_module:
                    symbol_module = utility.array_to_string(found_module)
                else:
                    symbol_module = "UNKNOWN"

                yield (0, (check, ent_name, symbol_module,
                           format_hints.Hex(call_addr)))
Beispiel #29
0
    def _generator(self, procs):

        pe_table_name = intermed.IntermediateSymbolTable.create(
            self.context,
            self.config_path,
            "windows",
            "pe",
            class_types=pe.class_types)

        for proc in procs:
            process_name = utility.array_to_string(proc.ImageFileName)

            try:
                proc_layer_name = proc.add_process_layer()
            except exceptions.InvalidAddressException:
                continue

            try:
                peb = self._context.object(self.config["nt_symbols"] +
                                           constants.BANG + "_PEB",
                                           layer_name=proc_layer_name,
                                           offset=proc.Peb)

                dos_header = self.context.object(
                    pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
                    offset=peb.ImageBaseAddress,
                    layer_name=proc_layer_name)

                filedata = interfaces.plugins.FileInterface(
                    "pid.{0}.{1:#x}.dmp".format(proc.UniqueProcessId,
                                                peb.ImageBaseAddress))

                for offset, data in dos_header.reconstruct():
                    filedata.data.seek(offset)
                    filedata.data.write(data)

                self.produce_file(filedata)
                result_text = "Stored {}".format(filedata.preferred_filename)

            except ValueError:
                result_text = "PE parsing error"

            except exceptions.SwappedInvalidAddressException as exp:
                result_text = "Required memory at {0:#x} is inaccessible (swapped)".format(
                    exp.invalid_address)

            except exceptions.PagedInvalidAddressException as exp:
                result_text = "Required memory at {0:#x} is not valid (process exited?)".format(
                    exp.invalid_address)

            except exceptions.InvalidAddressException as exp:
                result_text = "Required memory at {0:#x} is not valid (incomplete layer {1}?)".format(
                    exp.invalid_address, exp.layer_name)

            yield (0, (proc.UniqueProcessId, process_name, result_text))
Beispiel #30
0
    def _generator(self, procs):
        pe_table_name = intermed.IntermediateSymbolTable.create(self.context,
                                                                self.config_path,
                                                                "windows",
                                                                "pe",
                                                                class_types = extensions.pe.class_types)

        filter_func = lambda _: False
        if self.config.get('address', None) is not None:
            filter_func = lambda x: x.get_start() not in [self.config['address']]

        for proc in procs:
            process_name = utility.array_to_string(proc.ImageFileName)
            # TODO: what kind of exceptions could this raise and what should we do?
            proc_layer_name = proc.add_process_layer()

            for vad in vadinfo.VadInfo.list_vads(proc, filter_func = filter_func):

                # this parameter is inherited from the VadInfo plugin. if a user specifies
                # an address, then it bypasses the DLL identification heuristics
                if self.config.get("address", None) is None:

                    # rather than relying on the PEB for DLLs, which can be swapped,
                    # it requires special handling on wow64 processes, and its
                    # unreliable from an integrity standpoint, let's use the VADs instead
                    protection_string = vad.get_protection(
                        vadinfo.VadInfo.protect_values(self.context, self.config['primary'], self.config['nt_symbols']),
                        vadinfo.winnt_protections)

                    # DLLs are write copy...
                    if protection_string != "PAGE_EXECUTE_WRITECOPY":
                        continue

                    # DLLs have mapped files...
                    if isinstance(vad.get_file_name(), interfaces.renderers.BaseAbsentValue):
                        continue

                try:
                    filedata = interfaces.plugins.FileInterface("pid.{0}.{1}.{2:#x}.dmp".format(
                        proc.UniqueProcessId, ntpath.basename(vad.get_file_name()), vad.get_start()))

                    dos_header = self.context.object(pe_table_name + constants.BANG + "_IMAGE_DOS_HEADER",
                                                     offset = vad.get_start(),
                                                     layer_name = proc_layer_name)

                    for offset, data in dos_header.reconstruct():
                        filedata.data.seek(offset)
                        filedata.data.write(data)

                    self.produce_file(filedata)
                    result_text = "Stored {}".format(filedata.preferred_filename)
                except Exception:
                    result_text = "Unable to dump PE at {0:#x}".format(vad.get_start())

                yield (0, (proc.UniqueProcessId, process_name, result_text))