def make_process(self, event: dict) -> Tuple[Process, File, Process, File]: """Accepts a process with the `EventTypes.PROCESS_LAUNCHED` event_type. For example:: { FieldNames.PARENT_PROCESS_IMAGE: "cmd.exe", FieldNames.PARENT_PROCESS_IMAGE_PATH: "\\", FieldNames.PARENT_PROCESS_ID: "2568", FieldNames.PARENT_COMMAND_LINE: '/K name.exe"', FieldNames.PROCESS_IMAGE: "find.exe", FieldNames.PROCESS_IMAGE_PATH: "\\", FieldNames.COMMAND_LINE: 'find /i "svhost.exe"', FieldNames.PROCESS_ID: "3144", FieldNames.EVENT_TYPE: EventTypes.PROCESS_LAUNCHED, } Parameters ---------- event : dict [description] Returns ------- Tuple[Process, File, Process, File] [description] """ parent = Process( process_image=event[FieldNames.PARENT_PROCESS_IMAGE], process_image_path=event[FieldNames.PARENT_PROCESS_IMAGE_PATH], process_id=int(event[FieldNames.PARENT_PROCESS_ID]), command_line=event[FieldNames.PARENT_COMMAND_LINE], ) # Create the file node. # TODO: Integrate into the Process() init function? parent_file = parent.get_file_node() parent_file.file_of[parent] child = Process( process_image=event[FieldNames.PROCESS_IMAGE], process_image_path=event[FieldNames.PROCESS_IMAGE_PATH], process_id=int(event[FieldNames.PROCESS_ID]), command_line=event[FieldNames.COMMAND_LINE], ) child_file = child.get_file_node() child_file.file_of[child] if FieldNames.TIMESTAMP in event: parent.launched[child].append( timestamp=int(event[FieldNames.TIMESTAMP])) else: parent.launched[child] return (parent, parent_file, child, child_file)
def make_regkey_set_value( self, event: dict) -> Tuple[Process, File, RegistryKey]: process = Process( process_image=event[FieldNames.PROCESS_IMAGE], process_image_path=event[FieldNames.PROCESS_IMAGE_PATH], process_id=int(event[FieldNames.PROCESS_ID]), command_line=event[FieldNames.COMMAND_LINE], ) proc_file = process.get_file_node() proc_file.file_of[process] # RegistryKey Node Creation reg_node = RegistryKey( hive=event[FieldNames.HIVE], key_path=event[FieldNames.REG_KEY_PATH], key=event[FieldNames.REG_KEY], value=event.get(FieldNames.REG_KEY_VALUE), ) if reg_node.value: process.changed_value[reg_node].append(value=reg_node.value) else: process.changed_value[reg_node] return (process, proc_file, reg_node)
def make_dnslookup( self, event: dict ) -> Union[Tuple[Process, File, Domain, IPAddress], Tuple[Process, File, Domain]]: process = Process( process_image=event[FieldNames.PROCESS_IMAGE], process_image_path=event[FieldNames.PROCESS_IMAGE_PATH], process_id=int(event[FieldNames.PROCESS_ID]), command_line=event[FieldNames.COMMAND_LINE], ) proc_file = process.get_file_node() proc_file.file_of[process] dom = Domain(event[FieldNames.HTTP_HOST]) process.dns_query_for[dom] # Sometimes we don't know what the domain resolved to. if FieldNames.IP_ADDRESS in event: addr = IPAddress(ip_address=event[FieldNames.IP_ADDRESS]) dom.resolves_to[addr] return (process, proc_file, dom, addr) else: return (process, proc_file, dom)
def make_connection(self, event: dict) -> Tuple[Process, File, IPAddress]: process = Process( process_image=event[FieldNames.PROCESS_IMAGE], process_image_path=event[FieldNames.PROCESS_IMAGE_PATH], process_id=int(event[FieldNames.PROCESS_ID]), command_line=event[FieldNames.COMMAND_LINE], ) proc_file = process.get_file_node() proc_file.file_of[process] addr = IPAddress(ip_address=event[FieldNames.IP_ADDRESS]) if FieldNames.PORT in event and FieldNames.PROTOCOL in event: process.connected_to[addr].append( port=int(event[FieldNames.PORT]), protocol=event[FieldNames.PROTOCOL]) elif FieldNames.PORT in event: process.connected_to[addr].append(port=int(event[FieldNames.PORT])) elif FieldNames.PROTOCOL in event: process.connected_to[addr].append( protocol=event[FieldNames.PROTOCOL]) else: process.connected_to[addr] return (process, proc_file, addr)
def make_http_req( self, event: dict ) -> Union[Tuple[Process, File, URI, Domain], Tuple[Process, File, URI, Domain, IPAddress]]: process = Process( process_image=event[FieldNames.PROCESS_IMAGE], process_image_path=event[FieldNames.PROCESS_IMAGE_PATH], process_id=int(event[FieldNames.PROCESS_ID]), command_line=event[FieldNames.COMMAND_LINE], ) proc_file = process.get_file_node() proc_file.file_of[process] dom = Domain(event[FieldNames.HTTP_HOST]) uri = URI(uri=event[FieldNames.URI]) uri.uri_of[dom] process.http_request_to[uri].append( method=event[FieldNames.HTTP_METHOD]) if FieldNames.IP_ADDRESS in event: ip = IPAddress(event[FieldNames.IP_ADDRESS]) dom.resolves_to[ip] process.connected_to[ip] return (process, proc_file, uri, dom, ip) else: return (process, proc_file, uri, dom)
def make_file_copy(self, event: dict) -> Tuple[Process, File, File, File]: process = Process( process_image=event[FieldNames.PROCESS_IMAGE], process_image_path=event[FieldNames.PROCESS_IMAGE_PATH], process_id=int(event[FieldNames.PROCESS_ID]), command_line=event[FieldNames.COMMAND_LINE], ) proc_file = process.get_file_node() proc_file.file_of[process] # Source file src_file = File( file_path=event[FieldNames.SRC_FILE][FieldNames.FILE_PATH], file_name=event[FieldNames.SRC_FILE][FieldNames.FILE_NAME], hashes=event[FieldNames.SRC_FILE].get(FieldNames.HASHES), ) # Dest file src_file.set_extension() dest_file = File( file_path=event[FieldNames.DEST_FILE][FieldNames.FILE_PATH], file_name=event[FieldNames.DEST_FILE][FieldNames.FILE_NAME], hashes=event[FieldNames.DEST_FILE].get(FieldNames.HASHES), ) dest_file.set_extension() src_file.copied_to[dest_file] process.copied[src_file] return (process, proc_file, src_file, dest_file)
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 make_imageload(self, event: dict) -> Optional[Tuple[File, Process, File]]: # Pull out the process fields. process = Process( process_image=event["process"], process_image_path=event["processPath"], process_id=int(event["pid"]), user=event.get("username", None), ) # Pull out the image of the process file_node = process.get_file_node() # File - (File Of) -> Process file_node.file_of[process] # Add the drive where possible. if event.get("drive"): file_path = f"{event['drive']}:\\{event['filePath']}" else: file_path = event["filePath"] loaded_file = File(file_path=file_path, file_name=event["fileName"]) loaded_file.set_extension() process.loaded[loaded_file].append(timestamp=event["event_time"]) return (loaded_file, process, file_node)
def make_basic_regkey(self, event: dict) -> Tuple[Process, File, RegistryKey]: process = Process( process_image=event[FieldNames.PROCESS_IMAGE], process_image_path=event[FieldNames.PROCESS_IMAGE_PATH], process_id=int(event[FieldNames.PROCESS_ID]), command_line=event[FieldNames.COMMAND_LINE], ) proc_file = process.get_file_node() proc_file.file_of[process] # RegistryKey Node Creation reg_node = RegistryKey( hive=event[FieldNames.HIVE], key_path=event[FieldNames.REG_KEY_PATH], key=event[FieldNames.REG_KEY], ) if event["event_type"] == EventTypes.REG_KEY_OPENED: process.read_key[reg_node] else: process.deleted_key[reg_node] return (process, proc_file, reg_node)
def make_file(self, event: dict) -> Optional[Tuple[File, Process, File]]: """Converts a fileWriteEvent to two nodes, a file and the process manipulated the file. Generates a process - (Wrote) -> File edge. Parameters ---------- event : dict The fileWriteEvent event. Returns ------- Optional[Tuple[File, Process, File]] Returns a tuple contaning the File that this event is focused on, and the process which manipulated the file. The process has a Wrote edge to the file. Also contains the file that the process belongs to. """ if "filePath" not in event: return None # Add the drive where possible. if event.get("drive"): file_path = f"{event['drive']}:\\{event['filePath']}" else: file_path = event["filePath"] hashes: Dict[str, str] = {} if event.get("md5"): hashes = {"md5": event["md5"]} # Create the file node. file_node = File(file_path=file_path, file_name=event["fileName"], hashes=hashes) # Set the extension file_node.set_extension() # Set the process node process = Process( process_id=int(event["pid"]), process_image=event["process"], process_image_path=event["processPath"], user=event.get("username"), ) # Add a wrote edge with the contents of the file write. process.wrote[file_node].append( timestamp=int(event["event_time"]), contents=event.get("textAtLowestOffset")) # Pull out the image of the process proc_file_node = process.get_file_node() # File - (File Of) -> Process proc_file_node.file_of[process] return (file_node, process, proc_file_node)
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 make_basic_file(self, event: dict) -> Tuple[Process, File, File]: """Transforms a file based event. Support events: 1. EventTypes.FILE_DELETED 2. EventTypes.FILE_OPENED 3. EventTypes.FILE_WRITTEN 4. EventTypes.LOADED_MODULE Parameters ---------- event : dict [description] Returns ------- Tuple[Process, File, File] [description] """ process = Process( process_image=event[FieldNames.PROCESS_IMAGE], process_image_path=event[FieldNames.PROCESS_IMAGE_PATH], process_id=int(event[FieldNames.PROCESS_ID]), command_line=event[FieldNames.COMMAND_LINE], ) proc_file = process.get_file_node() proc_file.file_of[process] file_node = File( file_path=event[FieldNames.FILE_PATH], file_name=event[FieldNames.FILE_NAME], hashes=event.get(FieldNames.HASHES), ) file_node.set_extension() # Switch based on the event type event_type = event[FieldNames.EVENT_TYPE] if event_type == EventTypes.FILE_OPENED: process.accessed[file_node] elif event_type == EventTypes.FILE_WRITTEN: process.wrote[file_node] elif event_type == EventTypes.LOADED_MODULE: process.loaded[file_node] else: process.deleted[file_node] return (process, proc_file, file_node)
def make_network(self, event: dict) -> Optional[Tuple[IPAddress, Process, File]]: """Converts a network connection event into a Process, File and IP Address node. Nodes: 1. IP Address communicated to. 2. Process contacting IP. 3. File process launched from. Edges: 1. Process - (Connected To) -> IP Address 2. File - (File Of) -> Process Parameters ---------- event : dict The ipv4NetworkEvent Returns ------- Optional[Tuple[IPAddress, Process, File]] The IP Address, Process, and Process's File object. """ # Pull out the process fields. process = Process( process_image=event["process"], process_image_path=event["processPath"], process_id=int(event["pid"]), user=event.get("username", None), ) # Pull out the image of the process file_node = process.get_file_node() # File - (File Of) -> Process file_node.file_of[process] # Create the network node ip_address = IPAddress(event["remoteIP"]) # Create the connection edge # Process - (Connected To) -> IP Address process.connected_to[ip_address].append(timestamp=event["event_time"], protocol=event["protocol"], port=int(event["remotePort"])) return (ip_address, process, file_node)
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 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 make_registry( self, event: dict) -> Optional[Tuple[RegistryKey, Process, File]]: # Pull out the process fields. process = Process( process_image=event["process"], process_image_path=event["processPath"], process_id=int(event["pid"]), user=event.get("username", None), ) # Pull out the image of the process file_node = process.get_file_node() # File - (File Of) -> Process file_node.file_of[process] # RegistryKey Node Creation reg_node = RegistryKey( hive=event["hive"], key_path=event["keyPath"], key=event.get("valueName"), value=event.get("text"), value_type=event.get("valueType"), ) # Space shuttle code for the edge setting # # EventType Mappings: # 1: Value Changed # 2: Value Deleted # 3: Key Created # 4: Key Deleted # reg_event_type = str(event["eventType"]) if reg_event_type == "1": process.changed_value[reg_node].append( timestamp=event["event_time"]) elif reg_event_type == "2": process.deleted_value[reg_node].append( timestamp=event["event_time"]) elif reg_event_type == "3": process.created_key[reg_node].append(timestamp=event["event_time"]) elif reg_event_type == "4": process.deleted_key[reg_node].append(timestamp=event["event_time"]) else: logger.warn( f"Found a new registry event type with a value of {reg_event_type}: {event}" ) return (reg_node, process, file_node)
def make_dnslookup(self, event: dict) -> Optional[Tuple[Domain, Process, File]]: """Converts a dnsLookupEvent into a Domain, Process, and Process's File node. Nodes: 1. Domain looked up. 2. Process performing the lookup. 3. File the Process was launched from. Edges: 1. Process - (DNS Lookup For) -> Domain. 2. File - (FileOf) -> Process. Parameters ---------- event : dict A dnsLookupEvent Returns ------- Optional[Tuple[Domain, Process, File]] The Domain, Process, and File nodes. """ # Pull out the process fields. process = Process( process_image=event["process"], process_image_path=event["processPath"], process_id=int(event["pid"]), user=event.get("username", None), ) # Pull out the image of the process file_node = process.get_file_node() # File - (File Of) -> Process file_node.file_of[process] domain = Domain(event["hostname"]) process.dns_query_for[domain].append(timestamp=event["event_time"]) return (domain, process, file_node)
def make_http_req(self, event: dict) -> Tuple[Process, File, URI, Domain]: process = Process( process_image=event[FieldNames.PROCESS_IMAGE], process_image_path=event[FieldNames.PROCESS_IMAGE_PATH], process_id=int(event[FieldNames.PROCESS_ID]), command_line=event[FieldNames.COMMAND_LINE], ) proc_file = process.get_file_node() proc_file.file_of[process] dom = Domain(event[FieldNames.HTTP_HOST]) uri = URI(uri=event[FieldNames.URI]) uri.uri_of[dom] process.http_request_to[uri].append( method=event[FieldNames.HTTP_METHOD]) return (process, proc_file, uri, dom)
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 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)
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 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 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 make_url( self, event: dict ) -> Optional[Tuple[URI, Domain, Process, File, IPAddress]]: """Converts a URL access event and returns 5 nodes with 4 different relationships. Nodes created: 1. URI Accessed (e.g /foobar) 2. Domain Accessed (e.g omer.com) 3. Process performing URL request. 4. File object for the Process image. 5. IP Address the domain resolves to. Relationships created: 1. URI - (URI Of) -> Domain 2. Domain - (Resolves To) -> IP Address 3. Process - (`http method of event`) -> URI 4. Process - (Connected To) -> IP Address 5. File - (File Of) -> Process Parameters ---------- event : dict The urlMonitorEvent events Returns ------- Optional[Tuple[URI, Domain, Process, File, IPAddress]] 5 tuple of the nodes pulled out of the event (see function description). """ uri = URI(uri=event["requestUrl"]) domain = Domain(domain=event["hostname"]) ip_address = IPAddress(ip_address=event["remoteIpAddress"]) # Pull out the process fields. process = Process( process_image=event["process"], process_image_path=event["processPath"], command_line=event.get("processCmdLine"), process_id=int(event["pid"]), user=event.get("username", None), ) # Pull out the image of the process file_node = process.get_file_node() # File - (File Of) -> Process file_node.file_of[process] # Link up the URI and the domain # URI - (URI Of) -> Domain uri.uri_of[domain].append(timestamp=event["event_time"]) # HTTP Request to the URL from the process # Proc - (HTTP Request) -> URI process.http_request_to[uri].append( method=event.get("urlMethod"), user_agent=event.get("userAgent"), header=event.get("httpHeader"), timestamp=event["event_time"], ) # TCP Communication from process to IP of domain # Process - (Connected To) -> IP Address process.connected_to[ip_address].append(port=int(event["remotePort"]), protocol=Protocols.HTTP, timestamp=event["event_time"]) # Domain resolving to that IP # Domain - (Resolves To) -> IP Address domain.resolves_to[ip_address].append(timestamp=event["event_time"]) return (uri, domain, process, file_node, ip_address)