def test_handle_artefacts(artefact_list, expected_result,
                           dummy_request_class):
     from assemblyline_v4_service.common.dynamic_service_helper import SandboxOntology
     r = dummy_request_class()
     o = SandboxOntology()
     actual_result = o.handle_artefacts(artefact_list, r)
     assert actual_result == expected_result
예제 #2
0
    def _process_extraction_info(self, processes: List[Dict[str, Any]],
                                 process_path_set: Set[str],
                                 command_line_set: Set[str],
                                 so: SandboxOntology) -> None:
        """
        This method handles the processing of the extraction info process details
        :param processes: A list of processes
        :param process_path_set: A set containing process paths
        :param command_line_set: A set containing command lines
        :param so: the sandbox ontology object
        :return: None
        """
        for item in processes:
            p = so.create_process(
                pid=item["process_id"],
                image=item["process_path"],
                ppid=item["parent_process_id"],
            )
            process_path_set.add(item["process_path"])
            so.add_process(p)

            if item["process_path"] != item["module_path"]:
                self.log.debug(
                    f"Investigate! process_path: {item['process_path']} != module_path: {item['module_path']}"
                )
                process_path_set.add(item["module_path"])
                command_line = f"{item['process_path']} {item['module_path']}"
                command_line_set.add(command_line)
                so.update_process(command_line=command_line,
                                  pid=item["process_id"],
                                  start_time=float("-inf"))
    def test_handle_artefact(artefact, expected_result_section_title):
        from assemblyline_v4_service.common.dynamic_service_helper import SandboxOntology, Artefact
        from assemblyline_v4_service.common.result import ResultSection

        if artefact is None:
            with pytest.raises(Exception):
                SandboxOntology._handle_artefact(artefact, None)
            return

        expected_result_section = None
        if expected_result_section_title is not None:
            expected_result_section = ResultSection(
                expected_result_section_title)
            expected_result_section.add_tag("dynamic.process.file_name",
                                            artefact["path"])

        parent_result_section = ResultSection("blah")
        a = Artefact(name=artefact["name"],
                     path=artefact["path"],
                     description=artefact["description"],
                     to_be_extracted=artefact["to_be_extracted"])
        SandboxOntology._handle_artefact(a, parent_result_section)
        if len(parent_result_section.subsections) > 0:
            actual_result_section = parent_result_section.subsections[0]
        else:
            actual_result_section = None

        if expected_result_section is None and actual_result_section is None:
            assert True
        else:
            assert check_section_equality(actual_result_section,
                                          expected_result_section)
 def test_get_process_tree_with_signatures(process_list, signatures,
                                           expected_result):
     from assemblyline_v4_service.common.dynamic_service_helper import SandboxOntology
     o = SandboxOntology(process_list)
     if process_list and signatures and process_list[0][
             "pid"] != signatures[0]["pid"]:
         with pytest.raises(Exception):
             o.get_process_tree_with_signatures(signatures=signatures)
     else:
         actual_result = o.get_process_tree_with_signatures(
             signatures=signatures)
         assert actual_result == expected_result
 def test_validate_artefacts(artefact_list):
     from assemblyline_v4_service.common.dynamic_service_helper import SandboxOntology, Artefact
     actual_validated_artefact_list = SandboxOntology._validate_artefacts(
         artefact_list)
     if artefact_list is None:
         artefact_list = []
     for index, artefact in enumerate(artefact_list):
         expected_artefact = Artefact(
             name=artefact["name"],
             path=artefact["path"],
             description=artefact["description"],
             to_be_extracted=artefact["to_be_extracted"])
         assert check_artefact_equality(
             expected_artefact, actual_validated_artefact_list[index])
예제 #6
0
    def _handle_subanalyses(self, request: ServiceRequest, sha256: str,
                            analysis_id: str, file_verdict_map: Dict[str, str],
                            parent_section: ResultSection) -> None:
        """
        This method handles the subanalyses for a given analysis ID
        :param request: The service request object
        :param sha256: The hash of the given file
        :param analysis_id: The ID for the analysis which we will be retrieving
        :param file_verdict_map: A map of sha256s representing a file's
        contents, and the verdict for that file
        :param parent_result_section: The result section that the network
        result section will be added to, if applicable
        :return: None
        """
        so = SandboxOntology()

        # This boolean is used to determine if we should try to download another file
        can_we_download_files = True

        # These sets will be used as we work through the process trees
        process_path_set = set()
        command_line_set = set()

        # Now let's get into the subanalyses for this sample
        sub_analyses = self.client.get_sub_analyses_by_id(analysis_id)

        for sub in sub_analyses:
            sub_analysis_id = sub["sub_analysis_id"]

            # Get the extraction info, which is basically the details of how the subanalysis object came to be
            extraction_info = sub.pop("extraction_info", None)

            # Processes is only present when the sample has undergone dynamic execution
            if extraction_info and "processes" not in extraction_info:
                extraction_info = None

            code_reuse = self.client.get_sub_analysis_code_reuse_by_id(
                analysis_id, sub_analysis_id)

            if code_reuse:
                families = code_reuse.pop("families", [])
            else:
                families = []

            if not families and not extraction_info:
                # Otherwise, boring!
                continue

            if families and not any(family["reused_gene_count"] > 1
                                    for family in families):
                # Most likely a false positive
                continue

            ###
            # If we have gotten to this point, then the sub analysis is worth reporting
            ###

            extraction_method = sub["source"].replace("_", " ")

            if extraction_method != "root":
                sub_kv_section = ResultKeyValueSection(
                    f"Subanalysis report for {sub['sha256']}, extracted via {extraction_method}"
                )
            else:
                sub_kv_section = ResultKeyValueSection(
                    f"Subanalysis report for {sub['sha256']}")

            metadata = self.client.get_sub_analysis_metadata_by_id(
                analysis_id, sub_analysis_id)
            processed_subanalysis = self._process_details(
                metadata.copy(), UNINTERESTING_SUBANALYSIS_KEYS)
            sub_kv_section.update_items(processed_subanalysis)
            parent_section.add_subsection(sub_kv_section)

            if code_reuse:
                code_reuse_kv_section = ResultKeyValueSection(
                    "Code reuse detected")
                code_reuse_kv_section.update_items(code_reuse)
                sub_kv_section.add_subsection(code_reuse_kv_section)

            sub_sha256 = sub["sha256"]
            if families:
                self._process_families(families, sub_sha256, file_verdict_map,
                                       sub_kv_section)

            if extraction_info:
                self._process_extraction_info(extraction_info["processes"],
                                              process_path_set,
                                              command_line_set, so)

            # Setting a heuristic here or downloading the file would be redundant if the hash matched the original file
            if sub_sha256 != sha256:
                self._set_heuristic_by_verdict(
                    sub_kv_section, file_verdict_map.get(sub_sha256))

                if can_we_download_files:
                    file_was_downloaded = self.client.download_file_by_sha256(
                        sub_sha256, self.working_directory)
                    if file_was_downloaded:
                        path = f"{self.working_directory}/{sub_sha256}.sample"
                        request.add_extracted(
                            path,
                            f"{sub_sha256}.sample",
                            f"Extracted via {extraction_method}",
                        )
                        self.log.debug(
                            f"Added {sub_sha256}.sample as an extracted file.")
                    else:
                        can_we_download_files = False

        process_tree_section = so.get_process_tree_result_section()
        for process_path in process_path_set:
            process_tree_section.add_tag("dynamic.process.file_name",
                                         process_path)
        for command_line in command_line_set:
            process_tree_section.add_tag("dynamic.process.command_line",
                                         command_line)
        if process_tree_section.body:
            parent_section.add_subsection(process_tree_section)
 def test_get_process_tree(process_list, expected_result):
     from assemblyline_v4_service.common.dynamic_service_helper import SandboxOntology
     o = SandboxOntology(process_list)
     actual_result = o.get_process_tree()
     assert actual_result == expected_result
 def test_convert_processes_dict_to_tree(processes_dict, expected_result):
     from assemblyline_v4_service.common.dynamic_service_helper import SandboxOntology
     actual_result = SandboxOntology._convert_processes_dict_to_tree(
         processes_dict)
     assert expected_result == actual_result
 def test_init(events, expected_events):
     from assemblyline_v4_service.common.dynamic_service_helper import SandboxOntology
     so = SandboxOntology(events=events)
     assert so.events == expected_events
 def test_get_events(events, expected_result):
     from assemblyline_v4_service.common.dynamic_service_helper import SandboxOntology
     so = SandboxOntology(events=events)
     actual_result = so.get_events()
     assert actual_result == expected_result
    def test_process_extraction_info(intezer_static_class_instance):
        from assemblyline_v4_service.common.dynamic_service_helper import SandboxOntology
        so = SandboxOntology()

        processes = [
            {
                "process_id": 123,
                "process_path": "blah.exe",
                "parent_process_id": 321,
                "module_path": "blah.exe"
            },
            {
                "process_id": 124,
                "process_path": "blah2.exe",
                "parent_process_id": 321,
                "module_path": "blah2.dll,blah"
            },
            {
                "process_id": 123,
                "process_path": "blah.exe",
                "parent_process_id": 321,
                "module_path": "blah.dll,blah"
            },
            {
                "process_id": 321,
                "process_path": "blah3.exe",
                "parent_process_id": 322,
                "module_path": "blah3.exe"
            },
        ]
        process_path_set = set()
        command_line_set = set()
        correct_processes = [
            {
                "start_time": float("-inf"),
                "end_time": float("inf"),
                "objectid": {
                    "tag": "blah.exe",
                    "treeid": None,
                    "processtree": None,
                    "time_observed": float("-inf")
                },
                "pobjectid": {
                    "tag": "blah3.exe",
                    "treeid": None,
                    "processtree": None,
                    "time_observed": float("-inf")
                },
                "pimage": "blah3.exe",
                "pcommand_line": None,
                "ppid": 321,
                "pid": 123,
                "image": "blah.exe",
                "command_line": "blah.exe blah.dll,blah",
                "integrity_level": None,
                "image_hash": None,
                "original_file_name": None,
            },
            {
                "start_time": float("-inf"),
                "end_time": float("inf"),
                "objectid": {
                    "tag": "blah2.exe",
                    "treeid": None,
                    "processtree": None,
                    "time_observed": float("-inf")
                },
                "pobjectid": {
                    "tag": "blah3.exe",
                    "treeid": None,
                    "processtree": None,
                    "time_observed": float("-inf")
                },
                "pimage": "blah3.exe",
                "pcommand_line": None,
                "ppid": 321,
                "pid": 124,
                "image": "blah2.exe",
                "command_line": "blah2.exe blah2.dll,blah",
                "integrity_level": None,
                "image_hash": None,
                "original_file_name": None,
            },
            {
                "start_time": float("-inf"),
                "end_time": float("inf"),
                "objectid": {
                    "tag": "blah3.exe",
                    "treeid": None,
                    "processtree": None,
                    "time_observed": float("-inf")
                },
                "pobjectid": {
                    "tag": None,
                    "treeid": None,
                    "processtree": None,
                    "time_observed": None
                },
                "pimage": None,
                "pcommand_line": None,
                "ppid": 322,
                "pid": 321,
                "image": "blah3.exe",
                "command_line": None,
                "integrity_level": None,
                "image_hash": None,
                "original_file_name": None,
            },
        ]
        intezer_static_class_instance._process_extraction_info(
            processes, process_path_set, command_line_set, so)
        for index, process in enumerate(so.get_processes()):
            process_as_primitives = process.as_primitives()
            process_as_primitives["objectid"].pop("guid")
            process_as_primitives["pobjectid"].pop("guid")
            assert process_as_primitives == correct_processes[index]
        assert process_path_set == {
            "blah.dll,blah", "blah2.dll,blah", "blah2.exe", "blah.exe",
            "blah3.exe"
        }
        assert command_line_set == {
            "blah.exe blah.dll,blah", "blah2.exe blah2.dll,blah"
        }