Esempio n. 1
0
    def test_send_analysis_by_file_with_zip_password_adds_zip_extension(self):
        # Arrange
        with responses.RequestsMock() as mock:
            mock.add('POST',
                     url=self.full_url + '/analyze',
                     status=201,
                     json={'result_url': 'a/sd/asd'})
            mock.add('GET',
                     url=self.full_url + '/analyses/asd',
                     status=200,
                     json={
                         'result': 'report',
                         'status': 'succeeded'
                     })
            analysis = FileAnalysis(file_path='a', zip_password='******')

            with patch(self.patch_prop, mock_open(read_data='data')):
                # Act
                analysis.send(wait=True)

            # Assert
            self.assertEqual(analysis.status, consts.AnalysisStatusCode.FINISH)
            self.assertEqual(analysis.result(), 'report')
            request_body = mock.calls[0].request.body.decode()
            self.assertTrue(
                'Content-Disposition: form-data; name="zip_password"\r\n\r\nasd'
                in request_body)
            self.assertTrue(
                'Content-Disposition: form-data; name="file"; filename="a.zip"'
                in request_body)
Esempio n. 2
0
    def test_send_analysis_by_file_with_disable_unpacking(self):
        # Arrange
        with responses.RequestsMock() as mock:
            mock.add('POST',
                     url=self.full_url + '/analyze',
                     status=201,
                     json={'result_url': 'a/sd/asd'})
            mock.add('GET',
                     url=self.full_url + '/analyses/asd',
                     status=200,
                     json={
                         'result': 'report',
                         'status': 'succeeded'
                     })
            analysis = FileAnalysis(file_path='a',
                                    disable_dynamic_unpacking=True,
                                    disable_static_unpacking=True)
            with patch(self.patch_prop, mock_open(read_data='data')):
                # Act
                analysis.send(wait=True)

            # Assert
            self.assertEqual(analysis.status, consts.AnalysisStatusCode.FINISH)
            self.assertEqual(analysis.result(), 'report')
            request_body = mock.calls[0].request.body.decode()
            self.assertTrue(
                'Content-Disposition: form-data; name="disable_static_extraction"\r\n\r\nTrue'
                in request_body)
            self.assertTrue(
                'Content-Disposition: form-data; name="disable_dynamic_execution"\r\n\r\nTrue'
                in request_body)
Esempio n. 3
0
def get_analysis_family(analysis: FileAnalysis,
                        software_type_priorities: List[str],
                        should_use_largest_families: bool = True) -> Tuple[Optional[str], Optional[int]]:
    result = analysis.result()
    family_name = result.get('family_name')
    if family_name:
        reused_gene_count = get_analysis_family_by_family_id(analysis, result['family_id'])
        return family_name, reused_gene_count

    if should_use_largest_families:
        largest_family_by_software_type = find_largest_family(analysis)
        for software_type in software_type_priorities:
            if software_type in largest_family_by_software_type:
                family = largest_family_by_software_type[software_type]
                return family['family_name'], family['reused_gene_count']

    return None, None
Esempio n. 4
0
def get_analysis_summary_metadata(analysis: FileAnalysis,
                                  use_hash_link: bool = False,
                                  should_use_largest_families: bool = True) -> Dict[str, any]:
    result = analysis.result()
    verdict = result['verdict'].lower()
    sub_verdict = result['sub_verdict'].lower()
    analysis_url = f"{ANALYZE_URL}/files/{result['sha256']}?private=true" if use_hash_link else result['analysis_url']
    main_family = None
    gene_count = None
    iocs = None
    dynamic_ttps = None
    related_samples_unique_count = None

    software_type_priorities_by_verdict = {
        'malicious': ['malware', 'malicious_packer'],
        'trusted': ['application', 'library', 'interpreter', 'installer'],
        'suspicious': ['administration_tool', 'packer']
    }

    software_type_priorities = software_type_priorities_by_verdict.get(verdict)
    if software_type_priorities:
        main_family, gene_count = get_analysis_family(analysis, software_type_priorities, should_use_largest_families)

    if verdict in ('malicious', 'suspicious'):
        iocs = analysis.iocs
        dynamic_ttps = analysis.dynamic_ttps

    related_samples = [sub_analysis.get_account_related_samples(wait=True) for sub_analysis in
                       analysis.get_sub_analyses()]
    if related_samples:
        related_samples_unique_count = len({analysis['analysis']['sha256'] for analysis in
                                            itertools.chain.from_iterable(
                                                sample.result['related_samples'] for sample in related_samples
                                                if sample is not None)})

    return {
        'verdict': verdict,
        'sub_verdict': sub_verdict,
        'analysis_url': analysis_url,
        'main_family': main_family,
        'gene_count': gene_count,
        'iocs': iocs,
        'dynamic_ttps': dynamic_ttps,
        'related_samples_unique_count': related_samples_unique_count
    }
Esempio n. 5
0
    def test_send_analysis_by_file_and_get_report(self):
        # Arrange
        with responses.RequestsMock() as mock:
            mock.add('POST',
                     url=self.full_url + '/analyze',
                     status=201,
                     json={'result_url': 'a/sd/asd'})
            mock.add('GET',
                     url=self.full_url + '/analyses/asd',
                     status=200,
                     json={
                         'result': 'report',
                         'status': 'succeeded'
                     })
            analysis = FileAnalysis(file_path='a')
            with patch(self.patch_prop, mock_open(read_data='data')):
                # Act
                analysis.send(wait=True)

        # Assert
        self.assertEqual(analysis.status, consts.AnalysisStatusCode.FINISH)
        self.assertEqual(analysis.result(), 'report')
Esempio n. 6
0
 def test_analysis_get_report_for_not_finish_analyze_raise_error(self):
     # Arrange
     analysis = FileAnalysis(file_hash='a')
     # Act + Assert
     with self.assertRaises(errors.ReportDoesNotExistError):
         analysis.result()
def send_file_with_wait(file_path):
    api.set_global_api('<api_key>')
    analysis = FileAnalysis(file_path=file_path)
    analysis.send(wait=True)
    pprint(analysis.result())
def send_file_without_wait(file_path):
    api.set_global_api('<api_key>')
    analysis = FileAnalysis(file_path=file_path)
    analysis.send()
    analysis.wait_for_completion()
    pprint(analysis.result())
Esempio n. 9
0
def get_analysis_summary(analysis: FileAnalysis,
                         no_emojis: bool = False,
                         short: bool = False,
                         use_hash_link=False) -> str:
    result = analysis.result()

    metadata = analysis.get_root_analysis().metadata
    verdict = result['verdict'].lower()
    sub_verdict = result['sub_verdict'].lower()
    emoji = ''

    note = _get_title(short)

    if not no_emojis:
        emoji = get_emoji(verdict)

    if verdict == 'malicious':
        main_family, gene_count = get_analysis_family(analysis, [])
    elif verdict == 'trusted':
        main_family, gene_count = get_analysis_family(analysis, ['application', 'library', 'interpreter', 'installer'])
    elif verdict == 'suspicious':
        main_family, gene_count = get_analysis_family(analysis, ['administration_tool', 'packer'])
    else:
        main_family = None
        gene_count = None

    note = f'{note}{emoji} {verdict.capitalize()}'

    if verdict in ('suspicious', 'unknown'):
        note = f'{note} - {sub_verdict.replace("_", " ").title()}'
    if main_family:
        note = f'{note} - {main_family}'
        if gene_count and not short:
            note = f'{note} ({gene_count} shared code genes)'

    if use_hash_link:
        analysis_url = f"{ANALYZE_URL}/files/{result['sha256']}?private=true"
    else:
        analysis_url = result['analysis_url']

    if short:
        return f'{note} > {analysis_url}'

    note = f'{note}\n\nSize: {human_readable_size(metadata["size_in_bytes"])}\n'

    if 'file_type' in metadata:
        note = f'{note}File type: {metadata["file_type"]}\n'

    if verdict in ('malicious', 'suspicious'):
        iocs = analysis.iocs

        if iocs:
            iocs_count = 0
            files = iocs.get('files')
            network = iocs.get('network')

            if files:
                iocs_count += len(files)

            if network:
                iocs_count += len(network)

            if iocs_count > 1:
                note = f'{note}IOCs: {iocs_count} Indicators\n'

        if analysis.dynamic_ttps:
            note = f'{note}TTPs: {len(analysis.dynamic_ttps)} techniques\n'

    related_samples = [sub_analysis.get_account_related_samples(wait=True) for sub_analysis in
                       analysis.get_sub_analyses()]
    if related_samples:
        related_samples_unique_count = len({analysis['analysis']['sha256'] for analysis in
                                            itertools.chain.from_iterable(
                                                sample.result['related_samples'] for sample in related_samples
                                                if sample is not None)})
        note = f'{note}Similar previous uploads: {related_samples_unique_count} files \n'

    note = (f'{note}\nFull report:\n'
            f'{"" if no_emojis else get_emoji("result_url")} {analysis_url}')

    return note
def analysis_by_hash_with_wait(file_hash: str):
    api.set_global_api('<api_key>')
    analysis = FileAnalysis(file_hash=file_hash)
    analysis.send(wait=True)
    pprint(analysis.result())
def analysis_by_hash_without_wait(file_hash: str):
    api.set_global_api('<api_key>')
    analysis = FileAnalysis(file_hash=file_hash)
    analysis.send()
    analysis.wait_for_completion()
    pprint(analysis.result())
def analysis_by_hash_with_wait_timeout(file_hash: str):
    api.set_global_api('<api_key>')
    analysis = FileAnalysis(file_hash=file_hash)
    analysis.send(wait=True, wait_timeout=datetime.timedelta(minutes=1))
    pprint(analysis.result())
Esempio n. 13
0
def send_analysis(analysis: FileAnalysis):
    analysis.send(wait=True)
    return analysis.result()