コード例 #1
0
ファイル: sysmon_transformer.py プロジェクト: zulu8/beagle
    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)
コード例 #2
0
    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)
コード例 #3
0
    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)
コード例 #4
0
    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)
コード例 #5
0
ファイル: pcap_transformer.py プロジェクト: zulu8/beagle
    def transform(self, event: Dict) -> Optional[Tuple[Node, ...]]:

        event_type = event["event_type"]

        # Skip all ether events, no src/dst IP
        if event_type in ["Ether", "IP"
                          ] or "src_ip" not in event or "dst_ip" not in event:
            return None

        src = IPAddress(ip_address=event["src_ip"], mac=event["src_mac"])
        dst = IPAddress(ip_address=event["dst_ip"], mac=event["dst_mac"])

        src.connected_to[dst].append(
            port=event["dport"],
            protocol=event["protocol"],
            payload=event["payload"],
            timestamp=event["timestamp"],
        )

        if event_type == "HTTPRequest":
            dom = Domain(event["http_dest"])
            uri = URI(event["uri"])
            src.http_request_to[uri].append(method=event["http_method"],
                                            timestamp=event["timestamp"])

            dom.resolves_to[dst]

            uri.uri_of[dom]
            return (src, dst, dom, uri)

        if event_type == "DNS":
            if event["qname"][-1] == ".":
                event["qname"] = event["qname"][:-1]
            dom = Domain(event["qname"])

            src.dns_query_for[dom].append(record_type=event["qtype"],
                                          timestamp=event["timestamp"])
            if "qanswer" in event:
                ip = IPAddress(event["qanswer"])
                dom.resolves_to[ip].append(timestamp=event["timestamp"])
                return (src, dom, ip, dst)

            return (src, dom, dst)

        return (src, dst)
コード例 #6
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)
コード例 #7
0
    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)
コード例 #8
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)
コード例 #9
0
    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)
コード例 #10
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)