Beispiel #1
0
    def _complex_file_events(self) -> Generator[dict, None, None]:
        """Generator over files_dropped and files_copied events"""

        for copied_file in self.behaviour_report.get("files_copied", []):

            dst_file_name, dst_file_path = split_path(
                copied_file["destination"])
            src_file_name, src_file_path = split_path(copied_file["source"])

            yield {
                FieldNames.EVENT_TYPE: EventTypes.FILE_COPIED,
                FieldNames.SRC_FILE: {
                    FieldNames.FILE_NAME: src_file_name,
                    FieldNames.FILE_PATH: src_file_path,
                },
                FieldNames.DEST_FILE: {
                    FieldNames.FILE_NAME: dst_file_name,
                    FieldNames.FILE_PATH: dst_file_path,
                },
                **self.parent_process,
            }

        for dropped_file in self.behaviour_report.get("files_dropped", []):

            file_name, file_path = split_path(dropped_file["path"])

            yield {
                FieldNames.EVENT_TYPE: EventTypes.FILE_WRITTEN,
                FieldNames.FILE_NAME: file_name,
                FieldNames.FILE_PATH: file_path,
                FieldNames.HASHES: {
                    HashAlgos.SHA256: dropped_file["sha256"]
                },
                **self.parent_process,
            }
Beispiel #2
0
    def process_create(self, event) -> Tuple[Process, File, Process]:

        pid = -1
        command_line = None
        match = re.match(r"PID: (\d*), Command line: (.*)", event["params"])
        if match:
            pid, command_line = match.groups()

        process_image, process_image_path = split_path(event["path"])

        proc = Process(
            process_id=int(pid),
            process_image=process_image,
            process_image_path=process_image_path,
            command_line=command_line,
        )
        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        parent = Process(process_id=int(event["process_id"]),
                         process_image=event["process_name"])

        parent.launched[proc].append(timestamp=event["event_time"])

        return (proc, proc_file, parent)
Beispiel #3
0
    def _basic_file_events(self, process_summary: dict,
                           process: dict) -> Generator[dict, None, None]:

        event_type_mappings = {
            "file_deleted": EventTypes.FILE_DELETED,
            "file_opened": EventTypes.FILE_OPENED,
            "file_failed": EventTypes.FILE_OPENED,
            "file_read": EventTypes.FILE_OPENED,
            "file_written": EventTypes.FILE_WRITTEN,
            "dll_loaded": EventTypes.LOADED_MODULE,
            "file_attribute_changed": EventTypes.FILE_OPENED,
            "file_exists": EventTypes.FILE_OPENED,
        }

        for entry_key, event_type in event_type_mappings.items():

            for file_path in process_summary.get(entry_key, []):

                # Ignore directorys
                if file_path.endswith("\\"):
                    continue

                file_name, file_path = split_path(file_path)

                yield {
                    FieldNames.FILE_NAME: file_name,
                    FieldNames.FILE_PATH: file_path,
                    FieldNames.EVENT_TYPE: event_type,
                    **process,
                }
Beispiel #4
0
    def network_connection(
        self, event: dict
    ) -> Union[Tuple[Process, File, IPAddress], Tuple[Process, File, IPAddress, Domain]]:
        process_image, process_path = split_path(event["EventData_Image"])

        proc = SysMonProc(
            host=event["Computer"],
            user=event["EventData_User"],
            process_guid=event["EventData_ProcessGuid"],
            process_id=int(event["EventData_ProcessId"]),
            process_image=process_image,
            process_image_path=process_path,
        )
        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        dest_addr = IPAddress(ip_address=event["EventData_DestinationIp"])

        proc.connected_to[dest_addr].append(
            timestamp=event["EventData_UtcTime"],
            port=event["EventData_DestinationPort"],
            protocol=event["EventData_Protocol"],
        )

        if event.get("EventData_DestinationHostname"):
            hostname = Domain(event["EventData_DestinationHostname"])
            hostname.resolves_to[dest_addr].append(timestamp=event["EventData_UtcTime"])
            return (proc, proc_file, dest_addr, hostname)

        return (proc, proc_file, dest_addr)
Beispiel #5
0
    def dns_events(
        self, event: dict
    ) -> Union[Tuple[Process, File, Domain], Tuple[Process, File, Domain,
                                                   IPAddress]]:
        """Transforms a single DNS event

        Example event::

            {
                "mode": "dns_query",
                "protocol_type": "udp",
                "hostname": "foobar",
                "qtype": "Host Address",
                "processinfo": {
                    "imagepath": "C:\\ProgramData\\bloop\\some_proc.exe",
                    "tainted": true,
                    "md5sum": "....",
                    "pid": 3020
                },
                "timestamp": 27648
            }

        Optionally, if the event is "dns_query_answer", we can also extract the response.

        Parameters
        ----------
        event : dict
            source dns_query event

        Returns
        -------
        Tuple[Process, File, Domain]
            Process and its image, and the domain looked up
        """
        proc_info = event["processinfo"]
        process_image, process_image_path = split_path(proc_info["imagepath"])

        proc = Process(
            process_id=int(proc_info["pid"]),
            process_image=process_image,
            process_image_path=process_image_path,
        )

        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        domain = Domain(event["hostname"])

        proc.dns_query_for[domain].append(timestamp=int(event["timestamp"]))

        if "ipaddress" in event:
            addr = IPAddress(event["ipaddress"])
            domain.resolves_to[addr].append(timestamp=int(event["timestamp"]))
            return (proc, proc_file, domain, addr)
        else:
            return (proc, proc_file, domain)
Beispiel #6
0
    def access_file(self, event) -> Tuple[Process, File]:
        proc = Process(process_id=int(event["process_id"]),
                       process_image=event["process_name"])

        file_name, file_path = split_path(event["path"])
        target_file = File(file_name=file_name, file_path=file_path)

        proc.accessed[target_file].append(timestamp=event["event_time"])

        return (proc, target_file)
Beispiel #7
0
    def handles(self) -> Generator[dict, None, None]:
        """Converts the output of the rekall `handles` plugin to a series
        of events which represent accessing registry keys or file.

        Yields
        -------
        Generator[dict, None, None]
            One file or registry key access event a time.
        """

        for handle in self.session.plugins.handles().collect():

            # Regardless of if we use this handle or not, can make a process node
            # if this is a process that wasnt in pslist/pstree.
            e_proc = handle["_EPROCESS"]
            pid = int(e_proc.pid)

            if pid in self.processes:
                proc_data = self.processes[pid]
            else:
                logger.warn(
                    f"Previously unseen PID={pid} showed up in handles")

            if handle["obj_type"] == "File":

                full_file_path = handle["details"]

                if full_file_path.startswith("\\"):
                    full_file_path = full_file_path[1:]

                file_path, file_name = split_path(full_file_path)
                yield {
                    FieldNames.FILE_PATH: file_path,
                    FieldNames.FILE_NAME: file_name,
                    **proc_data,
                    FieldNames.EVENT_TYPE: EventTypes.FILE_OPENED,
                }
            elif handle["obj_type"] == "Key":

                key_path = handle["details"]
                if key_path.startswith("MACHINE\\"):
                    start_indx = len("MACHINE\\")
                    key_path = key_path[start_indx:]

                hive = key_path.split("\\")[0]
                key = key_path.split("\\")[-1]
                key_path = key_path[len(hive):len(key)]

                yield {
                    FieldNames.HIVE: hive,
                    FieldNames.REG_KEY: key,
                    FieldNames.REG_KEY_PATH: key_path,
                    **proc_data,
                    FieldNames.EVENT_TYPE: EventTypes.REG_KEY_OPENED,
                }
Beispiel #8
0
    def process_creation(self, event: dict) -> Tuple[Process, File, Process]:
        """Transformers a process creation (event ID 4688) into a set of nodes.

        https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/event.aspx?eventID=4688

        Parameters
        ----------
        event : dict
            [description]

        Returns
        -------
        Optional[Tuple[Process, File, Process, File]]
            [description]
        """

        # Get the parent PID
        parent_pid = int(event["data_name_processid"], 16)

        # Child PID
        child_pid = int(event["data_name_newprocessid"], 16)

        proc_name, proc_path = split_path(event["data_name_newprocessname"])

        child = Process(
            host=event["computer"],
            process_id=child_pid,
            user=event["data_name_subjectusername"],
            process_image=proc_name,
            process_image_path=proc_path,
            command_line=event.get("data_name_commandline"),
        )

        child_file = child.get_file_node()
        child_file.file_of[child]

        # Map the process for later
        self.seen_procs[child_pid] = child

        parent = self.seen_procs.get(parent_pid)

        if parent is None:
            # Create a dummy proc. If we haven't already seen the parent
            parent = Process(host=event["computer"], process_id=parent_pid)

        parent.launched[child].append(
            timestamp=event["timecreated_systemtime"])

        # Don't need to pull out the parent's file, as it will have always
        # been created before being put into seen_procs

        return (child, child_file, parent)
Beispiel #9
0
    def file_created(self, event: dict) -> Tuple[Process, File, File]:

        process_image, process_path = split_path(event["EventData_Image"])

        proc = SysMonProc(
            host=event["Computer"],
            user=event.get("EventData_User"),
            process_guid=event["EventData_ProcessGuid"],
            process_id=int(event["EventData_ProcessId"]),
            process_image=process_image,
            process_image_path=process_path,
        )
        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        file_image, file_path = split_path(event["EventData_TargetFilename"])

        file_node = File(file_name=file_image, file_path=file_path)

        proc.accessed[file_node].append(timestamp=event["EventData_UtcTime"])

        return (proc, proc_file, file_node)
Beispiel #10
0
    def process_creation(self,
                         event: dict) -> Tuple[Process, File, Process, File]:

        # Make the parent process
        parent_image, parent_path = split_path(event["EventData_ParentImage"])

        parent = SysMonProc(
            host=event["Computer"],
            process_id=int(event["EventData_ParentProcessId"]),
            process_guid=event["EventData_ParentProcessGuid"],
            process_image=parent_image,
            process_image_path=parent_path,
        )

        parent_file = parent.get_file_node()
        parent_file.file_of[parent]

        process_image, process_path = split_path(event["EventData_Image"])

        proc = SysMonProc(
            host=event["Computer"],
            user=event["EventData_User"],
            process_guid=event["EventData_ProcessGuid"],
            process_id=int(event["EventData_ProcessId"]),
            process_image=process_image,
            process_image_path=process_path,
            command_line=event["EventData_CommandLine"],
            hashes={
                val.split("=")[0].lower(): val.split("=")[1]
                for val in event["EventData_Hashes"].split(",")
            },
        )

        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        parent.launched[proc].append(timestamp=event["EventData_UtcTime"])

        return (parent, parent_file, proc, proc_file)
Beispiel #11
0
    def conn_events(self, event: dict) -> Tuple[Process, File, IPAddress]:
        """Transforms a single connection event

        Example event::

            {
                "mode": "connect",
                "protocol_type": "tcp",
                "ipaddress": "199.168.199.123",
                "destination_port": 3333,
                "processinfo": {
                    "imagepath": "C:\\ProgramData\\bloop\\some_proc.exe",
                    "tainted": true,
                    "md5sum": "....",
                    "pid": 3020
                },
                "timestamp": 27648
            }

        Parameters
        ----------
        event : dict
            source dns_query event

        Returns
        -------
        Tuple[Process, File, IPAddress]
            Process and its image, and the destination address
        """
        proc_info = event["processinfo"]
        process_image, process_image_path = split_path(proc_info["imagepath"])

        proc = Process(
            process_id=int(proc_info["pid"]),
            process_image=process_image,
            process_image_path=process_image_path,
        )

        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        addr = IPAddress(event["ipaddress"])

        proc.connected_to[addr].append(
            protocol=event["protocol_type"],
            timestamp=event["timestamp"],
            port=int(event["destination_port"]),
        )

        return (proc, proc_file, addr)
Beispiel #12
0
    def access_reg_key(self, event) -> Tuple[Process, RegistryKey]:

        proc = Process(process_id=int(event["process_id"]),
                       process_image=event["process_name"])

        reg_key, reg_path = split_path(event["path"])

        hive = reg_path.split("\\")[0]
        reg_path = "\\".join(reg_path.split("\\")[1:])

        reg_node = RegistryKey(hive=hive, key_path=reg_path, key=reg_key)

        proc.read_key[reg_node].append(timestamp=event["event_time"])

        return (proc, reg_node)
Beispiel #13
0
    def registry_creation(
            self, event: dict) -> Optional[Tuple[Process, File, RegistryKey]]:

        if "EventData_TargetObject" not in event:
            return None

        process_image, process_path = split_path(event["EventData_Image"])

        proc = SysMonProc(
            host=event["Computer"],
            user=event.get("EventData_User"),
            process_guid=event["EventData_ProcessGuid"],
            process_id=int(event["EventData_ProcessId"]),
            process_image=process_image,
            process_image_path=process_path,
        )
        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        key_path = event["EventData_TargetObject"]
        hive = key_path.split("\\")[1]
        key = key_path.split("\\")[-1]
        # Always has a leading \\ so split from 2:
        key_path = "\\".join(key_path.split("\\")[2:-1])

        key = RegistryKey(
            hive=hive,
            key=key,
            key_path=key_path,
            value=event.get("EventData_Details"),
            value_type="DWORD",
        )

        event_type = event["EventData_EventType"]
        if event_type == "SetValue":
            proc.changed_value[key].append(
                value=event.get("EventData_Details"),
                timestamp=event["EventData_UtcTime"])
        elif event_type == "DeleteValue":
            proc.deleted_value[key].append(
                timestamp=event["EventData_UtcTime"])
        elif event_type == "CreateKey":
            proc.created_key[key].append(timestamp=event["EventData_UtcTime"])
        elif event_type == "DeleteKey":
            proc.deleted_key[key].append(timestamp=event["EventData_UtcTime"])

        return (proc, proc_file, key)
Beispiel #14
0
    def make_file(self, event: dict) -> Tuple[TCFile]:

        base_obj = event["baseObject"]

        file_node = TCFile(uuid=event["uuid"], host=base_obj["hostId"])

        # Since not everything has a full path, and this is multiple different systems,
        # this is the best try for this.
        if base_obj.get("properties"):
            full_path = base_obj["properties"]["map"].get("filename", "")
            full_path = full_path.replace("/", "\\")
            file_name, file_path = split_path(full_path)

            file_node.full_path = full_path
            file_node.file_path = file_path
            file_node.file_name = file_name

        return (file_node, )
Beispiel #15
0
    def _parse_process_name(self, proc_string: str) -> dict:
        """Pulls out the comand line, process name, and process path out of a string, if possible"""

        # NOTE: Case not handeled by the regex, hardcoded result:

        # Tencent
        if proc_string == "****.exe":
            proc_path = "****.exe"

        # Sometimes, "****.exe --local-service" shows up.
        elif proc_string.startswith("****.exe"):
            proc_path = "****.exe"

        # Dr.web
        elif proc_string == "<PATH_SAMPLE.EXE>":
            proc_path = "<PATH_SAMPLE.EXE>"

        # Manually introduced.
        elif proc_string == "<SUBMITTED_FILE>":
            proc_path = "<SUBMITTED_FILE>"

        # Try and parse the path.
        else:
            match = PROC_PATH_REX.match(proc_string)
            if match:
                proc_path = match.group()
            else:
                logger.critical(f"Could not parse {proc_string}")

        # Leave only the command line
        command_line = proc_string.replace(proc_path, "")

        # Remove leading whitespace.
        command_line = command_line.lstrip()

        proc_name, proc_path = split_path(proc_path)

        return {
            FieldNames.PROCESS_IMAGE: proc_name,
            FieldNames.PROCESS_IMAGE_PATH: proc_path,
            FieldNames.COMMAND_LINE: command_line,
        }
Beispiel #16
0
    def dns_lookup(self, event: dict) -> Tuple[Process, File, Domain]:
        process_image, process_path = split_path(event["EventData_Image"])

        proc = SysMonProc(
            host=event["Computer"],
            user=event.get("EventData_User"),
            process_guid=event["EventData_ProcessGuid"],
            process_id=int(event["EventData_ProcessId"]),
            process_image=process_image,
            process_image_path=process_path,
        )
        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        # TODO: Parse out EventData_QueryResults and add resolutions
        domain = Domain(domain=event["EventData_QueryName"])

        proc.dns_query_for[domain].append(timestamp=event["EventData_UtcTime"])

        return (proc, proc_file, domain)
Beispiel #17
0
    def _basic_file_events(self) -> Generator[dict, None, None]:

        event_type_mappings = {
            "files_deleted": EventTypes.FILE_DELETED,
            "files_opened": EventTypes.FILE_OPENED,
            "files_written": EventTypes.FILE_WRITTEN,
            "modules_loaded": EventTypes.LOADED_MODULE,
            "files_attribute_changed": EventTypes.FILE_OPENED,
        }

        for entry_key, event_type in event_type_mappings.items():

            for file_path in self.behaviour_report.get(entry_key, []):

                file_name, file_path = split_path(file_path)

                yield {
                    FieldNames.FILE_NAME: file_name,
                    FieldNames.FILE_PATH: file_path,
                    FieldNames.EVENT_TYPE: event_type,
                    **self.parent_process,
                }
Beispiel #18
0
    def make_process(
            self, event: dict
    ) -> Union[Tuple[TCProcess], Tuple[TCProcess, TCProcess]]:
        if event.get("cmdLine"):
            proc_cmdline = event["cmdLine"]["string"]
        else:
            proc_cmdline = None

        path = None
        image = None
        if event.get("properties"):
            path = event["properties"]["map"].get("path")
            if "/" in path:
                # Swap the path directions
                path = path.replace("/", "\\")
            image, path = split_path(path)

        proc = TCProcess(
            uuid=event["uuid"],
            process_image=image or proc_cmdline,
            process_image_path=path or proc_cmdline,
            command_line=proc_cmdline,
            host=event["hostId"],
        )
        if event.get("parentSubject"):

            parent = TCProcess(
                uuid=event["parentSubject"]
                ["com.bbn.tc.schema.avro.cdm18.UUID"],
                host=event["hostId"],
            )

            parent.launched[proc]

            return (proc, parent)
        else:
            return (proc, )
Beispiel #19
0
    def identify_processes(self) -> Dict[int, dict]:
        """The `generic` tab contains an array of processes. We can iterate over it to quickly generate
        `Process` entries for later. After grabbing all processes, we can walk the "processtree" entry
        to update them with the command lines.


        Returns
        -------
        None
        """

        processes = {}

        for process in self.behavior["generic"]:

            proc_name, proc_path = split_path(process["process_path"])

            processes[int(process["pid"])] = {
                FieldNames.PROCESS_IMAGE: proc_name,
                FieldNames.PROCESS_IMAGE_PATH: proc_path,
                FieldNames.PROCESS_ID: int(process["pid"]),
            }

        return processes
    def make_process(
        self, event: dict
    ) -> Optional[Union[Tuple[Process, File], Tuple[Process, File, Process,
                                                    File]]]:
        """Converts a processEvent into either one Process node, or two Process nodes with a
        parent - (Launched) -> child relationship.
        Additionally, creats File nodes for the images of both of the Processe's identified.

        Parameters
        ----------
        event : dict
            The processEvent event

        Returns
        -------
        Optional[Union[Tuple[Process, File], Tuple[Process, File, Process, File]]]
            Returns either a single process node, or a (parent, child) tuple
            where the parent has a launched edge to the child.
        """

        # Only look at start or already running event types.
        if event["eventType"] not in ["start", "running"]:
            return None

        # Sometimes a process in a `running` state doens't properly identify the path
        # which causes a case where processPath == process.
        # For example {"process": "cmd.exe", "processPath": "cmd.exe"}

        # See: test_process_equal_processpath
        if event["processPath"] == event["process"]:
            return None

        process_image, process_image_path = split_path(event["processPath"])

        # Pull out the hashes
        hashes: Dict[str, str] = {}
        if event.get("md5"):
            hashes = {"md5": event["md5"]}

        # Create the "child" process. This is the process who this event
        # belongs to.
        child = Process(
            process_image=process_image,
            process_image_path=process_image_path,
            command_line=event.get("processCmdLine"),
            process_id=int(event["pid"]),
            hashes=hashes,
            user=event.get("username", None),
        )

        # Pull out the image of the child process
        child_proc_file_node = child.get_file_node()

        # File - (File Of) -> Process
        child_proc_file_node.file_of[child]

        # If there is no parent field, return just the child
        if "parentProcessPath" not in event:

            return (child, child_proc_file_node)

        parent_process_image, parent_process_image_path = split_path(
            event["parentProcessPath"])

        # Create the parent process
        parent = Process(
            process_id=int(event["parentPid"]),
            process_image=parent_process_image,
            process_image_path=parent_process_image_path,
        )

        # Create a parent - (launched) -> child edge.
        parent.launched[child].append(timestamp=event["event_time"])

        # Pull out the image of the parent process
        parent_proc_file_node = child.get_file_node()

        # File - (File Of) -> Process
        parent_proc_file_node.file_of[child]

        return (parent, parent_proc_file_node, child, child_proc_file_node)
Beispiel #21
0
    def pslist(self) -> Generator[dict, None, None]:
        """Converts the output of rekall's `pslist` plugin to a series of dictionaries
        that represent a process getting launched.

        Returns
        -------
        Generator[dict, None, None]
            Yields one process launch event
        """

        # Function to switch fields to represent a parent
        def _convert_to_parent_fields(process: dict) -> dict:
            output = {}
            for left, right in [
                (FieldNames.PROCESS_IMAGE, FieldNames.PARENT_PROCESS_IMAGE),
                (FieldNames.PROCESS_ID, FieldNames.PARENT_PROCESS_ID),
                (FieldNames.COMMAND_LINE, FieldNames.PARENT_COMMAND_LINE),
                (FieldNames.PROCESS_IMAGE_PATH,
                 FieldNames.PARENT_PROCESS_IMAGE_PATH),
            ]:
                output[right] = process[left]

            return output

        # Use the pstree dict output to get a mapping from pid -> proc
        procs = self.session.plugins.pstree()._make_process_dict()

        parent_procs: Dict[int, dict] = {}

        # Add the system idle process
        parent_procs[0] = {
            FieldNames.PARENT_PROCESS_ID: 0,
            FieldNames.PARENT_COMMAND_LINE: "",
            FieldNames.PARENT_PROCESS_IMAGE: "System Idle Process",
            FieldNames.PARENT_PROCESS_IMAGE_PATH: "\\",
        }

        for proc in procs.values():

            parent_pid = proc.InheritedFromUniqueProcessId

            # Get the current processes info
            command_line = str(proc.Peb.ProcessParameters.CommandLine)
            image_path = str(proc.Peb.ProcessParameters.ImagePathName)

            if int(proc.pid) == 4:
                process_image = "SYSTEM"
                process_image_path = "\\"
            else:
                process_image, process_image_path = split_path(image_path)

            current_proc = {
                FieldNames.EVENT_TYPE: EventTypes.PROCESS_LAUNCHED,
                FieldNames.PROCESS_ID: int(proc.pid),
                FieldNames.COMMAND_LINE: command_line,
                FieldNames.PROCESS_IMAGE: process_image,
                FieldNames.PROCESS_IMAGE_PATH: process_image_path,
            }

            # Keep track of the processes.
            self.processes[int(proc.pid)] = current_proc

            current_as_parent = _convert_to_parent_fields(current_proc)
            parent_procs[int(proc.pid)] = current_as_parent

            # Parse the parent process
            if parent_pid not in parent_procs:

                # Do we the _EPROCESS for this process?
                if int(parent_pid) in procs:
                    parent = procs[int(parent_pid)]
                    parent_image_path = parent.Peb.ProcessParameters.ImagePathName

                    parent_process_image, parent_process_image_path = split_path(
                        str(parent_image_path))

                    parent_proc = {
                        FieldNames.PARENT_PROCESS_ID:
                        int(parent.pid),
                        FieldNames.PARENT_COMMAND_LINE:
                        parent.Peb.ProcessParameters.CommandLine,
                        FieldNames.PARENT_PROCESS_IMAGE:
                        parent_process_image,
                        FieldNames.PARENT_PROCESS_IMAGE_PATH:
                        parent_process_image_path,
                    }

                # If not, make a dummy one with the PID
                else:
                    parent_proc = {
                        FieldNames.PARENT_PROCESS_ID: int(parent_pid),
                        FieldNames.PARENT_COMMAND_LINE: "",
                        FieldNames.PARENT_PROCESS_IMAGE: "",
                        FieldNames.PARENT_PROCESS_IMAGE_PATH: "",
                    }

                parent_procs[int(parent_pid)] = parent_proc

            yield {**current_proc, **parent_procs[int(parent_pid)]}
Beispiel #22
0
    def process_events(
            self,
            event: dict) -> Optional[Tuple[Process, File, Process, File]]:
        """Transformers events from the `process` entry.

        A single process entry looks like::

            {
                "mode": string,
                "fid": dict,
                "parentname": string,
                "cmdline": string,
                "sha1sum": "string,
                "md5sum": string,
                "sha256sum": string,
                "pid": int,
                "filesize": int,
                "value": string,
                "timestamp": int,
                "ppid": int
            },

        Parameters
        ----------
        event : dict
            The input event.

        Returns
        -------
        Optional[Tuple[Process, File, Process, File]]
            Parent and child processes, and the file nodes that represent their binaries.
        """

        if event.get("mode") != "started":
            return None

        process_image, process_image_path = split_path(event["value"])
        parent_image, parent_image_path = split_path(event["parentname"])

        hashes = {
            HashAlgos.MD5: event.get("md5sum"),
            HashAlgos.SHA1: event.get("sha1sum"),
            HashAlgos.SHA256: event.get("sha256sum"),
        }
        proc = Process(
            process_image=process_image,
            process_image_path=process_image_path,
            command_line=event["cmdline"],
            process_id=int(event["pid"]),
            hashes={h: k
                    for h, k in hashes.items() if k},
        )

        proc_file = proc.get_file_node()

        proc_file.file_of[proc]

        parent = Process(
            process_image=parent_image,
            process_image_path=parent_image_path,
            process_id=int(event["ppid"]),
        )

        parent_file = parent.get_file_node()

        parent_file.file_of[parent]

        parent.launched[proc].append(timestamp=int(event["timestamp"]))

        return (proc, proc_file, parent, parent_file)
Beispiel #23
0
    def regkey_events(self, event: dict) -> Tuple[Process, File, RegistryKey]:
        """Transforms a single registry key event

        Example event::

            {
                "mode": "queryvalue",
                "processinfo": {
                    "imagepath": "C:\\Users\\admin\\AppData\\Local\\Temp\\bar.exe",
                    "tainted": True,
                    "md5sum": "....",
                    "pid": 1700,
                },
                "value": "\\REGISTRY\\USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\\"ProxyOverride\"",
                "timestamp": 6203
            },

        Parameters
        ----------
        event : dict
            source regkey event

        Returns
        -------
        Tuple[Process, File, RegistrKey]
            Process and its image, and the registry key.
        """
        proc_info = event["processinfo"]
        process_image, process_image_path = split_path(proc_info["imagepath"])

        proc = Process(
            process_id=int(proc_info["pid"]),
            process_image=process_image,
            process_image_path=process_image_path,
        )

        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        path, key_contents = re.match(r"(.*)\\\"(.*)",
                                      event["value"]).groups()  # type: ignore

        key_contents = key_contents[:-1]  # remove last quote.

        hive, reg_key_path = path.replace("\\REGISTRY\\", "").split("\\", 1)

        if '" = ' in key_contents:
            key, value = key_contents.split('" = ')
        else:
            key = key_contents
            value = None

        regkey = RegistryKey(hive=hive,
                             key=key,
                             key_path=reg_key_path,
                             value=value)

        if event["mode"] == "added":
            proc.created_key[regkey].append(timestamp=event["timestamp"],
                                            value=value)
        elif event["mode"] == "setval":
            proc.changed_value[regkey].append(timestamp=event["timestamp"],
                                              value=value)
        elif event["mode"] in ["deleteval", "deleted"]:
            proc.deleted_key[regkey].append(timestamp=event["timestamp"],
                                            value=value)
        else:
            proc.read_key[regkey].append(timestamp=event["timestamp"],
                                         value=value)

        return (proc, proc_file, regkey)
Beispiel #24
0
    def file_events(
        self, event: dict
    ) -> Union[Tuple[Process, File, File], Tuple[Process, File, File, File]]:
        """Transforms a file event

        Example file event::

            {
                "mode": "created",
                "fid": { "ads": "", "content": 2533274790555891 },
                "processinfo": {
                    "imagepath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
                    "md5sum": "eb32c070e658937aa9fa9f3ae629b2b8",
                    "pid": 2956
                },
                "ntstatus": "0x0",
                "value": "C:\\Users\\admin\\AppData\\Local\\Temp\\sy24ttkc.k25.ps1",
                "CreateOptions": "0x400064",
                "timestamp": 9494
            }

        In 8.2.0 the `value` field became a dictionary when the mode is `failed`::

            "values": {
                "value": "C:\\Users\\admin\\AppData\\Local\\Temp\\sy24ttkc.k25.ps1""
            }

        Parameters
        ----------
        event : dict
            The source event

        Returns
        -------
        Tuple[Process, File, File]
            The process, the process' image, and the file written.
        """

        proc_info = event["processinfo"]
        process_image, process_image_path = split_path(proc_info["imagepath"])

        proc = Process(
            process_id=int(proc_info["pid"]),
            process_image=process_image,
            process_image_path=process_image_path,
        )

        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        # 8.2.0 changes.
        if "values" in event:
            full_path = event["values"]["value"]
        else:
            full_path = event["value"]

        file_name, file_path = split_path(full_path)

        file_node = File(file_name=file_name, file_path=file_path)
        file_node.set_extension()

        if event["mode"] == "created":
            proc.wrote[file_node].append(timestamp=event["timestamp"])
        elif event["mode"] == "deleted":
            proc.deleted[file_node].append(timestamp=event["timestamp"])
        elif event["mode"] == "CopyFile":
            src_name, src_path = split_path(event["source"])
            src_file = File(file_name=src_name, file_path=src_path)
            src_file.set_extension()

            src_file.copied_to[file_node].append(timestamp=event["timestamp"])

            proc.copied[src_file].append(timestamp=event["timestamp"])

            return (proc, proc_file, file_node, src_file)
        else:
            proc.accessed[file_node].append(timestamp=event["timestamp"])

        return (proc, proc_file, file_node)
Beispiel #25
0
    def http_requests(
        self, event: dict
    ) -> Union[Tuple[Process, File, IPAddress, URI, Domain], Tuple[
            Process, File, IPAddress, URI], Tuple[Process, File, IPAddress], ]:
        """Transforms a single `http_request` network event. A typical event looks like::

            {
                "mode": "http_request",
                "protocol_type": "tcp",
                "ipaddress": "199.168.199.1",
                "destination_port": 80,
                "processinfo": {
                    "imagepath": "c:\\Windows\\System32\\svchost.exe",
                    "tainted": false,
                    "md5sum": "1234",
                    "pid": 1292
                },
                "http_request": "GET /some_route.crl HTTP/1.1~~Cache-Control: max-age = 900~~User-Agent: Microsoft-CryptoAPI/10.0~~Host: crl.microsoft.com~~~~",
                "timestamp": 433750
            }


        Parameters
        ----------
        event : dict
            The source `network` event with mode `http_request`

        Returns
        -------
        Tuple[Node]
            [description]
        """

        proc_info = event["processinfo"]
        process_image, process_image_path = split_path(proc_info["imagepath"])

        proc = Process(
            process_id=int(proc_info["pid"]),
            process_image=process_image,
            process_image_path=process_image_path,
        )

        proc_file = proc.get_file_node()
        proc_file.file_of[proc]

        addr = IPAddress(event["ipaddress"])

        proc.connected_to[addr].append(
            timestamp=event["timestamp"],
            protocol=event["protocol_type"],
            port=event["destination_port"],
        )

        try:
            url, header = event["http_request"].split("~~", 1)

            method, uri_path, _ = url.split(" ")

            uri = URI(uri_path)

            headers = dict(
                email.message_from_string(header.replace("~~", "\n")).items())

            proc.http_request_to[uri].append(timestamp=event["timestamp"],
                                             method=method)

            if "Host" in headers:
                domain = Domain(headers["Host"])  # type: ignore

                domain.resolves_to[addr].append(timestamp=event["timestamp"])
                uri.uri_of[domain]

                return (proc, proc_file, addr, uri, domain)
            else:
                return (proc, proc_file, addr, uri)

        except (ValueError, KeyError):
            return (proc, proc_file, addr)