fixed capa scan api stuff, took a lot of stuff from the default capa render
This commit is contained in:
		
							parent
							
								
									9faa5fb170
								
							
						
					
					
						commit
						f3bb30007b
					
				
					 1 changed files with 82 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
from flask import Blueprint, request, abort
 | 
			
		||||
from flask.json import jsonify
 | 
			
		||||
from werkzeug.utils import secure_filename
 | 
			
		||||
import capa.main
 | 
			
		||||
import capa.rules
 | 
			
		||||
| 
						 | 
				
			
			@ -11,9 +12,13 @@ from pathlib import Path
 | 
			
		|||
import config
 | 
			
		||||
import json
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
import capa.render.utils as rutils
 | 
			
		||||
import capa.render.result_document as rd
 | 
			
		||||
import collections
 | 
			
		||||
from capa.render.default import find_subrule_matches
 | 
			
		||||
capa_bp = Blueprint('capa', __name__)
 | 
			
		||||
 | 
			
		||||
# This function is essentially a hacked up version of https://github.com/mandiant/capa/blob/master/capa/render/default.py
 | 
			
		||||
@capa_bp.route('/analyze', methods=['GET'])
 | 
			
		||||
def analyze_capa():
 | 
			
		||||
    file = secure_filename(request.args.get('file', ''))
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +34,82 @@ def analyze_capa():
 | 
			
		|||
    capabilities = capa.capabilities.common.find_capabilities(rules, extractor, disable_progress=True)
 | 
			
		||||
 | 
			
		||||
    meta = capa.loader.collect_metadata([], filepath, FORMAT_AUTO, OS_AUTO, [capa.main.get_default_root()/ "rules"], extractor, capabilities)
 | 
			
		||||
    doc = rd.ResultDocument.from_capa(meta, rules, capabilities.matches)
 | 
			
		||||
    caps = {}
 | 
			
		||||
    tactics = {}
 | 
			
		||||
    maec = {}
 | 
			
		||||
    objectives = {}
 | 
			
		||||
 | 
			
		||||
    subrule_matches = find_subrule_matches(doc)
 | 
			
		||||
    for rule in rutils.capability_rules(doc):
 | 
			
		||||
        if rule.meta.name in subrule_matches:
 | 
			
		||||
            # rules that are also matched by other rules should not get rendered by default.
 | 
			
		||||
            # this cuts down on the amount of output while giving approx the same detail.
 | 
			
		||||
            # see #224
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
        count = len(rule.matches)
 | 
			
		||||
        if count == 1:
 | 
			
		||||
            capability = rule.meta.name
 | 
			
		||||
        else:
 | 
			
		||||
            capability = rule.meta.name + f" ({count} matches)"
 | 
			
		||||
        caps[capability] = rule.meta.namespace
 | 
			
		||||
        for attack in rule.meta.attack:
 | 
			
		||||
            tactics[attack.tactic] = attack.technique + attack.subtechnique + attack.id.strip("[").strip("]")
 | 
			
		||||
 | 
			
		||||
    maec_categories = {
 | 
			
		||||
        "analysis_conclusion",
 | 
			
		||||
        "analysis_conclusion_ov",
 | 
			
		||||
        "malware_family",
 | 
			
		||||
        "malware_category",
 | 
			
		||||
        "malware_category_ov",
 | 
			
		||||
    }
 | 
			
		||||
    for rule in rutils.maec_rules(doc):
 | 
			
		||||
        for maec_category in maec_categories:
 | 
			
		||||
            maec_value = getattr(rule.meta.maec, maec_category, None)
 | 
			
		||||
            if maec_value:
 | 
			
		||||
                maec[maec_category] = maec_value
 | 
			
		||||
    for rule in rutils.capability_rules(doc):
 | 
			
		||||
        for mbc in rule.meta.mbc:
 | 
			
		||||
            objectives[mbc.objective] = mbc.behavior + mbc.method + mbc.id.strip("[").strip("]")
 | 
			
		||||
 | 
			
		||||
    return jsonify(capabilities=caps, tactics=tactics, maec=maec, objectives=objectives)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@capa_bp.route('/json', methods=['GET'])
 | 
			
		||||
def analyze_capa_json():
 | 
			
		||||
    file = secure_filename(request.args.get('file', ''))
 | 
			
		||||
    if file == '':
 | 
			
		||||
        abort(400)
 | 
			
		||||
    filepath = Path(path.join(config.Config.FILE_DIRECTORY, file))
 | 
			
		||||
    if not os.path.exists(filepath):
 | 
			
		||||
        print(f"Error: File not found at '{filepath}'")
 | 
			
		||||
        abort(400)
 | 
			
		||||
 | 
			
		||||
    rules = capa.rules.get_rules([Path(config.Config.RULES)])
 | 
			
		||||
    extractor = capa.loader.get_extractor(filepath, FORMAT_AUTO, OS_AUTO, capa.main.BACKEND_VIV, [], should_save_workspace=False, disable_progress=True)
 | 
			
		||||
    capabilities = capa.capabilities.common.find_capabilities(rules, extractor, disable_progress=True)
 | 
			
		||||
 | 
			
		||||
    meta = capa.loader.collect_metadata([], filepath, FORMAT_AUTO, OS_AUTO, [capa.main.get_default_root()/ "rules"], extractor, capabilities)
 | 
			
		||||
 | 
			
		||||
    return json.loads(capa.render.json.render(meta=meta, rules=rules, capabilities=capabilities.matches))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@capa_bp.route('/default', methods=['GET'])
 | 
			
		||||
def analyze_capa_default():
 | 
			
		||||
    file = secure_filename(request.args.get('file', ''))
 | 
			
		||||
    if file == '':
 | 
			
		||||
        abort(400)
 | 
			
		||||
    filepath = Path(path.join(config.Config.FILE_DIRECTORY, file))
 | 
			
		||||
    if not os.path.exists(filepath):
 | 
			
		||||
        print(f"Error: File not found at '{filepath}'")
 | 
			
		||||
        abort(400)
 | 
			
		||||
 | 
			
		||||
    rules = capa.rules.get_rules([Path(config.Config.RULES)])
 | 
			
		||||
    extractor = capa.loader.get_extractor(filepath, FORMAT_AUTO, OS_AUTO, capa.main.BACKEND_VIV, [], should_save_workspace=False, disable_progress=True)
 | 
			
		||||
    capabilities = capa.capabilities.common.find_capabilities(rules, extractor, disable_progress=True)
 | 
			
		||||
 | 
			
		||||
    meta = capa.loader.collect_metadata([], filepath, FORMAT_AUTO, OS_AUTO, [capa.main.get_default_root()/ "rules"], extractor, capabilities)
 | 
			
		||||
 | 
			
		||||
    return capa.render.default.render(meta=meta, rules=rules, capabilities=capabilities.matches)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue