def selftest_function(opts):
    """
    Placeholder for selftest function. An example use would be to test package api connectivity.
    Suggested return values are be unimplemented, success, or failure.
    """
    TEST_IP = "8.8.8.8"

    options = opts.get("fn_virustotal", {})

    reason = ""
    try:
        vt = VirusTotal(options['api_token'], options['proxies'])
        response = vt.get_ip_report(TEST_IP)

        if response and type(response) is not dict:
            state = "failure"
            reason = "no response"
        else:
            status = response.get('response_code', -1)

            if status != HTTP_OK:
                state = "failure"
                reason = state
            else:
                state = "success"
    except Exception as err:
        state = "failure"
        reason = str(err)

    result = {"state": state, "reason": reason}

    log.info(result)

    return result
Esempio n. 2
0
def virustotal(conf, ipaddress, results):
    """This method updates the network results
    with the Virustotal reports.

    Args:
        conf (dict): dict of configuration
        ipaddress (string): ip address to analyze
        results (dict): dict where will put the results

    Returns:
        This method updates the results dict given
    """

    if conf["enabled"]:
        from virus_total_apis import PublicApi as VirusTotalPublicApi
        vt = VirusTotalPublicApi(conf["api_key"])

        # Error: {u'virustotal': {'error': SSLError(SSLEOFError(8, u'EOF
        # occurred in violation of protocol (_ssl.c:590)'),)}}')
        # TypeError: SSLError(SSLEOFError(8, u'EOF occurred in violation of
        # protocol (_ssl.c:590)'),) is not JSON serializable')
        try:
            r = vt.get_ip_report(ipaddress)
            report = json.dumps(r, ensure_ascii=False)
        except TypeError:
            log.error(
                "TypeError in VirusTotal report for ip {!r}".format(ipaddress))
        else:
            if report:
                results["virustotal"] = report
    def test_get_ip_report(self):
        vt = PublicApi(API_KEY)

        try:
            print(json.dumps(vt.get_ip_report('23.6.113.133'), sort_keys=False, indent=4))
        except Exception as e:
            self.fail(e)
Esempio n. 4
0
    def test_get_ip_report(self):
        vt = PublicApi(API_KEY)

        try:
            print json.dumps(vt.get_ip_report('23.6.113.133'),
                             sort_keys=False,
                             indent=4)
        except Exception as e:
            self.fail(e)
Esempio n. 5
0
def handle_ip(actapi: act.api.Act,
              vtapi: VirusTotalApi,
              ip: Text,
              output_format: Text = "json") -> None:
    """Read IP address from stdin, query VirusTotal and
    output a JSON text readable by generic_uploaderr.py"""

    # To figure out what kind of IP address we have, let the ipaddress module
    # parse the string and test for instance type as the platform distinguishes
    # between IPv4 and IPv6 addresses.
    try:
        (ip_type, ip) = act.api.helpers.ip_obj(ip)
    except ValueError:
        return  # invalid address

    with no_ssl_verification():
        response = vtapi.get_ip_report(ip)

    try:
        results = response['results']
    except KeyError:
        logging.error("%s in handle_ip for %s", response, ip)
        sys.exit(1)

    # create a dictionary of url that is observed in relation to the address.
    urls: collections.defaultdict = collections.defaultdict(list)
    if 'detected_urls' in results:
        for u in map(urllib.parse.urlparse,
                     [x['url'] for x in results['detected_urls']]):
            urls[u.netloc].append(u)
    if 'undetected_urls' in results:
        for u in map(urllib.parse.urlparse,
                     [x[0] for x in results['undetected_urls']]):
            urls[u.netloc].append(u)

    if 'resolutions' in results:
        for resolution in results['resolutions']:
            act.api.helpers.handle_fact(actapi.fact('resolvesTo').source(
                'fqdn', resolution['hostname']).destination(ip_type, ip),
                                        output_format=output_format)
            # add all detected and undetected urls related to a given resolved hostname
            if resolution['hostname'] in urls:
                for u in urls[resolution['hostname']]:
                    add_uri(actapi, 'fqdn', resolution['hostname'], list(u))
    # if the actuall ip is part of the url, add the urls directly connected to the
    # ip.
    if ip in urls:
        for u in urls[ip]:
            add_uri(actapi, ip_type, ip, list(u))

    if 'detected_downloaded_samples' in results:
        for sample in results['detected_downloaded_samples']:

            my_uri = add_uri(actapi, ip_type, ip,
                             ['network', ip, '', '', '', ''])

            act.api.helpers.handle_fact(actapi.fact('at').source(
                'content', sample['sha256']).destination('uri', my_uri),
                                        output_format=output_format)

            act.api.helpers.handle_fact(actapi.fact('represents').source(
                'hash', sample['sha256']).destination('content',
                                                      sample['sha256']),
                                        output_format=output_format)

            handle_hexdigest(actapi,
                             vtapi,
                             sample['sha256'],
                             output_format=output_format)

    if 'detected_communicating_samples' in results:
        for sample in results['detected_communicating_samples']:
            my_uri = add_uri(actapi, ip_type, ip,
                             ['network', ip, '', '', '', ''])

            act.api.helpers.handle_fact(actapi.fact('connectsTo').source(
                'content', sample['sha256']).destination('uri', my_uri),
                                        output_format=output_format)

            act.api.helpers.handle_fact(actapi.fact('represents').source(
                'hash', sample['sha256']).destination('content',
                                                      sample['sha256']),
                                        output_format=output_format)

            handle_hexdigest(actapi,
                             vtapi,
                             sample['sha256'],
                             output_format=output_format)
Esempio n. 6
0
if x == 1:
    # try ip

    # def (ip):

    ip = raw_input("Enter Ip adress :")

    print " OTX_REPORT " * 80
    pprint.pprint(threatcrowd.ip_report(ip))

    print "**" * 80
    print "VIRUSTOTAL_REPORT " * 80

    vt = VirusTotalPublicApi(API_KEY_VT)
    response = vt.get_ip_report(ip)

    print(json.dumps(response, sort_keys=False, indent=4))

    # ###################################################################################################
    #hybrid analysis module

elif x == 2:
    # email_report(address)
    email = raw_input("Enter Email :")
    pprint.pprint(threatcrowd.email_report(email))

    print "/n"
    print "virustotal report"
    print "**" * 80
    def _virustotal_function(self, event, *args, **kwargs):
        """Function: perform different scans on the following types:
            ip addresses
            hash - this will attempt to find an existing file report on the hash
            domain
            url - this will attempt to find an existing file report on the url. If none exist, a new scan is queued
            file - this will start a new scan for the file and queue for a report later.
        """
        try:
            validateFields(('incident_id', 'vt_type'), kwargs)  # required

            # Init RequestsCommon with app.config options
            rc = RequestsCommon(opts=self.opts, function_opts=self.options)

            # Create a VirusTotal instance with the API Token and any proxies gathered by RequestsCommon
            vt = VirusTotal(self.options['api_token'], rc.get_proxies())

            # Get the function parameters:
            incident_id = kwargs.get("incident_id")  # number
            artifact_id = kwargs.get("artifact_id")  # number
            attachment_id = kwargs.get("attachment_id")  # number
            vt_type = kwargs.get("vt_type")  # text
            vt_data = kwargs.get("vt_data")  # text

            self.log = logging.getLogger(__name__)
            self.log.info("incident_id: %s", incident_id)
            self.log.info("artifact_id: %s", artifact_id)
            self.log.info("attachment_id: %s", attachment_id)
            self.log.info("vt_type: %s", vt_type)
            self.log.info("vt_data: %s", vt_data)

            yield StatusMessage("starting...")

            # determine next steps based on the API call to make
            if vt_type.lower() == 'file':
                entity = get_input_entity(get_resilient_client(self.resilient),
                                          incident_id, attachment_id,
                                          artifact_id)
                # Create a temporary file to write the binary data to.
                with tempfile.NamedTemporaryFile(
                        'w+b', delete=False) as temp_file_binary:
                    # Write binary data to a temporary file. Make sure to close the file here...this
                    # code must work on Windows and on Windows the file cannot be opened a second time
                    # While open.  Floss will open the file again to read the data, so close before
                    # calling Floss.
                    temp_file_binary.write(entity["data"])
                    temp_file_binary.close()
                    try:
                        response = vt.scan_file(temp_file_binary.name,
                                                filename=entity["name"])
                    except Exception as err:
                        raise err
                    finally:
                        os.unlink(temp_file_binary.name)

                file_result = self.return_response(response,
                                                   vt.get_file_report,
                                                   time.time())

                ## was a sha-256 returned? try an existing report first
                if file_result.get("sha256"):
                    response = vt.get_file_report(file_result.get("sha256"))
                    report_result = self.return_response(
                        response, None, time.time())

                    if report_result.get(
                            "response_code") and report_result.get(
                                "response_code") == 1:
                        result = report_result
                    else:
                        result = file_result

            elif vt_type.lower() == 'url':
                # attempt to see if a report already exists
                response = vt.get_url_report(vt_data)
                result = self.return_response(response, None, time.time())

                # check if result is not found, meaning no report exists
                if result['response_code'] == RC_NOT_FOUND:
                    response = vt.scan_url(vt_data)
                    result = self.return_response(response, vt.get_url_report,
                                                  time.time())

            elif vt_type.lower() == 'ip':
                response = vt.get_ip_report(vt_data)
                result = self.return_response(response, None, time.time())

            elif vt_type.lower() == 'domain':
                response = vt.get_domain_report(vt_data)
                result = self.return_response(response, None, time.time())

            elif vt_type.lower() == 'hash':
                response = vt.get_file_report(vt_data)
                result = self.return_response(response, None, time.time())

            else:
                raise ValueError(
                    "Unknown type field: {}. Check workflow pre-processor script."
                    .format(vt_type))

            results = {"scan": result}

            self.log.debug("scan: {}".format(results))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
Esempio n. 8
0
def handle_ip(actapi: act.api.Act,
              vtapi: VirusTotalApi,
              ip: Text,
              output_format: Text = "json") -> None:
    """Read IP address from stdin, query VirusTotal and
    output a JSON text readable by generic_uploaderr.py"""

    # To figure out what kind of IP address we have, let the ipaddress module
    # parse the string and test for instance type as the platform distinguishes
    # between IPv4 and IPv6 addresses.
    try:
        (ip_type, ip) = act.api.helpers.ip_obj(ip)
    except ValueError:
        return  # invalid address

    with no_ssl_verification():
        response = vtapi.get_ip_report(ip)

    try:
        results = response["results"]
    except KeyError:
        logging.error("%s in handle_ip for %s", response, ip)
        sys.exit(1)

    # create a dictionary of url that is observed in relation to the address.
    urls: collections.defaultdict = collections.defaultdict(list)
    if "detected_urls" in results:
        for u in map(urllib.parse.urlparse,
                     [x["url"] for x in results["detected_urls"]]):
            urls[u.netloc].append(u)
    if "undetected_urls" in results:
        for u in map(urllib.parse.urlparse,
                     [x[0] for x in results["undetected_urls"]]):
            urls[u.netloc].append(u)

    if "resolutions" in results:
        for resolution in results["resolutions"]:
            if not resolution["hostname"]:
                warning("Empty hostname in resolution: ip=%s, result=%s", ip,
                        results)
                continue
            act.api.helpers.handle_fact(
                actapi.fact("resolvesTo").source(
                    "fqdn", resolution["hostname"]).destination(ip_type, ip),
                output_format=output_format,
            )
            # add all detected and undetected urls related to a given resolved hostname
            if resolution["hostname"] in urls:
                for u in urls[resolution["hostname"]]:
                    add_uri(actapi, "fqdn", resolution["hostname"], list(u))
    # if the actuall ip is part of the url, add the urls directly connected to the
    # ip.
    if ip in urls:
        for u in urls[ip]:
            add_uri(actapi, ip_type, ip, list(u))

    if "detected_downloaded_samples" in results:
        for sample in results["detected_downloaded_samples"]:

            my_uri = add_uri(actapi, ip_type, ip,
                             ["network", ip, "", "", "", ""])

            act.api.helpers.handle_fact(
                actapi.fact("at").source("content",
                                         sample["sha256"]).destination(
                                             "uri", my_uri),
                output_format=output_format,
            )

            act.api.helpers.handle_fact(
                actapi.fact("represents").source("hash",
                                                 sample["sha256"]).destination(
                                                     "content",
                                                     sample["sha256"]),
                output_format=output_format,
            )

            handle_hexdigest(actapi,
                             vtapi,
                             sample["sha256"],
                             output_format=output_format)

    if "detected_communicating_samples" in results:
        for sample in results["detected_communicating_samples"]:
            my_uri = add_uri(actapi, ip_type, ip,
                             ["network", ip, "", "", "", ""])

            act.api.helpers.handle_fact(
                actapi.fact("connectsTo").source("content",
                                                 sample["sha256"]).destination(
                                                     "uri", my_uri),
                output_format=output_format,
            )

            act.api.helpers.handle_fact(
                actapi.fact("represents").source("hash",
                                                 sample["sha256"]).destination(
                                                     "content",
                                                     sample["sha256"]),
                output_format=output_format,
            )

            handle_hexdigest(actapi,
                             vtapi,
                             sample["sha256"],
                             output_format=output_format)
class VirusTotal:
    OutputDir = None
    HTMLHeader = None
    APIKeys = None
    APIKEY = None
    APIKeysNumber = None
    APIKeyIndex = None
    DisabledAttr = None
    MaxResults = None
    AttrSubstitution = None
    Order = None
    VTInstance = None
    Persistence = None
    Host = None
    Database = None
    UsernameR = None
    PasswordR = None
    UsernameRW = None
    PasswordRW = None
    Input = None
    IP = None
    GeneralOutput = None
    DBR = None
    DBRW = None
    CursorR = None
    CursorRW = None

    def init(self):
        config = None
        try:
            with open('config.json', 'r') as configFile:
                configContent = configFile.read()
                config = json.loads(configContent)
        except json.decoder.JSONDecodeError:
            print("Problem occured while parsing the config.json file")
            exit()
        if config == None:
            print("Problem occured while parsing the config.json file")
            exit()
        self.OutputDir = config['General']['OutputDir']
        self.HTMLHeader = config['General']['HTMLHeader']
        self.TablesClass = config['General']['TablesClass']
        self.APIKeys = config['VirusTotal']['APIKeys']
        self.loadRecordsTmp()
        self.APIKEY = self.APIKeys[self.APIKeyIndex]
        self.APIKeysNumber = len(self.APIKeys)
        self.DisabledAttr = config['VirusTotal']['DisabledAttr']
        self.MaxResults = config['VirusTotal']['MaxResults']
        self.AttrSubstitution = config['VirusTotal']['AttrSubstitution']
        self.Order = config['VirusTotal']['Order']
        self.VTInstance = VirusTotalPublicApi(self.APIKEY)
        self.Persistence = config['VirusTotal']['Persistence']
        self.Host = config['VirusTotal']['PersistenceCredentials']['host']
        self.Database = config['VirusTotal']['PersistenceCredentials'][
            'database']
        self.UsernameR = config['VirusTotal']['PersistenceCredentials'][
            'username_r']
        self.PasswordR = config['VirusTotal']['PersistenceCredentials'][
            'password_r']
        self.UsernameRW = config['VirusTotal']['PersistenceCredentials'][
            'username_rw']
        self.PasswordRW = config['VirusTotal']['PersistenceCredentials'][
            'password_rw']
        self.Input = config['VirusTotal']['Input']
        self.GeneralOutput = config['VirusTotal']['GeneralOutput']
        self.HTML = ""
        self.IMG = ""
        if self.Persistence == PERSISTENCE_TYPE_SQL:
            self.initSQL()

    def initSQL(self):
        self.DBR = mysql.connector.connect(host=self.Host,
                                           user=self.UsernameR,
                                           passwd=self.PasswordR,
                                           database=self.Database)
        self.CursorR = self.DBR.cursor(dictionary=True)
        self.DBRW = mysql.connector.connect(host=self.Host,
                                            user=self.UsernameRW,
                                            passwd=self.PasswordRW,
                                            database=self.Database)
        self.CursorRW = self.DBRW.cursor(dictionary=True)

    def resetSQL(self):
        self.CursorR.close()
        self.CursorRW.close()
        self.DBR.close()
        self.DBRW.close()
        self.initSQL()

    def preHandling(self):
        self.number = {}
        self.history = {}

    def loadRecordsTmp(self):
        try:
            with open('.records.tmp', 'r') as recordsTmpFile:
                recordsTmpContent = recordsTmpFile.read()
                recordsTmp = json.loads(recordsTmpContent)
                self.APIKeyIndex = recordsTmp["APIKeyIndex"]
        except Exception:
            self.APIKeyIndex = 0
            recordsTmp = {"APIKeyIndex": self.APIKeyIndex}
            with open('.records.tmp', 'w') as recordsTmpFile:
                json.dump(recordsTmp, recordsTmpFile)

    def updateAPIKeyIndex(self):
        try:
            with open('.records.tmp', 'r') as recordsTmpFile:
                recordsTmpContent = recordsTmpFile.read()
                recordsTmp = json.loads(recordsTmpContent)
        except Exception:
            recordsTmp = {"APIKeyIndex": self.APIKeyIndex}
        recordsTmp["APIKeyIndex"] = self.APIKeyIndex
        with open('.records.tmp', 'w') as recordsTmpFile:
            json.dump(recordsTmp, recordsTmpFile)

    def updateVTInstance(self):
        self.APIKeyIndex = (self.APIKeyIndex + 1) % self.APIKeysNumber
        self.updateAPIKeyIndex()
        self.APIKEY = self.APIKeys[self.APIKeyIndex]
        self.VTInstance = VirusTotalPublicApi(self.APIKEY)

    def getIPReportAPI(self):
        if self.Input == INPUT_TYPE_FILE:
            return self.getIPReportAPIFile()
        elif self.Input == INPUT_TYPE_ARGUMENT:
            return self.getIPReportAPIArgument()
        return {}

    def getIPReportAPIArgument(self):
        ips = "\n".join(self.IP.split(" ")).strip()
        return self.getVTReport(ips)

    def getIPReportAPIFile(self):
        result = {}
        with open("input_ip.txt") as file:
            ips = file.read().strip()
            result = self.getVTReport(ips)
        return result

    def getVTReport(self, ips):
        result = {}
        for ip in ips.split("\n"):
            response = self.VTInstance.get_ip_report(ip)
            self.updateVTInstance()
            if response['response_code'] == 200:
                result[ip] = response['results']
        return result

    def setHTMLDomain(self, domain):
        return '<a href="https://www.virustotal.com/gui/domain/' + domain + '/details">' + domain + '</a>'

    def formatArrayDateDomain(self, ip_report_api, attr):
        result = []
        count = self.MaxResults[attr] if self.MaxResults[attr] else -1
        tmp = sorted(ip_report_api[attr], key=lambda i: i['last_resolved'])
        for elem in list(reversed(tmp)):
            if count == 0:
                break
            obj = {'Date resolved': "", 'Domain': ""}
            obj['Date resolved'] = elem['last_resolved']
            obj['Domain'] = self.setHTMLDomain(elem['hostname'])
            result.append(obj)
            count = count - 1
        return result

    def setHTMLFileHash(self, hash):
        return '<a href="https://www.virustotal.com/gui/file/' + hash + '/detection">' + hash + '</a>'

    def formatArrayDateScoreHash(self, ip_report_api, attr):
        result = []
        count = self.MaxResults[attr] if self.MaxResults[attr] else -1
        for elem in list(ip_report_api[attr]):
            if count == 0:
                break
            obj = {'Scanned': "", 'Detections': "", 'File Hash (sha256)': ""}
            obj['Scanned'] = elem['date']
            if elem['positives'] == 0:
                color = "green"
            else:
                color = "red"
            obj['Detections'] = '<span style="color:' + color + '">' + str(
                elem['positives']) + "</span>/" + str(elem['total'])
            #response=self.VTInstance.get_file_report(elem['sha256'])
            #print(response)
            obj['File Hash (sha256)'] = self.setHTMLFileHash(elem['sha256'])
            result.append(obj)
            count = count - 1
        return result

    def setHTMLURL(self, url, url_hash):
        if url_hash == False:
            url_hash = hashlib.sha256(url.encode('utf-8')).hexdigest()
        return '<a href="https://www.virustotal.com/gui/url/' + url_hash + '/detection">' + url + '</a>'

    def formatArrayDateScoreURL(self, ip_report_api, attr):
        result = []
        count = self.MaxResults[attr] if self.MaxResults[attr] else -1
        for elem in list(ip_report_api[attr]):
            if count == 0:
                break
            obj = {'Scanned': "", 'Detections': "", 'URL': ""}
            obj['Scanned'] = elem['scan_date']
            if elem['positives'] == 0:
                color = "green"
            else:
                color = "red"
            obj['Detections'] = '<span style="color:' + color + '">' + str(
                elem['positives']) + "</span>/" + str(elem['total'])
            #response=self.VTInstance.get_file_report(elem['sha256'])
            #print(response)
            obj['URL'] = self.setHTMLURL(elem['url'], False)
            result.append(obj)
            count = count - 1
        return result

    def formatArrayDateScoreURLnum(self, ip_report_api, attr):
        result = []
        count = self.MaxResults[attr] if self.MaxResults[attr] else -1
        for elem in list(ip_report_api[attr]):
            if count == 0:
                break
            obj = {'Scanned': "", 'Detections': "", 'URL': ""}
            obj['Scanned'] = elem[4]
            if elem[2] == 0:
                color = "green"
            else:
                color = "red"
            obj['Detections'] = '<span style="color:' + color + '">' + str(
                elem[2]) + "</span>/" + str(elem[3])
            #response=self.VTInstance.get_file_report(elem['sha256'])
            #print(response)
            obj['URL'] = self.setHTMLURL(elem[0], elem[1])
            result.append(obj)
            count = count - 1
        return result

    def getNumberMalicious(self, ip_report_api, attr):
        result = [
            d for d in ip_report_api[attr]
            if ('positives' in d and d['positives'] > 0) or (
                'positives' not in d and d[2] > 0)
        ]
        return result

    def getNumberBenign(self, ip_report_api, attr):
        result = [
            d for d in ip_report_api[attr]
            if ('positives' in d and d['positives'] == 0) or (
                'positives' not in d and d[2] == 0)
        ]
        return result

    def updateScoredAttr(self, attr, verdict, result):
        self.number[attr] = self.number[attr] if attr in self.number else {}
        self.number[attr][verdict] = result

    def getIPReportFiltered(self, ip_report_api):
        result = {}
        for attr in list(ip_report_api):
            if (attr in self.DisabledAttr):
                None  #del result[attr]
            elif attr == 'resolutions':
                newAttr = self.AttrSubstitution[
                    attr] if attr in self.AttrSubstitution else attr
                self.history[newAttr] = len(ip_report_api[attr])
                result[newAttr] = self.formatArrayDateDomain(
                    ip_report_api, attr)
            elif attr == 'detected_referrer_samples':
                newAttr = self.AttrSubstitution[
                    attr] if attr in self.AttrSubstitution else attr
                tmp = self.formatArrayDateScoreHash(ip_report_api, attr)
                self.updateScoredAttr(
                    newAttr, "malicious",
                    len(self.getNumberMalicious(ip_report_api, attr)))
                if newAttr in result:
                    result[newAttr] = tmp + result[newAttr]
                else:
                    result[newAttr] = tmp
            elif attr == 'undetected_referrer_samples':
                newAttr = self.AttrSubstitution[
                    attr] if attr in self.AttrSubstitution else attr
                tmp = self.formatArrayDateScoreHash(ip_report_api, attr)
                self.updateScoredAttr(
                    newAttr, "benign",
                    len(self.getNumberBenign(ip_report_api, attr)))
                if newAttr in result:
                    result[newAttr] = result[newAttr] + tmp
                else:
                    result[newAttr] = tmp
            elif attr == 'detected_downloaded_samples':
                newAttr = self.AttrSubstitution[
                    attr] if attr in self.AttrSubstitution else attr
                tmp = self.formatArrayDateScoreHash(ip_report_api, attr)
                self.updateScoredAttr(
                    newAttr, "malicious",
                    len(self.getNumberMalicious(ip_report_api, attr)))
                if newAttr in result:
                    result[newAttr] = tmp + result[newAttr]
                else:
                    result[newAttr] = tmp
            elif attr == 'undetected_downloaded_samples':
                newAttr = self.AttrSubstitution[
                    attr] if attr in self.AttrSubstitution else attr
                tmp = self.formatArrayDateScoreHash(ip_report_api, attr)
                self.updateScoredAttr(
                    newAttr, "benign",
                    len(self.getNumberBenign(ip_report_api, attr)))
                if newAttr in result:
                    result[newAttr] = result[newAttr] + tmp
                else:
                    result[newAttr] = tmp
            elif attr == 'detected_communicating_samples':
                newAttr = self.AttrSubstitution[
                    attr] if attr in self.AttrSubstitution else attr
                tmp = self.formatArrayDateScoreHash(ip_report_api, attr)
                self.updateScoredAttr(
                    newAttr, "malicious",
                    len(self.getNumberMalicious(ip_report_api, attr)))
                if newAttr in result:
                    result[newAttr] = tmp + result[newAttr]
                else:
                    result[newAttr] = tmp
            elif attr == 'undetected_communicating_samples':
                newAttr = self.AttrSubstitution[
                    attr] if attr in self.AttrSubstitution else attr
                tmp = self.formatArrayDateScoreHash(ip_report_api, attr)
                self.updateScoredAttr(
                    newAttr, "benign",
                    len(self.getNumberBenign(ip_report_api, attr)))
                if newAttr in result:
                    result[newAttr] = result[newAttr] + tmp
                else:
                    result[newAttr] = tmp
            elif attr == 'detected_urls':
                newAttr = self.AttrSubstitution[
                    attr] if attr in self.AttrSubstitution else attr
                tmp = self.formatArrayDateScoreURL(ip_report_api, attr)
                self.updateScoredAttr(
                    newAttr, "malicious",
                    len(self.getNumberMalicious(ip_report_api, attr)))
                if newAttr in result:
                    result[newAttr] = tmp + result[newAttr]
                else:
                    result[newAttr] = tmp
            elif attr == 'undetected_urls':
                newAttr = self.AttrSubstitution[
                    attr] if attr in self.AttrSubstitution else attr
                tmp = self.formatArrayDateScoreURLnum(ip_report_api, attr)
                self.updateScoredAttr(
                    newAttr, "benign",
                    len(self.getNumberBenign(ip_report_api, attr)))
                if newAttr in result:
                    result[newAttr] = result[newAttr] + tmp
                else:
                    result[newAttr] = tmp
            else:
                result[attr] = ip_report_api[attr]
        return result

    def getOrdered(self, ip_report_filtered):
        result = {}
        #We order the Order's elements in the begining of the result list
        for elem in self.Order:
            #If the substitued element index exists in the Order list, then it should be ordered
            if elem in self.AttrSubstitution and self.AttrSubstitution[
                    elem] and self.AttrSubstitution[
                        elem] in ip_report_filtered and ip_report_filtered[
                            self.AttrSubstitution[elem]]:
                #Ordered elements should not duplicated
                if self.AttrSubstitution[elem] not in result:
                    result[self.AttrSubstitution[elem]] = ip_report_filtered[
                        self.AttrSubstitution[elem]]
            #If the index is not substitutable and if the index exists in the Order list, then it should be ordered
            elif elem in ip_report_filtered and ip_report_filtered[elem]:
                #Ordered elements should not duplicated
                if elem not in result:
                    result[elem] = ip_report_filtered[elem]
        #Then, we add the non ordered elements since they are not blacklisted so of the Order list is missing some elements, they will be added in the end of the result list
        for attr in list(ip_report_filtered):
            #Ordered elements should not duplicated
            if attr not in result:
                result[attr] = ip_report_filtered[attr]
        return result

    def getHTML(self, ip_report_filtered, ip):
        html = ""
        html = html + "<h3>IP Address: " + ip + "</h3>"
        for elem in list(ip_report_filtered):
            html = html + "<h4>" + elem + "</h4>"
            if elem in self.number and self.number[elem]:
                malicious = self.number[elem][
                    "malicious"] if "malicious" in self.number[elem] else 0
                benign = self.number[elem][
                    "benign"] if "benign" in self.number[elem] else 0
                html = html + "<h5>(<span style='color:red'>" + str(
                    malicious
                ) + " malicious</span> and <span style='color:green'>" + str(
                    benign) + " benign</span>)</h5>"
            if elem in self.history and self.history[elem]:
                history = self.history[elem]
                html = html + "<h5>(" + str(history) + " found)</h5>"
            html = html + json2html.convert(
                json=ip_report_filtered[elem],
                table_attributes='class="' + self.TablesClass + '"',
                escape=False)
        self.HTML = self.HTML + html
        html = '<html><head>' + self.HTMLHeader + '</head><body>' + html
        html = html + '</body></html>'
        output = self.OutputDir + "/"
        #print(html)
        #imgkit.from_string(html, output+ip+'-VirusTotal.jpg')
        with open(output + ip + '-VirusTotal.html', 'w') as HTMLFile:
            HTMLFile.write(html)
        #self.IMG=self.IMG+"<img src='"+ip+"-VirusTotal.jpg'><br/>"

    def updateGeneralHTML(self):
        HTMLPrefix = '<html><head>' + self.HTMLHeader + '</head><body>'
        self.HTML = HTMLPrefix + self.HTML + '</body></html>'
        self.IMG = HTMLPrefix + self.IMG + '</body></html>'
        output = self.OutputDir + "/"
        with open(output + 'latest-HTML-VirusTotal.html', 'w') as HTMLFile:
            HTMLFile.write(self.HTML)
        with open(output + 'latest-IMG-VirusTotal.html', 'w') as HTMLFile:
            HTMLFile.write(self.IMG)

    def findPersistedIP(self, ip_id, table_name):
        self.CursorR.execute("SELECT * FROM " + table_name + " where ip_id='" +
                             str(ip_id) + "'")
        return self.CursorR.fetchall()

    def persistResolutions(self, selected_ips, ip_report_filtered):
        attr = "resolutions"
        table_name = "vt_scanned_resolutions_table"
        newAttr = self.AttrSubstitution[
            attr] if attr in self.AttrSubstitution else attr
        selected_domains = self.findPersistedIP(selected_ips[0]['id'],
                                                table_name)
        selected_domains_filtered = []
        for selected_domain in selected_domains:
            selected_domains_filtered.append(selected_domain['domain'])
        if newAttr in ip_report_filtered:
            for domain in ip_report_filtered[newAttr]:
                if domain['Domain'] not in selected_domains_filtered:
                    try:
                        self.CursorRW.execute(
                            "INSERT INTO " + table_name +
                            " (ip_id,domain,scanned_time) VALUES ('" +
                            str(selected_ips[0]['id']) + "','" +
                            domain['Domain'] + "','" +
                            domain['Date resolved'] + "')")
                        self.DBRW.commit()
                        self.resetSQL()
                    except Exception as e:
                        print("INSERT INTO " + table_name +
                              " (ip_id,domain,scanned_time) VALUES ('" +
                              str(selected_ips[0]['id']) + "','" +
                              domain['Domain'] + "','" +
                              domain['Date resolved'] + "')")
                        print("EXCEPTION: ", e)
                        self.resetSQL()

    def persistURLs(self, selected_ips, ip_report_filtered):
        attr = "detected_urls"
        table_name = "vt_scanned_urls_table"
        newAttr = self.AttrSubstitution[
            attr] if attr in self.AttrSubstitution else attr
        selected_urls = self.findPersistedIP(selected_ips[0]['id'], table_name)
        selected_urls_filtered = []
        for selected_url in selected_urls:
            selected_urls_filtered.append(selected_url['url'])
        if newAttr in ip_report_filtered:
            for url in ip_report_filtered[newAttr]:
                print(url['URL'])
                if url['URL'] not in selected_urls_filtered:
                    try:
                        self.CursorRW.execute(
                            "INSERT INTO " + table_name +
                            " (ip_id,url,detections,scanned_time) VALUES ('" +
                            str(selected_ips[0]['id']) + "','" + url['URL'] +
                            "','" + url['Detections'] + "','" +
                            url['Scanned'] + "')")
                        self.DBRW.commit()
                        self.resetSQL()
                    except Exception as e:
                        print(
                            "INSERT INTO " + table_name +
                            " (ip_id,url,detections,scanned_time) VALUES ('" +
                            str(selected_ips[0]['id']) + "','" + url['URL'] +
                            "','" + url['Detections'] + "','" +
                            url['Scanned'] + "')")
                        print("EXCEPTION: ", e)
                        self.resetSQL()

    def persistHashs(self, selected_ips, ip_report_filtered, attr, table_name):
        newAttr = self.AttrSubstitution[
            attr] if attr in self.AttrSubstitution else attr
        selected_hashs = self.findPersistedIP(selected_ips[0]['id'],
                                              table_name)
        selected_hashs_filtered = []
        for selected_hash in selected_hashs:
            selected_hashs_filtered.append(selected_hash['hash'])
        if newAttr in ip_report_filtered:
            for hash in ip_report_filtered[newAttr]:
                if hash['File Hash (sha256)'] not in selected_hashs_filtered:
                    try:
                        self.CursorRW.execute(
                            "INSERT INTO " + table_name +
                            " (ip_id,hash,detections,scanned_time) VALUES ('" +
                            str(selected_ips[0]['id']) + "','" +
                            hash['File Hash (sha256)'] + "','" +
                            hash['Detections'] + "','" + hash['Scanned'] +
                            "')")
                        self.DBRW.commit()
                        self.resetSQL()
                    except Exception as e:
                        print(
                            "INSERT INTO " + table_name +
                            " (ip_id,hash,detections,scanned_time) VALUES ('" +
                            str(selected_ips[0]['id']) + "','" +
                            hash['File Hash (sha256)'] + "','" +
                            hash['Detections'] + "','" + hash['Scanned'] +
                            "')")
                        print("EXCEPTION: ", e)
                        self.resetSQL()

    def persist(self, ip_report_api, ip_report_filtered):
        self.CursorR.execute(
            "SELECT * FROM vt_scanned_ips_table where scanned_ip='" +
            ip_report_api + "'")
        selected_ips = self.CursorR.fetchall()
        if len(selected_ips) == 0:
            self.CursorRW.execute(
                "INSERT INTO vt_scanned_ips_table (scanned_ip,last_scanned_time) VALUES ('"
                + ip_report_api + "','" + str(int(time.time())) + "')")
            self.DBRW.commit()
            self.resetSQL()
            self.CursorR.execute(
                "SELECT * FROM vt_scanned_ips_table where scanned_ip='" +
                ip_report_api + "'")
            selected_ips = self.CursorR.fetchall()
        self.persistResolutions(selected_ips, ip_report_filtered)
        self.persistURLs(selected_ips, ip_report_filtered)
        attr = "detected_referrer_samples"
        table_name = "vt_scanned_referring_files_table"
        self.persistHashs(selected_ips, ip_report_filtered, attr, table_name)
        attr = "detected_downloaded_samples"
        table_name = "vt_scanned_downloads_table"
        self.persistHashs(selected_ips, ip_report_filtered, attr, table_name)
        attr = "detected_communicating_samples"
        table_name = "vt_scanned_communicating_files_table"
        self.persistHashs(selected_ips, ip_report_filtered, attr, table_name)
Esempio n. 10
0
class VirusTotalAnalyzer(Analyzer):

    def __init__(self):
        Analyzer.__init__(self)
        self.service = self.get_param('config.service', None, 'Service parameter is missing')
        self.virustotal_key = self.get_param('config.key', None, 'Missing VirusTotal API key')
        self.polling_interval = self.get_param('config.polling_interval', 60)
        self.proxies = self.get_param('config.proxy', None)
        self.vt = VirusTotalPublicApi(self.virustotal_key, self.proxies)

    def wait_file_report(self, id):
        results = self.check_response(self.vt.get_file_report(id))
        code = results.get('response_code', None)
        if code == 1:
            self.report(results)
        else:
            time.sleep(self.polling_interval)
            self.wait_file_report(id)

    def wait_url_report(self, id):
        results = self.check_response(self.vt.get_url_report(id))
        code = results.get('response_code', None)
        if code == 1 and (results.get('scan_id') == id):
            self.report(results)
        else:
            time.sleep(self.polling_interval)
            self.wait_url_report(id)

    def check_response(self, response):
        if type(response) is not dict:
            self.error('Bad response : ' + str(response))
        status = response.get('response_code', -1)
        if status == 204:
            self.error('VirusTotal api rate limit exceeded (Status 204).')
        if status != 200:
            self.error('Bad status : ' + str(status))
        results = response.get('results', {})
        if 'Missing IP address' in results.get('verbose_msg', ''):
            results['verbose_msg'] = 'IP address not available in VirusTotal'
        return results

        # 0 => not found
        # -2 => in queue
        # 1 => ready

    def read_scan_response(self, response, func):
        results = self.check_response(response)
        code = results.get('response_code', None)
        scan_id = results.get('scan_id', None)
        if code == 1 and scan_id is not None:
            func(scan_id)
        else:
            self.error('Scan not found')

    def summary(self, raw):
        taxonomies = []
        level = "info"
        namespace = "VT"
        predicate = "GetReport"
        value = "0"

        if self.service == "scan":
            predicate = "Scan"

        result = {
            "has_result": True
        }

        if raw["response_code"] != 1:
            result["has_result"] = False

        result["positives"] = raw.get("positives", 0)
        result["total"] = raw.get("total", 0)

        if "scan_date" in raw:
            result["scan_date"] = raw["scan_date"]

        if self.service == "get":
            if "scans" in raw:
                result["scans"] = len(raw["scans"])
                value = "{}/{}".format(result["positives"], result["total"])
                if result["positives"] == 0:
                    level = "safe"
                elif result["positives"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

            if "resolutions" in raw:
                result["resolutions"] = len(raw["resolutions"])
                value = "{} resolution(s)".format(result["resolutions"])
                if result["resolutions"] == 0:
                    level = "safe"
                elif result["resolutions"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"
            if "detected_urls" in raw:
                result["detected_urls"] = len(raw["detected_urls"])
                value = "{} detected_url(s)".format(result["detected_urls"])
                if result["detected_urls"] == 0:
                    level = "safe"
                elif result["detected_urls"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

            if "detected_downloaded_samples" in raw:
                result["detected_downloaded_samples"] = len(
                    raw["detected_downloaded_samples"])

        if self.service == "scan":
            if "scans" in raw:
                result["scans"] = len(raw["scans"])
                value = "{}/{}".format(result["positives"], result["total"])
                if result["positives"] == 0:
                    level = "safe"
                elif result["positives"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

        taxonomies.append(self.build_taxonomy(level, namespace, predicate, value))
        return {"taxonomies": taxonomies}

    def run(self):
        if self.service == 'scan':
            if self.data_type == 'file':
                filename = self.get_param('filename', 'noname.ext')
                filepath = self.get_param('file', None, 'File is missing')
                self.read_scan_response(
                    self.vt.scan_file(filepath, from_disk=True, filename=filename),
                    self.wait_file_report
                )
            elif self.data_type == 'url':
                data = self.get_param('data', None, 'Data is missing')
                self.read_scan_response(
                    self.vt.scan_url(data), self.wait_url_report)
            else:
                self.error('Invalid data type')
        elif self.service == 'get':
            if self.data_type == 'domain':
                data = self.get_param('data', None, 'Data is missing')
                self.report(self.check_response(
                    self.vt.get_domain_report(data)))
            elif self.data_type == 'fqdn':
                data = self.get_param('data', None, 'Data is missing')
                self.report(self.check_response(
                    self.vt.get_domain_report(data)))
            elif self.data_type == 'ip':
                data = self.get_param('data', None, 'Data is missing')
                self.report(self.check_response(self.vt.get_ip_report(data)))
            elif self.data_type == 'file':
                hashes = self.get_param('attachment.hashes', None)
                if hashes is None:
                    filepath = self.get_param('file', None, 'File is missing')
                    hash = hashlib.sha256(open(filepath, 'rb').read()).hexdigest()
                else:
                    # find SHA256 hash
                    hash = next(h for h in hashes if len(h) == 64)

                self.report(self.check_response(self.vt.get_file_report(hash)))
            elif self.data_type == 'hash':
                data = self.get_param('data', None, 'Data is missing')
                self.report(self.check_response(self.vt.get_file_report(data)))
            elif self.data_type == 'url':
                data = self.get_param('data', None, 'Data is missing')
                self.report(self.check_response(self.vt.get_url_report(data)))
            else:
                self.error('Invalid data type')
        else:
            self.error('Invalid service')
Esempio n. 11
0
class VirusTotalAnalyzer(Analyzer):
    def __init__(self):
        Analyzer.__init__(self)
        self.service = self.get_param("config.service", None,
                                      "Service parameter is missing")
        self.virustotal_key = self.get_param("config.key", None,
                                             "Missing VirusTotal API key")
        self.polling_interval = self.get_param("config.polling_interval", 60)
        self.rescan_hash_older_than_days = self.get_param(
            "config.rescan_hash_older_than_days", None)
        self.highlighted_antivirus = self.get_param(
            "config.highlighted_antivirus", None)
        self.download_sample = self.get_param("config.download_sample", False)
        self.download_sample_if_highlighted = self.get_param(
            "config.download_sample_if_highlighted", False)
        self.obs_path = None
        self.proxies = self.get_param("config.proxy", None)
        if (self.download_sample or self.download_sample_if_highlighted
                or self.service == "download"):
            self.vt_pay = PrivateApi(self.virustotal_key, self.proxies)
        self.vt = PublicApi(self.virustotal_key, self.proxies)

    def get_file(self, hash):
        self.obs_path = "{}/{}".format(tempfile.gettempdir(), hash)
        response = self.vt_pay.get_file(hash)
        if response.get("response_code", None) == 200:
            with open(self.obs_path, "wb") as f:
                f.write(response["results"])
            kind = filetype.guess(self.obs_path)
            if kind and kind.extension != None:
                os.rename(self.obs_path,
                          "{}.{}".format(self.obs_path, kind.extension))
                self.obs_path = "{}.{}".format(self.obs_path, kind.extension)

    def wait_file_report(self, id):
        results = self.check_response(self.vt.get_file_report(id))
        code = results.get("response_code", None)
        if code == 1:
            if self.data_type == "hash" and (
                    self.download_sample or
                (self.download_sample_if_highlighted
                 and self.highlighted_antivirus and any([
                     results.get("scans", {}).get(av, {}).get(
                         "detected", None) == False
                     for av in self.highlighted_antivirus
                 ]))):
                self.get_file(self.get_param("data", None, "Data is missing"))
            self.report(results)
        else:
            time.sleep(self.polling_interval)
            self.wait_file_report(id)

    def wait_url_report(self, id):
        results = self.check_response(self.vt.get_url_report(id))
        code = results.get("response_code", None)
        if code == 1 and (results.get("scan_id") == id):
            self.report(results)
        else:
            time.sleep(self.polling_interval)
            self.wait_url_report(id)

    def check_response(self, response):
        if type(response) is not dict:
            self.error("Bad response : " + str(response))
        status = response.get("response_code", -1)
        if status == 204:
            self.error("VirusTotal api rate limit exceeded (Status 204).")
        if status != 200:
            self.error("Bad status : " + str(status))
        results = response.get("results", {})
        if "Missing IP address" in results.get("verbose_msg", ""):
            results["verbose_msg"] = "IP address not available in VirusTotal"
        return results

        # 0 => not found
        # -2 => in queue
        # 1 => ready

    def read_scan_response(self, response, func):
        results = self.check_response(response)
        code = results.get("response_code", None)
        scan_id = results.get("scan_id", None)
        if code == 1 and scan_id is not None:
            func(scan_id)
        else:
            self.error("Scan not found")

    def artifacts(self, raw):
        artifacts = []
        if self.obs_path:
            tags = []
            # This will work only in scan/rescan workflow, not in download only
            if self.highlighted_antivirus:
                for av in self.highlighted_antivirus:
                    detected = raw.get("scans",
                                       {}).get(av, {}).get("detected", None)
                    if detected == False:
                        tags.append("to_{}".format(av))
            artifacts.append(
                self.build_artifact("file", self.obs_path, tags=tags))
        return artifacts

    def summary(self, raw):
        taxonomies = []
        level = "info"
        namespace = "VT"
        predicate = "GetReport"
        value = "0"

        if self.service == "scan":
            predicate = "Scan"
        elif self.service == "rescan":
            predicate = "Rescan"
        elif self.service == "download":
            return {"taxonomies": taxonomies}

        result = {"has_result": True}

        if raw["response_code"] != 1:
            result["has_result"] = False

        result["positives"] = raw.get("positives", 0)
        result["total"] = raw.get("total", 0)

        if "scan_date" in raw:
            result["scan_date"] = raw["scan_date"]

        if self.service == "get":
            if "scans" in raw:
                result["scans"] = len(raw["scans"])
                value = "{}/{}".format(result["positives"], result["total"])
                if result["positives"] == 0:
                    level = "safe"
                elif result["positives"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

            if "resolutions" in raw:
                result["resolutions"] = len(raw["resolutions"])
                value = "{} resolution(s)".format(result["resolutions"])
                if result["resolutions"] == 0:
                    level = "safe"
                elif result["resolutions"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

            if "detected_urls" in raw:
                result["detected_urls"] = len(raw["detected_urls"])
                value = "{} detected_url(s)".format(result["detected_urls"])
                if result["detected_urls"] == 0:
                    level = "safe"
                elif result["detected_urls"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

            if "detected_downloaded_samples" in raw:
                result["detected_downloaded_samples"] = len(
                    raw["detected_downloaded_samples"])

        if self.service in ["scan", "rescan"]:
            if "scans" in raw:
                result["scans"] = len(raw["scans"])
                value = "{}/{}".format(result["positives"], result["total"])
                if result["positives"] == 0:
                    level = "safe"
                elif result["positives"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

        taxonomies.append(
            self.build_taxonomy(level, namespace, predicate, value))

        if self.highlighted_antivirus:
            for av in self.highlighted_antivirus:
                detected = raw.get("scans", {}).get(av,
                                                    {}).get("detected", None)
                if detected == False:
                    taxonomies.append(
                        self.build_taxonomy("info", namespace, av,
                                            "Not detected!"))

        return {"taxonomies": taxonomies}

    def run(self):
        if self.service == "scan":
            if self.data_type == "file":
                filename = self.get_param("filename", "noname.ext")
                filepath = self.get_param("file", None, "File is missing")
                self.read_scan_response(
                    self.vt.scan_file(filepath,
                                      from_disk=True,
                                      filename=filename),
                    self.wait_file_report,
                )
            elif self.data_type == "url":
                data = self.get_param("data", None, "Data is missing")
                self.read_scan_response(self.vt.scan_url(data),
                                        self.wait_url_report)
            else:
                self.error("Invalid data type")

        elif self.service == "rescan":
            if self.data_type == "hash":
                data = self.get_param("data", None, "Data is missing")
                self.read_scan_response(self.vt.rescan_file(data),
                                        self.wait_file_report)
            else:
                self.error("Invalid data type")

        elif self.service == "download":
            if self.data_type == "hash":
                data = self.get_param("data", None, "Data is missing")
                self.get_file(data)
                self.report({"message": "file downloaded"})

        elif self.service == "get":
            if self.data_type == "domain":
                data = self.get_param("data", None, "Data is missing")
                results = self.check_response(self.vt.get_domain_report(data))

            elif self.data_type == "fqdn":
                data = self.get_param("data", None, "Data is missing")
                results = self.check_response(self.vt.get_domain_report(data))

            elif self.data_type == "ip":
                data = self.get_param("data", None, "Data is missing")
                results = self.check_response(self.vt.get_ip_report(data))

            elif self.data_type == "file":
                hashes = self.get_param("attachment.hashes", None)
                if hashes is None:
                    filepath = self.get_param("file", None, "File is missing")
                    hash = hashlib.sha256(open(filepath,
                                               "rb").read()).hexdigest()
                else:
                    hash = next(h for h in hashes if len(h) == 64)
                results = self.check_response(self.vt.get_file_report(hash))

            elif self.data_type == "hash":
                data = self.get_param("data", None, "Data is missing")
                results = self.check_response(self.vt.get_file_report(data))

            elif self.data_type == "url":
                data = self.get_param("data", None, "Data is missing")
                results = self.check_response(self.vt.get_url_report(data))
            else:
                self.error("Invalid data type")

            # if aged and enabled rescan
            if self.data_type == "hash" and self.rescan_hash_older_than_days:
                if (datetime.strptime(results["scan_date"],
                                      "%Y-%m-%d %H:%M:%S") - datetime.now()
                    ).days > self.rescan_hash_older_than_days:
                    self.read_scan_response(self.vt.rescan_file(data),
                                            self.wait_file_report)

            # download if hash, dangerous and not seen by av
            if (self.data_type == "hash"
                    and (results.get("response_code", None) == 1)
                    and (results.get("positives", 0) >= 5)
                    and (self.download_sample or
                         (self.download_sample_if_highlighted
                          and self.highlighted_antivirus and any([
                              results.get("scans", {}).get(av, {}).get(
                                  "detected", None) == False
                              for av in self.highlighted_antivirus
                          ])))):
                self.get_file(data)
            self.report(results)

        else:
            self.error("Invalid service")
Esempio n. 12
0
class VT(object):
    """
    Class to hold VirusTotal items.
    """

    #
    # FUNCTIONS
    #
    """
    Sets up a VirusTotal object with the public api.
    """
    def __init__(self, vtpublicapi):
        self.vtpublicapi = vtpublicapi
        self.vt = VirusTotalPublicApi(self.vtpublicapi)

    def add_headers(self, inputheaders):
        """
        Adds appropriate headers to input list.
        """
        inputheaders.append('VirusTotal Detected URLs')
        inputheaders.append('VirusTotal Detected Communicating Samples')
        inputheaders.append('VirusTotal Detected Downloaded Samples')
        inputheaders.append('VirusTotal Link')

    def add_row(self, host, inputrow):
        """
        Adds the pulled data to the input row.
        """

        vtdetectedurls = vtdetectedcommunicatingsamples = \
            vtdetecteddownloadedsamples = vturl = ''

        if libs.network.IsIPv4(host):
            vtresponse = self.vt.get_ip_report(host)
            while "response_code" not in vtresponse or \
                    (vtresponse["response_code"] != 200 and
                     vtresponse["response_code"] != 403):
                time.sleep(60)  # Sleep for the API throttling
                vtresponse = self.vt.get_ip_report(host)
            if "results" not in vtresponse:
                vtdetectedurls = "INVALID API KEY"
            elif "detected_urls" in vtresponse["results"]:
                vtdetectedurls = str(
                    len(vtresponse["results"]["detected_urls"]))
            else:
                vtdetectedurls = str(0)
            if "results" not in vtresponse:
                vtdetectedcommunicatingsamples = "INVALID API KEY"
            elif "detected_communicating_samples" in vtresponse["results"]:
                vtdetectedcommunicatingsamples = str(
                    len(vtresponse["results"]["detected_"
                                              "communicating_"
                                              "samples"]))
            else:
                vtdetectedcommunicatingsamples = str(0)
            vturl = "https://www.virustotal.com/en/ip-address/{}/information/"\
                    .format(host)
        else:
            vtresponse = self.vt.get_domain_report(host)
            while "response_code" not in vtresponse or \
                    (vtresponse["response_code"] != 200 and
                     vtresponse["response_code"] != 403):
                time.sleep(60)  # Sleep for the API throttling
                vtresponse = self.vt.get_domain_report(host)
            if "results" not in vtresponse:
                vtdetectedurls = "INVALID API KEY"
            elif "detected_urls" in vtresponse["results"]:
                vtdetectedurls = str(
                    len(vtresponse["results"]["detected_urls"]))
            else:
                vtdetectedurls = str(0)
            if "results" not in vtresponse:
                vtdetectedcommunicatingsamples = "INVALID API KEY"
            elif "detected_communicating_samples" in vtresponse["results"]:
                vtdetectedcommunicatingsamples = str(
                    len(vtresponse["results"]["detected_"
                                              "communicating_"
                                              "samples"]))
            else:
                vtdetectedcommunicatingsamples = str(0)
            if "results" not in vtresponse:
                vtdetecteddownloadedsamples = "INVALID API KEY"
            elif "detected_downloaded_samples" in vtresponse["results"]:
                vtdetecteddownloadedsamples = str(
                    len(vtresponse["results"]["detected_"
                                              "downloaded_"
                                              "samples"]))
            else:
                vtdetecteddownloadedsamples = str(0)
            vturl = "https://www.virustotal.com/en/domain/{}/information/"\
                    .format(host)

        inputrow.append(vtdetectedurls)
        inputrow.append(vtdetectedcommunicatingsamples)
        inputrow.append(vtdetecteddownloadedsamples)
        inputrow.append(vturl)