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, }
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)
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, }
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)
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)
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)
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, }
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)
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)
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)
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)
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)
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)
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, )
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, }
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)
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, }
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, )
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)
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)]}
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)
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)
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)
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)