mirror of https://github.com/MISP/misp-modules
Merge branch 'master' of github.com:MISP/misp-modules
commit
2d9b0cd172
|
@ -45,6 +45,7 @@ For more information: [Extending MISP with Python modules](https://www.circl.lu/
|
||||||
### Export modules
|
### Export modules
|
||||||
|
|
||||||
* [CEF](misp_modules/modules/export_mod/cef_export.py) module to export Common Event Format (CEF).
|
* [CEF](misp_modules/modules/export_mod/cef_export.py) module to export Common Event Format (CEF).
|
||||||
|
* [GoAML export](misp_modules/modules/export_mod/goamlexport.py) module to export in GoAML format.
|
||||||
* [Lite Export](misp_modules/modules/export_mod/liteexport.py) module to export a lite event.
|
* [Lite Export](misp_modules/modules/export_mod/liteexport.py) module to export a lite event.
|
||||||
* [Simple PDF export](misp_modules/modules/export_mod/pdfexport.py) module to export in PDF (required: asciidoctor-pdf).
|
* [Simple PDF export](misp_modules/modules/export_mod/pdfexport.py) module to export in PDF (required: asciidoctor-pdf).
|
||||||
* [ThreatConnect](misp_modules/modules/export_mod/threat_connect_export.py) module to export in ThreatConnect CSV format.
|
* [ThreatConnect](misp_modules/modules/export_mod/threat_connect_export.py) module to export in ThreatConnect CSV format.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import json
|
import json
|
||||||
from ._dnsdb_query.dnsdb_query import DnsdbClient
|
from ._dnsdb_query.dnsdb_query import DnsdbClient, QueryError
|
||||||
|
|
||||||
|
|
||||||
misperrors = {'error': 'Error'}
|
misperrors = {'error': 'Error'}
|
||||||
|
@ -41,6 +41,7 @@ def handler(q=False):
|
||||||
|
|
||||||
|
|
||||||
def lookup_name(client, name):
|
def lookup_name(client, name):
|
||||||
|
try:
|
||||||
res = client.query_rrset(name) # RRSET = entries in the left-hand side of the domain name related labels
|
res = client.query_rrset(name) # RRSET = entries in the left-hand side of the domain name related labels
|
||||||
for item in res:
|
for item in res:
|
||||||
if item.get('rrtype') in ['A', 'AAAA', 'CNAME']:
|
if item.get('rrtype') in ['A', 'AAAA', 'CNAME']:
|
||||||
|
@ -50,17 +51,25 @@ def lookup_name(client, name):
|
||||||
for i in item.get('rdata'):
|
for i in item.get('rdata'):
|
||||||
# grab email field and replace first dot by @ to convert to an email address
|
# grab email field and replace first dot by @ to convert to an email address
|
||||||
yield(i.split(' ')[1].rstrip('.').replace('.', '@', 1))
|
yield(i.split(' ')[1].rstrip('.').replace('.', '@', 1))
|
||||||
# res = client.query_rdata_name(name) # RDATA = entries on the right-hand side of the domain name related labels
|
except QueryError as e:
|
||||||
# for item in res:
|
pass
|
||||||
# if item.get('rrtype') in ['A', 'AAAA', 'CNAME']:
|
|
||||||
# yield(item.get('rrname').rstrip('.'))
|
try:
|
||||||
|
res = client.query_rdata_name(name) # RDATA = entries on the right-hand side of the domain name related labels
|
||||||
|
for item in res:
|
||||||
|
if item.get('rrtype') in ['A', 'AAAA', 'CNAME']:
|
||||||
|
yield(item.get('rrname').rstrip('.'))
|
||||||
|
except QueryError as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def lookup_ip(client, ip):
|
def lookup_ip(client, ip):
|
||||||
|
try:
|
||||||
res = client.query_rdata_ip(ip)
|
res = client.query_rdata_ip(ip)
|
||||||
for item in res:
|
for item in res:
|
||||||
print(item)
|
|
||||||
yield(item['rrname'].rstrip('.'))
|
yield(item['rrname'].rstrip('.'))
|
||||||
|
except QueryError as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def introspection():
|
def introspection():
|
||||||
|
|
|
@ -45,7 +45,7 @@ def findAll(data, keys):
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def valid_email(email):
|
def valid_email(email):
|
||||||
return bool(re.search(r"^[\w\.\+\-]+\@[\w]+\.[a-z]{2,3}$", email))
|
return bool(re.search(r"[a-zA-Z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?", email))
|
||||||
|
|
||||||
def handler(q=False):
|
def handler(q=False):
|
||||||
if q is False:
|
if q is False:
|
||||||
|
|
|
@ -14,7 +14,7 @@ extensions = {"ip1": "ipr/%s",
|
||||||
sys.path.append('./')
|
sys.path.append('./')
|
||||||
|
|
||||||
misperrors = {'error': 'Error'}
|
misperrors = {'error': 'Error'}
|
||||||
mispattributes = {'input': ['ip-src','ip-dst' 'vulnerability', 'md5', 'sha1', 'sha256'],
|
mispattributes = {'input': ['ip-src', 'ip-dst', 'vulnerability', 'md5', 'sha1', 'sha256'],
|
||||||
'output': ['ip-src', 'ip-dst', 'text', 'domain']}
|
'output': ['ip-src', 'ip-dst', 'text', 'domain']}
|
||||||
|
|
||||||
# possible module-types: 'expansion', 'hover' or both
|
# possible module-types: 'expansion', 'hover' or both
|
||||||
|
|
|
@ -5,7 +5,8 @@ from collections import defaultdict, Counter
|
||||||
misperrors = {'error': 'Error'}
|
misperrors = {'error': 'Error'}
|
||||||
moduleinfo = {'version': '1', 'author': 'Christian Studer',
|
moduleinfo = {'version': '1', 'author': 'Christian Studer',
|
||||||
'description': 'Export to GoAML',
|
'description': 'Export to GoAML',
|
||||||
'module-type': ['export']}
|
'module-type': ['export'],
|
||||||
|
'require_standard_format': True}
|
||||||
moduleconfig = ['rentity_id']
|
moduleconfig = ['rentity_id']
|
||||||
mispattributes = {'input': ['MISPEvent'], 'output': ['xml file']}
|
mispattributes = {'input': ['MISPEvent'], 'output': ['xml file']}
|
||||||
outputFileExtension = "xml"
|
outputFileExtension = "xml"
|
||||||
|
@ -13,30 +14,37 @@ responseType = "application/xml"
|
||||||
|
|
||||||
objects_to_parse = ['transaction', 'bank-account', 'person', 'entity', 'geolocation']
|
objects_to_parse = ['transaction', 'bank-account', 'person', 'entity', 'geolocation']
|
||||||
|
|
||||||
goAMLmapping = {'bank-account': 't_account', 'institution-code': 'institution_code', 'iban': 'iban',
|
goAMLmapping = {'bank-account': {'bank-account': 't_account', 'institution-name': 'institution_name',
|
||||||
'swift': 'swift', 'branch': 'branch', 'non-banking-institution': 'non_bank_institution',
|
'institution-code': 'institution_code', 'iban': 'iban', 'swift': 'swift',
|
||||||
'account': 'account', 'currency-code': 'currency_code', 'account-name': 'account_name',
|
'branch': 'branch', 'non-banking-institution': 'non_bank_institution',
|
||||||
'client-number': 'client_number', 'personal-account-type': 'personal_account_type',
|
'account': 'account', 'currency-code': 'currency_code',
|
||||||
'opened': 'opened', 'closed': 'closed', 'balance': 'balance', 'status-code': 'status_code',
|
'account-name': 'account_name', 'client-number': 'client_number',
|
||||||
'beneficiary': 'beneficiary', 'beneficiary-comment': 'beneficiary_comment', 'comments': 'comments',
|
'personal-account-type': 'personal_account_type', 'opened': 'opened',
|
||||||
'person': 't_person', 'text': 'comments', 'first-name': 'first_name', 'middle-name': 'middle_name',
|
'closed': 'closed', 'balance': 'balance', 'status-code': 'status_code',
|
||||||
'last-name': 'last_name', 'mothers-name': 'mothers_name', 'title': 'title', 'alias': 'alias',
|
'beneficiary': 'beneficiary', 'beneficiary-comment': 'beneficiary_comment',
|
||||||
'date-of-birth': 'birthdate', 'place-of-birth': 'birth_place', 'gender': 'gender',
|
'comments': 'comments'},
|
||||||
|
'person': {'person': 't_person', 'text': 'comments', 'first-name': 'first_name',
|
||||||
|
'middle-name': 'middle_name', 'last-name': 'last_name', 'title': 'title',
|
||||||
|
'mothers-name': 'mothers_name', 'alias': 'alias', 'date-of-birth': 'birthdate',
|
||||||
|
'place-of-birth': 'birth_place', 'gender': 'gender','nationality': 'nationality1',
|
||||||
'passport-number': 'passport_number', 'passport-country': 'passport_country',
|
'passport-number': 'passport_number', 'passport-country': 'passport_country',
|
||||||
'social-security-number': 'ssn', 'nationality': 'nationality1', 'identity-card-number': 'id_number',
|
'social-security-number': 'ssn', 'identity-card-number': 'id_number'},
|
||||||
'geolocation': 'location', 'city': 'city', 'region': 'state', 'country': 'country-code',
|
'geolocation': {'geolocation': 'location', 'city': 'city', 'region': 'state',
|
||||||
'address': 'address', 'zipcode': 'zip',
|
'country': 'country_code', 'address': 'address', 'zipcode': 'zip'},
|
||||||
'transaction': 'transaction', 'transaction-number': 'transactionnumber', 'date': 'date_transaction',
|
'transaction': {'transaction': 'transaction', 'transaction-number': 'transactionnumber',
|
||||||
'location': 'transaction_location', 'transmode-code': 'transmode_code', 'amount': 'amount_local',
|
'date': 'date_transaction', 'location': 'transaction_location',
|
||||||
'transmode-comment': 'transmode_comment', 'date-posting': 'date_posting', 'teller': 'teller',
|
'transmode-code': 'transmode_code', 'amount': 'amount_local',
|
||||||
'authorized': 'authorized',
|
'transmode-comment': 'transmode_comment', 'date-posting': 'date_posting',
|
||||||
'legal-entity': 'entity', 'name': 'name', 'commercial-name': 'commercial_name', 'business': 'business',
|
'teller': 'teller', 'authorized': 'authorized',
|
||||||
'legal-form': 'incorporation_legal_form', 'registration-number': 'incorporation_number',
|
'text': 'transaction_description'},
|
||||||
'phone-number': 'phone'}
|
'legal-entity': {'legal-entity': 'entity', 'name': 'name', 'business': 'business',
|
||||||
|
'commercial-name': 'commercial_name', 'phone-number': 'phone',
|
||||||
|
'legal-form': 'incorporation_legal_form',
|
||||||
|
'registration-number': 'incorporation_number'}}
|
||||||
|
|
||||||
referencesMapping = {'bank-account': {'aml_type': '{}_account', 'bracket': 't_{}'},
|
referencesMapping = {'bank-account': {'aml_type': '{}_account', 'bracket': 't_{}'},
|
||||||
'person': {'transaction': {'aml_type': '{}_person', 'bracket': 't_{}'}, 'bank-account': {'aml_type': 't_person', 'bracket': 'signatory'}},
|
'person': {'transaction': {'aml_type': '{}_person', 'bracket': 't_{}'}, 'bank-account': {'aml_type': 't_person', 'bracket': 'signatory'}},
|
||||||
'legal-entity': {'transaction': {'aml_type': '{}_entity', 'bracket': 't_{}'}, 'bank-account': {'aml_type': 'entity'}},
|
'legal-entity': {'transaction': {'aml_type': '{}_entity', 'bracket': 't_{}'}, 'bank-account': {'aml_type': 't_entity'}},
|
||||||
'geolocation': {'aml_type': 'address', 'bracket': 'addresses'}}
|
'geolocation': {'aml_type': 'address', 'bracket': 'addresses'}}
|
||||||
|
|
||||||
class GoAmlGeneration(object):
|
class GoAmlGeneration(object):
|
||||||
|
@ -88,7 +96,7 @@ class GoAmlGeneration(object):
|
||||||
obj = self.misp_event.get_object_by_uuid(uuid)
|
obj = self.misp_event.get_object_by_uuid(uuid)
|
||||||
if object_type == 'transaction':
|
if object_type == 'transaction':
|
||||||
self.xml[xml_part] += "<{}>".format(aml_type)
|
self.xml[xml_part] += "<{}>".format(aml_type)
|
||||||
self.fill_xml_transaction(obj.attributes, xml_part)
|
self.fill_xml_transaction(object_type, obj.attributes, xml_part)
|
||||||
self.parsed_uuids[object_type].append(uuid)
|
self.parsed_uuids[object_type].append(uuid)
|
||||||
if obj.ObjectReference:
|
if obj.ObjectReference:
|
||||||
self.parseObjectReferences(object_type, xml_part, obj.ObjectReference)
|
self.parseObjectReferences(object_type, xml_part, obj.ObjectReference)
|
||||||
|
@ -104,7 +112,7 @@ class GoAmlGeneration(object):
|
||||||
|
|
||||||
def itterate_normal_case(self, object_type, obj, aml_type, uuid, xml_part):
|
def itterate_normal_case(self, object_type, obj, aml_type, uuid, xml_part):
|
||||||
self.xml[xml_part] += "<{}>".format(aml_type)
|
self.xml[xml_part] += "<{}>".format(aml_type)
|
||||||
self.fill_xml(obj, xml_part)
|
self.fill_xml(object_type, obj, xml_part)
|
||||||
self.parsed_uuids[object_type].append(uuid)
|
self.parsed_uuids[object_type].append(uuid)
|
||||||
if obj.ObjectReference:
|
if obj.ObjectReference:
|
||||||
self.parseObjectReferences(object_type, xml_part, obj.ObjectReference)
|
self.parseObjectReferences(object_type, xml_part, obj.ObjectReference)
|
||||||
|
@ -117,7 +125,7 @@ class GoAmlGeneration(object):
|
||||||
relationship_type = ref.relationship_type
|
relationship_type = ref.relationship_type
|
||||||
self.parse_references(object_type, next_object_type, next_uuid, relationship_type, xml_part)
|
self.parse_references(object_type, next_object_type, next_uuid, relationship_type, xml_part)
|
||||||
|
|
||||||
def fill_xml_transaction(self, attributes, xml_part):
|
def fill_xml_transaction(self, object_type, attributes, xml_part):
|
||||||
from_and_to_fields = {'from': {}, 'to': {}}
|
from_and_to_fields = {'from': {}, 'to': {}}
|
||||||
for attribute in attributes:
|
for attribute in attributes:
|
||||||
object_relation = attribute.object_relation
|
object_relation = attribute.object_relation
|
||||||
|
@ -133,12 +141,12 @@ class GoAmlGeneration(object):
|
||||||
from_and_to_fields[relation_type][field] = attribute_value
|
from_and_to_fields[relation_type][field] = attribute_value
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
self.xml[xml_part] += "<{0}>{1}</{0}>".format(goAMLmapping[object_relation], attribute_value)
|
self.xml[xml_part] += "<{0}>{1}</{0}>".format(goAMLmapping[object_type][object_relation], attribute_value)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
self.from_and_to_fields = from_and_to_fields
|
self.from_and_to_fields = from_and_to_fields
|
||||||
|
|
||||||
def fill_xml(self, obj, xml_part):
|
def fill_xml(self, object_type, obj, xml_part):
|
||||||
if obj.name == 'bank-account':
|
if obj.name == 'bank-account':
|
||||||
for attribute in obj.attributes:
|
for attribute in obj.attributes:
|
||||||
if attribute.object_relation in ('personal-account-type', 'status-code'):
|
if attribute.object_relation in ('personal-account-type', 'status-code'):
|
||||||
|
@ -146,13 +154,13 @@ class GoAmlGeneration(object):
|
||||||
else:
|
else:
|
||||||
attribute_value = attribute.value
|
attribute_value = attribute.value
|
||||||
try:
|
try:
|
||||||
self.xml[xml_part] += "<{0}>{1}</{0}>".format(goAMLmapping[attribute.object_relation], attribute_value)
|
self.xml[xml_part] += "<{0}>{1}</{0}>".format(goAMLmapping[object_type][attribute.object_relation], attribute_value)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
for attribute in obj.attributes:
|
for attribute in obj.attributes:
|
||||||
try:
|
try:
|
||||||
self.xml[xml_part] += "<{0}>{1}</{0}>".format(goAMLmapping[attribute.object_relation], attribute.value)
|
self.xml[xml_part] += "<{0}>{1}</{0}>".format(goAMLmapping[object_type][attribute.object_relation], attribute.value)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -186,6 +194,15 @@ def handler(q=False):
|
||||||
config = request['config'].get('rentity_id')
|
config = request['config'].get('rentity_id')
|
||||||
export_doc = GoAmlGeneration(config)
|
export_doc = GoAmlGeneration(config)
|
||||||
export_doc.from_event(request['data'][0])
|
export_doc.from_event(request['data'][0])
|
||||||
|
if not export_doc.misp_event.Object:
|
||||||
|
misperrors['error'] = "There is no object in this event."
|
||||||
|
return misperrors
|
||||||
|
types = []
|
||||||
|
for obj in export_doc.misp_event.Object:
|
||||||
|
types.append(obj.name)
|
||||||
|
if 'transaction' not in types:
|
||||||
|
misperrors['error'] = "There is no transaction object in this event."
|
||||||
|
return misperrors
|
||||||
export_doc.parse_objects()
|
export_doc.parse_objects()
|
||||||
export_doc.build_xml()
|
export_doc.build_xml()
|
||||||
exp_doc = "{}{}".format(export_doc.xml.get('header'), export_doc.xml.get('data'))
|
exp_doc = "{}{}".format(export_doc.xml.get('header'), export_doc.xml.get('data'))
|
||||||
|
|
|
@ -15,7 +15,8 @@ misperrors = {'error': 'Error'}
|
||||||
moduleinfo = {'version': '1',
|
moduleinfo = {'version': '1',
|
||||||
'author': 'Raphaël Vinot',
|
'author': 'Raphaël Vinot',
|
||||||
'description': 'Simple export to PDF',
|
'description': 'Simple export to PDF',
|
||||||
'module-type': ['export']}
|
'module-type': ['export'],
|
||||||
|
'require_standard_format': True}
|
||||||
|
|
||||||
moduleconfig = []
|
moduleconfig = []
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from . import _vmray
|
from . import _vmray
|
||||||
|
|
||||||
__all__ = ['vmray_import', 'testimport', 'ocr', 'stiximport', 'cuckooimport',
|
__all__ = ['vmray_import', 'testimport', 'ocr', 'stiximport', 'cuckooimport', 'goamlimport',
|
||||||
'email_import', 'mispjson', 'openiocimport', 'threatanalyzer_import', 'csvimport']
|
'email_import', 'mispjson', 'openiocimport', 'threatanalyzer_import', 'csvimport']
|
||||||
|
|
|
@ -1,111 +1,99 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import json, os
|
import json, os, base64
|
||||||
import pymisp
|
import pymisp
|
||||||
|
|
||||||
misperrors = {'error': 'Error'}
|
misperrors = {'error': 'Error'}
|
||||||
mispattributes = {'input': ['file'], 'output': ['MISP attributes']}
|
|
||||||
moduleinfo = {'version': '0.1', 'author': 'Christian Studer',
|
moduleinfo = {'version': '0.1', 'author': 'Christian Studer',
|
||||||
'description': 'Import Attributes from a csv file.',
|
'description': 'Import Attributes from a csv file.',
|
||||||
'module-type': ['import']}
|
'module-type': ['import']}
|
||||||
moduleconfig = ['header']
|
moduleconfig = []
|
||||||
|
inputSource = ['file']
|
||||||
|
userConfig = {'header': {
|
||||||
|
'type': 'String',
|
||||||
|
'message': 'Define the header of the csv file, with types (included in MISP attribute types or attribute fields) separated by commas.\nFor fields that do not match these types, please use space or simply nothing between commas.\nFor instance: ip-src,domain, ,timestamp'},
|
||||||
|
'has_header':{
|
||||||
|
'type': 'Boolean',
|
||||||
|
'message': 'Tick this box ONLY if there is a header line, NOT COMMENTED, in the file (which will be skipped atm).'
|
||||||
|
}}
|
||||||
|
|
||||||
duplicatedFields = {'mispType': {'mispComment': 'comment'},
|
duplicatedFields = {'mispType': {'mispComment': 'comment'},
|
||||||
'attrField': {'eventComment': 'comment'}}
|
'attrField': {'attrComment': 'comment'}}
|
||||||
|
attributesFields = ['type', 'value', 'category', 'to_ids', 'comment', 'distribution']
|
||||||
|
delimiters = [',', ';', '|', '/', '\t', ' ']
|
||||||
|
|
||||||
def handler(q=False):
|
class CsvParser():
|
||||||
if q is False:
|
def __init__(self, header, has_header):
|
||||||
return False
|
self.header = header
|
||||||
request = json.loads(q)
|
self.fields_number = len(header)
|
||||||
if request.get('file'):
|
self.has_header = has_header
|
||||||
filename = request['file']
|
self.attributes = []
|
||||||
else:
|
|
||||||
misperrors['error'] = "Unsupported attributes type"
|
|
||||||
return misperrors
|
|
||||||
if not request.get('config') and not request['config'].get('header'):
|
|
||||||
misperrors['error'] = "Configuration error"
|
|
||||||
return misperrors
|
|
||||||
config = request['config'].get('header')
|
|
||||||
#header = []
|
|
||||||
try:
|
|
||||||
data = readFile(filename, 'utf-8')
|
|
||||||
except:
|
|
||||||
data = readFile(filename, 'iso-8859-1')
|
|
||||||
# find which delimiter is used
|
|
||||||
delimiter, length = findDelimiter(config, data)
|
|
||||||
# build the attributes
|
|
||||||
result = buildAttributes(config, data, delimiter, length)
|
|
||||||
r = {'results': [{'types': mispattributes['output'], 'values': result}]}
|
|
||||||
return r
|
|
||||||
|
|
||||||
def readFile(filename, encoding):
|
def parse_data(self, data):
|
||||||
data = []
|
return_data = []
|
||||||
with open(filename, 'r', encoding=encoding) as f:
|
if self.fields_number == 1:
|
||||||
for line in f:
|
for line in data:
|
||||||
# split comments from data
|
|
||||||
if '#' in line:
|
|
||||||
l = line.split('#')[0].strip()
|
l = line.split('#')[0].strip()
|
||||||
else:
|
|
||||||
l = line.strip()
|
|
||||||
if l:
|
if l:
|
||||||
data.append(l)
|
return_data.append(l)
|
||||||
return data
|
self.delimiter = None
|
||||||
|
|
||||||
def findDelimiter(header, data):
|
|
||||||
n = len(header)
|
|
||||||
if n > 1:
|
|
||||||
tmpData = []
|
|
||||||
for da in data:
|
|
||||||
tmp = []
|
|
||||||
for d in (';', '|', '/', ',', '\t', ' ',):
|
|
||||||
if da.count(d) == (n-1):
|
|
||||||
tmp.append(d)
|
|
||||||
if len(tmp) == 1 and tmp == tmpData:
|
|
||||||
return tmpData[0], n
|
|
||||||
else:
|
else:
|
||||||
tmpData = tmp
|
self.delimiter_count = dict([(d, 0) for d in delimiters])
|
||||||
else:
|
for line in data:
|
||||||
return None, 1
|
l = line.split('#')[0].strip()
|
||||||
|
if l:
|
||||||
|
self.parse_delimiter(l)
|
||||||
|
return_data.append(l)
|
||||||
|
# find which delimiter is used
|
||||||
|
self.delimiter = self.find_delimiter()
|
||||||
|
self.data = return_data[1:] if self.has_header else return_data
|
||||||
|
|
||||||
def buildAttributes(header, dataValues, delimiter, length):
|
def parse_delimiter(self, line):
|
||||||
attributes = []
|
for d in delimiters:
|
||||||
|
if line.count(d) >= (self.fields_number - 1):
|
||||||
|
self.delimiter_count[d] += 1
|
||||||
|
|
||||||
|
def find_delimiter(self):
|
||||||
|
_, delimiter = max((n, v) for v, n in self.delimiter_count.items())
|
||||||
|
return delimiter
|
||||||
|
|
||||||
|
def buildAttributes(self):
|
||||||
# if there is only 1 field of data
|
# if there is only 1 field of data
|
||||||
if delimiter is None:
|
if self.delimiter is None:
|
||||||
mispType = header[0]
|
mispType = self.header[0]
|
||||||
for data in dataValues:
|
for data in self.data:
|
||||||
d = data.strip()
|
d = data.strip()
|
||||||
if d:
|
if d:
|
||||||
attributes.append({'type': mispType, 'value': d})
|
self.attributes.append({'types': mispType, 'values': d})
|
||||||
else:
|
else:
|
||||||
# split fields that should be recognized as misp attribute types from the others
|
# split fields that should be recognized as misp attribute types from the others
|
||||||
list2pop, misp, head = findMispTypes(header)
|
list2pop, misp, head = self.findMispTypes()
|
||||||
# for each line of data
|
# for each line of data
|
||||||
for data in dataValues:
|
for data in self.data:
|
||||||
datamisp = []
|
datamisp = []
|
||||||
datasplit = data.split(delimiter)
|
datasplit = data.split(self.delimiter)
|
||||||
# in case there is an empty line or an error
|
# in case there is an empty line or an error
|
||||||
if len(datasplit) != length:
|
if len(datasplit) != self.fields_number:
|
||||||
continue
|
continue
|
||||||
# pop from the line data that matches with a misp type, using the list of indexes
|
# pop from the line data that matches with a misp type, using the list of indexes
|
||||||
for l in list2pop:
|
for l in list2pop:
|
||||||
datamisp.append(datasplit.pop(l).strip())
|
datamisp.append(datasplit.pop(l).strip())
|
||||||
# for each misp type, we create an attribute
|
# for each misp type, we create an attribute
|
||||||
for m, dm in zip(misp, datamisp):
|
for m, dm in zip(misp, datamisp):
|
||||||
attribute = {'type': m, 'value': dm}
|
attribute = {'types': m, 'values': dm}
|
||||||
for h, ds in zip(head, datasplit):
|
for h, ds in zip(head, datasplit):
|
||||||
if h:
|
if h:
|
||||||
attribute[h] = ds.strip()
|
attribute[h] = ds.strip()
|
||||||
attributes.append(attribute)
|
self.attributes.append(attribute)
|
||||||
return attributes
|
|
||||||
|
|
||||||
def findMispTypes(header):
|
def findMispTypes(self):
|
||||||
descFilename = os.path.join(pymisp.__path__[0], 'data/describeTypes.json')
|
descFilename = os.path.join(pymisp.__path__[0], 'data/describeTypes.json')
|
||||||
with open(descFilename, 'r') as f:
|
with open(descFilename, 'r') as f:
|
||||||
MispTypes = json.loads(f.read())['result'].get('types')
|
MispTypes = json.loads(f.read())['result'].get('types')
|
||||||
list2pop = []
|
list2pop = []
|
||||||
misp = []
|
misp = []
|
||||||
head = []
|
head = []
|
||||||
for h in reversed(header):
|
for h in reversed(self.header):
|
||||||
n = header.index(h)
|
n = self.header.index(h)
|
||||||
# fields that are misp attribute types
|
# fields that are misp attribute types
|
||||||
if h in MispTypes:
|
if h in MispTypes:
|
||||||
list2pop.append(n)
|
list2pop.append(n)
|
||||||
|
@ -118,14 +106,51 @@ def findMispTypes(header):
|
||||||
elif h in duplicatedFields['attrField']:
|
elif h in duplicatedFields['attrField']:
|
||||||
# fields that should be considered as attribute fields
|
# fields that should be considered as attribute fields
|
||||||
head.append(duplicatedFields['attrField'].get(h))
|
head.append(duplicatedFields['attrField'].get(h))
|
||||||
# otherwise, it is an attribute field
|
# or, it could be an attribute field
|
||||||
else:
|
elif h in attributesFields:
|
||||||
head.append(h)
|
head.append(h)
|
||||||
|
# otherwise, it is not defined
|
||||||
|
else:
|
||||||
|
head.append('')
|
||||||
# return list of indexes of the misp types, list of the misp types, remaining fields that will be attribute fields
|
# return list of indexes of the misp types, list of the misp types, remaining fields that will be attribute fields
|
||||||
return list2pop, misp, list(reversed(head))
|
return list2pop, misp, list(reversed(head))
|
||||||
|
|
||||||
|
def handler(q=False):
|
||||||
|
if q is False:
|
||||||
|
return False
|
||||||
|
request = json.loads(q)
|
||||||
|
if request.get('data'):
|
||||||
|
data = base64.b64decode(request['data']).decode('utf-8')
|
||||||
|
else:
|
||||||
|
misperrors['error'] = "Unsupported attributes type"
|
||||||
|
return misperrors
|
||||||
|
if not request.get('config') and not request['config'].get('header'):
|
||||||
|
misperrors['error'] = "Configuration error"
|
||||||
|
return misperrors
|
||||||
|
header = request['config'].get('header').split(',')
|
||||||
|
header = [c.strip() for c in header]
|
||||||
|
has_header = request['config'].get('has_header')
|
||||||
|
has_header = True if has_header == '1' else False
|
||||||
|
csv_parser = CsvParser(header, has_header)
|
||||||
|
csv_parser.parse_data(data.split('\n'))
|
||||||
|
# build the attributes
|
||||||
|
csv_parser.buildAttributes()
|
||||||
|
r = {'results': csv_parser.attributes}
|
||||||
|
return r
|
||||||
|
|
||||||
def introspection():
|
def introspection():
|
||||||
return mispattributes
|
modulesetup = {}
|
||||||
|
try:
|
||||||
|
userConfig
|
||||||
|
modulesetup['userConfig'] = userConfig
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
inputSource
|
||||||
|
modulesetup['inputSource'] = inputSource
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
return modulesetup
|
||||||
|
|
||||||
def version():
|
def version():
|
||||||
moduleinfo['config'] = moduleconfig
|
moduleinfo['config'] = moduleconfig
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
import json, datetime, time, base64
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from collections import defaultdict
|
||||||
|
from pymisp import MISPEvent, MISPObject
|
||||||
|
|
||||||
|
misperrors = {'error': 'Error'}
|
||||||
|
moduleinfo = {'version': 1, 'author': 'Christian Studer',
|
||||||
|
'description': 'Import from GoAML',
|
||||||
|
'module-type': ['import']}
|
||||||
|
moduleconfig = []
|
||||||
|
mispattributes = {'inputSource': ['file'], 'output': ['MISP objects']}
|
||||||
|
|
||||||
|
t_from_objects = {'nodes': ['from_person', 'from_account', 'from_entity'],
|
||||||
|
'leaves': ['from_funds_code', 'from_country']}
|
||||||
|
t_to_objects = {'nodes': ['to_person', 'to_account', 'to_entity'],
|
||||||
|
'leaves': ['to_funds_code', 'to_country']}
|
||||||
|
t_person_objects = {'nodes': ['addresses'],
|
||||||
|
'leaves': ['first_name', 'middle_name', 'last_name', 'gender', 'title', 'mothers_name', 'birthdate',
|
||||||
|
'passport_number', 'passport_country', 'id_number', 'birth_place', 'alias', 'nationality1']}
|
||||||
|
t_account_objects = {'nodes': ['signatory'],
|
||||||
|
'leaves': ['institution_name', 'institution_code', 'swift', 'branch', 'non_banking_insitution',
|
||||||
|
'account', 'currency_code', 'account_name', 'iban', 'client_number', 'opened', 'closed',
|
||||||
|
'personal_account_type', 'balance', 'date_balance', 'status_code', 'beneficiary',
|
||||||
|
'beneficiary_comment', 'comments']}
|
||||||
|
entity_objects = {'nodes': ['addresses'],
|
||||||
|
'leaves': ['name', 'commercial_name', 'incorporation_legal_form', 'incorporation_number', 'business', 'phone']}
|
||||||
|
|
||||||
|
goAMLobjects = {'report': {'nodes': ['reporting_person', 'location'],
|
||||||
|
'leaves': ['rentity_id', 'submission_code', 'report_code', 'submission_date', 'currency_code_local']},
|
||||||
|
'reporting_person': {'nodes': ['addresses'], 'leaves': ['first_name', 'middle_name', 'last_name', 'title']},
|
||||||
|
'location': {'nodes': [], 'leaves': ['address_type', 'address', 'city', 'zip', 'country_code', 'state']},
|
||||||
|
'transaction': {'nodes': ['t_from', 't_from_my_client', 't_to', 't_to_my_client'],
|
||||||
|
'leaves': ['transactionnumber', 'transaction_location', 'date_transaction',
|
||||||
|
'transmode_code', 'amount_local']},
|
||||||
|
't_from': t_from_objects, 't_from_my_client': t_from_objects,
|
||||||
|
't_to': t_to_objects, 't_to_my_client': t_to_objects,
|
||||||
|
'addresses': {'nodes': ['address'], 'leaves': []},
|
||||||
|
'address': {'nodes': [], 'leaves': ['address_type', 'address', 'city', 'zip', 'country_code', 'state']},
|
||||||
|
'from_person': t_person_objects, 'to_person': t_person_objects, 't_person': t_person_objects,
|
||||||
|
'from_account': t_account_objects, 'to_account': t_account_objects,
|
||||||
|
'signatory': {'nodes': ['t_person'], 'leaves': []},
|
||||||
|
'from_entity': entity_objects, 'to_entity': entity_objects,
|
||||||
|
}
|
||||||
|
|
||||||
|
t_account_mapping = {'misp_name': 'bank-account', 'institution_name': 'institution-name', 'institution_code': 'institution-code',
|
||||||
|
'iban': 'iban', 'swift': 'swift', 'branch': 'branch', 'non_banking_institution': 'non-bank-institution',
|
||||||
|
'account': 'account', 'currency_code': 'currency-code', 'account_name': 'account-name',
|
||||||
|
'client_number': 'client-number', 'personal_account_type': 'personal-account-type', 'opened': 'opened',
|
||||||
|
'closed': 'closed', 'balance': 'balance', 'status_code': 'status-code', 'beneficiary': 'beneficiary',
|
||||||
|
'beneficiary_comment': 'beneficiary-comment', 'comments': 'comments'}
|
||||||
|
|
||||||
|
t_person_mapping = {'misp_name': 'person', 'comments': 'text', 'first_name': 'first-name', 'middle_name': 'middle-name',
|
||||||
|
'last_name': 'last-name', 'title': 'title', 'mothers_name': 'mothers-name', 'alias': 'alias',
|
||||||
|
'birthdate': 'date-of-birth', 'birth_place': 'place-of-birth', 'gender': 'gender','nationality1': 'nationality',
|
||||||
|
'passport_number': 'passport-number', 'passport_country': 'passport-country', 'ssn': 'social-security-number',
|
||||||
|
'id_number': 'identity-card-number'}
|
||||||
|
|
||||||
|
location_mapping = {'misp_name': 'geolocation', 'city': 'city', 'state': 'region', 'country_code': 'country', 'address': 'address',
|
||||||
|
'zip': 'zipcode'}
|
||||||
|
|
||||||
|
t_entity_mapping = {'misp_name': 'legal-entity', 'name': 'name', 'business': 'business', 'commercial_name': 'commercial-name',
|
||||||
|
'phone': 'phone-number', 'incorporation_legal_form': 'legal-form', 'incorporation_number': 'registration-number'}
|
||||||
|
|
||||||
|
goAMLmapping = {'from_account': t_account_mapping, 'to_account': t_account_mapping, 't_person': t_person_mapping,
|
||||||
|
'from_person': t_person_mapping, 'to_person': t_person_mapping, 'reporting_person': t_person_mapping,
|
||||||
|
'from_entity': t_entity_mapping, 'to_entity': t_entity_mapping,
|
||||||
|
'location': location_mapping, 'address': location_mapping,
|
||||||
|
'transaction': {'misp_name': 'transaction', 'transactionnumber': 'transaction-number', 'date_transaction': 'date',
|
||||||
|
'transaction_location': 'location', 'transmode_code': 'transmode-code', 'amount_local': 'amount',
|
||||||
|
'transmode_comment': 'transmode-comment', 'date_posting': 'date-posting', 'teller': 'teller',
|
||||||
|
'authorized': 'authorized', 'transaction_description': 'text'}}
|
||||||
|
|
||||||
|
nodes_to_ignore = ['addresses', 'signatory']
|
||||||
|
relationship_to_keep = ['signatory', 't_from', 't_from_my_client', 't_to', 't_to_my_client', 'address']
|
||||||
|
|
||||||
|
class GoAmlParser():
|
||||||
|
def __init__(self):
|
||||||
|
self.misp_event = MISPEvent()
|
||||||
|
|
||||||
|
def read_xml(self, data):
|
||||||
|
self.tree = ET.fromstring(data)
|
||||||
|
|
||||||
|
def parse_xml(self):
|
||||||
|
self.first_itteration()
|
||||||
|
for t in self.tree.findall('transaction'):
|
||||||
|
self.itterate(t, 'transaction')
|
||||||
|
|
||||||
|
def first_itteration(self):
|
||||||
|
submission_date = self.tree.find('submission_date').text.split('+')[0]
|
||||||
|
self.misp_event.timestamp = int(time.mktime(time.strptime(submission_date, "%Y-%m-%dT%H:%M:%S")))
|
||||||
|
for node in goAMLobjects['report']['nodes']:
|
||||||
|
element = self.tree.find(node)
|
||||||
|
if element is not None:
|
||||||
|
self.itterate(element, element.tag)
|
||||||
|
|
||||||
|
def itterate(self, tree, aml_type, referencing_uuid=None, relationship_type=None):
|
||||||
|
objects = goAMLobjects[aml_type]
|
||||||
|
referenced_uuid = referencing_uuid
|
||||||
|
rel = relationship_type
|
||||||
|
if aml_type not in nodes_to_ignore:
|
||||||
|
try:
|
||||||
|
mapping = goAMLmapping[aml_type]
|
||||||
|
misp_object = MISPObject(name=mapping['misp_name'])
|
||||||
|
for leaf in objects['leaves']:
|
||||||
|
element = tree.find(leaf)
|
||||||
|
if element is not None:
|
||||||
|
object_relation = mapping[element.tag]
|
||||||
|
attribute = {'object_relation': object_relation, 'value': element.text}
|
||||||
|
misp_object.add_attribute(**attribute)
|
||||||
|
if aml_type == 'transaction':
|
||||||
|
for node in objects['nodes']:
|
||||||
|
element = tree.find(node)
|
||||||
|
if element is not None:
|
||||||
|
self.fill_transaction(element, element.tag, misp_object)
|
||||||
|
self.misp_event.add_object(misp_object)
|
||||||
|
last_object = self.misp_event.objects[-1]
|
||||||
|
referenced_uuid = last_object.uuid
|
||||||
|
if referencing_uuid and relationship_type:
|
||||||
|
referencing_object = self.misp_event.get_object_by_uuid(referencing_uuid)
|
||||||
|
referencing_object.add_reference(referenced_uuid, rel, None, **last_object)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
for node in objects['nodes']:
|
||||||
|
element = tree.find(node)
|
||||||
|
if element is not None:
|
||||||
|
tag = element.tag
|
||||||
|
if tag in relationship_to_keep:
|
||||||
|
rel = tag[2:] if tag.startswith('t_') else tag
|
||||||
|
self.itterate(element, element.tag, referencing_uuid=referenced_uuid, relationship_type=rel)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def fill_transaction(element, tag, misp_object):
|
||||||
|
if 't_from' in tag:
|
||||||
|
from_funds = element.find('from_funds_code').text
|
||||||
|
from_funds_attribute = {'object_relation': 'from-funds-code', 'value': from_funds}
|
||||||
|
misp_object.add_attribute(**from_funds_attribute)
|
||||||
|
from_country = element.find('from_country').text
|
||||||
|
from_country_attribute = {'object_relation': 'from-country', 'value': from_country}
|
||||||
|
misp_object.add_attribute(**from_country_attribute)
|
||||||
|
if 't_to' in tag:
|
||||||
|
to_funds = element.find('to_funds_code').text
|
||||||
|
to_funds_attribute = {'object_relation': 'to-funds-code', 'value': to_funds}
|
||||||
|
misp_object.add_attribute(**to_funds_attribute)
|
||||||
|
to_country = element.find('to_country').text
|
||||||
|
to_country_attribute = {'object_relation': 'to-country', 'value': to_country}
|
||||||
|
misp_object.add_attribute(**to_country_attribute)
|
||||||
|
|
||||||
|
def handler(q=False):
|
||||||
|
if q is False:
|
||||||
|
return False
|
||||||
|
request = json.loads(q)
|
||||||
|
if request.get('data'):
|
||||||
|
data = base64.b64decode(request['data']).decode('utf-8')
|
||||||
|
else:
|
||||||
|
misperrors['error'] = "Unsupported attributes type"
|
||||||
|
return misperrors
|
||||||
|
aml_parser = GoAmlParser()
|
||||||
|
try:
|
||||||
|
aml_parser.read_xml(data)
|
||||||
|
except:
|
||||||
|
misperrors['error'] = "Impossible to read XML data"
|
||||||
|
return misperrors
|
||||||
|
aml_parser.parse_xml()
|
||||||
|
r = {'results': [obj.to_json() for obj in aml_parser.misp_event.objects]}
|
||||||
|
return r
|
||||||
|
|
||||||
|
def introspection():
|
||||||
|
return mispattributes
|
||||||
|
|
||||||
|
def version():
|
||||||
|
moduleinfo['config'] = moduleconfig
|
||||||
|
return moduleinfo
|
|
@ -15,7 +15,7 @@ misperrors = {'error': 'Error'}
|
||||||
userConfig = {}
|
userConfig = {}
|
||||||
inputSource = ['file']
|
inputSource = ['file']
|
||||||
|
|
||||||
moduleinfo = {'version': '0.6', 'author': 'Christophe Vandeplas',
|
moduleinfo = {'version': '0.7', 'author': 'Christophe Vandeplas',
|
||||||
'description': 'Import for ThreatAnalyzer archive.zip/analysis.json files',
|
'description': 'Import for ThreatAnalyzer archive.zip/analysis.json files',
|
||||||
'module-type': ['import']}
|
'module-type': ['import']}
|
||||||
|
|
||||||
|
@ -62,12 +62,12 @@ def handler(q=False):
|
||||||
if re.match(r"Analysis/proc_\d+/modified_files/.+\.", zip_file_name) and "mapping.log" not in zip_file_name:
|
if re.match(r"Analysis/proc_\d+/modified_files/.+\.", zip_file_name) and "mapping.log" not in zip_file_name:
|
||||||
sample_md5 = zip_file_name.split('/')[-1].split('.')[0]
|
sample_md5 = zip_file_name.split('/')[-1].split('.')[0]
|
||||||
if sample_md5 in modified_files_mapping:
|
if sample_md5 in modified_files_mapping:
|
||||||
sample_filename = modified_files_mapping[sample_md5]
|
current_sample_filename = modified_files_mapping[sample_md5]
|
||||||
# print("{} maps to {}".format(sample_md5, sample_filename))
|
# print("{} maps to {}".format(sample_md5, current_sample_filename))
|
||||||
with zf.open(zip_file_name, mode='r', pwd=None) as fp:
|
with zf.open(zip_file_name, mode='r', pwd=None) as fp:
|
||||||
file_data = fp.read()
|
file_data = fp.read()
|
||||||
results.append({
|
results.append({
|
||||||
'values': sample_filename,
|
'values': current_sample_filename,
|
||||||
'data': base64.b64encode(file_data).decode(),
|
'data': base64.b64encode(file_data).decode(),
|
||||||
'type': 'malware-sample', 'categories': ['Artifacts dropped', 'Payload delivery'], 'to_ids': True, 'comment': ''})
|
'type': 'malware-sample', 'categories': ['Artifacts dropped', 'Payload delivery'], 'to_ids': True, 'comment': ''})
|
||||||
|
|
||||||
|
@ -76,8 +76,18 @@ def handler(q=False):
|
||||||
file_data = fp.read()
|
file_data = fp.read()
|
||||||
analysis_json = json.loads(file_data.decode('utf-8'))
|
analysis_json = json.loads(file_data.decode('utf-8'))
|
||||||
results += process_analysis_json(analysis_json)
|
results += process_analysis_json(analysis_json)
|
||||||
# if 'sample' in zip_file_name:
|
try:
|
||||||
# sample['data'] = base64.b64encode(file_data).decode()
|
sample_filename = analysis_json.get('analysis').get('@filename')
|
||||||
|
if sample_filename:
|
||||||
|
with zf.open('sample', mode='r', pwd=None) as fp:
|
||||||
|
file_data = fp.read()
|
||||||
|
results.append({
|
||||||
|
'values': sample_filename,
|
||||||
|
'data': base64.b64encode(file_data).decode(),
|
||||||
|
'type': 'malware-sample', 'categories': ['Artifacts dropped', 'Payload delivery'], 'to_ids': True, 'comment': ''})
|
||||||
|
except Exception as e:
|
||||||
|
# no 'sample' in archive, might be an url analysis, just ignore
|
||||||
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
|
@ -411,20 +421,22 @@ def cleanup_url(item):
|
||||||
|
|
||||||
def cleanup_filepath(item):
|
def cleanup_filepath(item):
|
||||||
noise_substrings = {
|
noise_substrings = {
|
||||||
'C:\\Windows\\Prefetch\\',
|
'\\AppData\\Local\\GDIPFONTCACHEV1.DAT',
|
||||||
'\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\',
|
|
||||||
'\\AppData\\Roaming\\Microsoft\\Office\\Recent\\',
|
|
||||||
'C:\\ProgramData\\Microsoft\\OfficeSoftwareProtectionPlatform\\Cache\\cache.dat',
|
|
||||||
'\\AppData\\Local\\Microsoft\\Windows\\Temporary Internet Files\\Content.',
|
|
||||||
'\\AppData\\Local\\Microsoft\\Internet Explorer\\Recovery\\High\\',
|
|
||||||
'\\AppData\\Local\\Microsoft\\Internet Explorer\\DOMStore\\',
|
'\\AppData\\Local\\Microsoft\\Internet Explorer\\DOMStore\\',
|
||||||
'\\AppData\\LocalLow\\Microsoft\\Internet Explorer\\Services\\search_',
|
'\\AppData\\Local\\Microsoft\\Internet Explorer\\Recovery\\High\\',
|
||||||
'\\AppData\\Local\\Microsoft\\Windows\\History\\History.',
|
|
||||||
'\\AppData\\Roaming\\Microsoft\\Windows\\Cookies\\',
|
|
||||||
'\\AppData\\LocalLow\\Microsoft\\CryptnetUrlCache\\',
|
|
||||||
'\\AppData\\Local\\Microsoft\\Windows\\Caches\\',
|
'\\AppData\\Local\\Microsoft\\Windows\\Caches\\',
|
||||||
'\\AppData\\Local\\Microsoft\\Windows\WebCache\\',
|
|
||||||
'\\AppData\\Local\\Microsoft\\Windows\\Explorer\\thumbcache',
|
'\\AppData\\Local\\Microsoft\\Windows\\Explorer\\thumbcache',
|
||||||
|
'\\AppData\\Local\\Microsoft\\Windows\\History\\History.',
|
||||||
|
'\\AppData\\Local\\Microsoft\\Windows\\Temporary Internet Files\\Content.',
|
||||||
|
'\\AppData\\Local\\Microsoft\\Windows\\WebCache\\',
|
||||||
|
'\\AppData\\Local\\Temp\\.*tmp$',
|
||||||
|
'\\AppData\\LocalLow\\Microsoft\\CryptnetUrlCache\\',
|
||||||
|
'\\AppData\\LocalLow\\Microsoft\\Internet Explorer\\Services\\search_',
|
||||||
|
'\\AppData\\Roaming\\Microsoft\\Office\\Recent\\',
|
||||||
|
'\\AppData\\Roaming\\Microsoft\\Windows\\Cookies\\',
|
||||||
|
'\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\',
|
||||||
|
'C:\\ProgramData\\Microsoft\\OfficeSoftwareProtectionPlatform\\Cache\\cache.dat',
|
||||||
|
'C:\\Windows\\Prefetch\\',
|
||||||
|
|
||||||
'\\AppData\\Roaming\\Adobe\\Acrobat\\9.0\\SharedDataEvents-journal',
|
'\\AppData\\Roaming\\Adobe\\Acrobat\\9.0\\SharedDataEvents-journal',
|
||||||
'\\AppData\\Roaming\\Adobe\\Acrobat\\9.0\\UserCache.bin',
|
'\\AppData\\Roaming\\Adobe\\Acrobat\\9.0\\UserCache.bin',
|
||||||
|
@ -441,24 +453,27 @@ def cleanup_filepath(item):
|
||||||
|
|
||||||
def cleanup_regkey(item):
|
def cleanup_regkey(item):
|
||||||
noise_substrings = {
|
noise_substrings = {
|
||||||
r'\\Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\',
|
r'\\CurrentVersion\\Explorer\\FileExts\\[a-z\.]+\\OpenWith',
|
||||||
r'\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\',
|
|
||||||
r'\\CurrentVersion\\Explorer\\RecentDocs\\',
|
r'\\CurrentVersion\\Explorer\\RecentDocs\\',
|
||||||
r'\\CurrentVersion\\Explorer\\UserAssist\\',
|
r'\\CurrentVersion\\Explorer\\UserAssist\\',
|
||||||
r'\\CurrentVersion\\Explorer\\FileExts\\[a-z\.]+\\OpenWith',
|
r'\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\Bag',
|
||||||
r'\\Software\\Microsoft\\Internet Explorer\\Main\\WindowsSearch',
|
|
||||||
r'\\Software\\Microsoft\\Office\\[0-9\.]+\\',
|
|
||||||
r'\\SOFTWARE\\Microsoft\\OfficeSoftwareProtectionPlatform\\',
|
|
||||||
r'\\Software\\Microsoft\\Office\\Common\\Smart Tag\\',
|
|
||||||
r'\\Usage\\SpellingAndGrammarFiles',
|
|
||||||
r'^HKLM\\Software\\Microsoft\\Tracing\\',
|
|
||||||
r'\\Software\\Classes\\CLSID\\',
|
r'\\Software\\Classes\\CLSID\\',
|
||||||
r'\\Software\\Classes\\Local Settings\\MuiCache\\',
|
r'\\Software\\Classes\\Local Settings\\MuiCache\\',
|
||||||
r'\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\Bag',
|
r'\\Software\\Microsoft\\Internet Explorer\\Main\\WindowsSearch',
|
||||||
r'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU\\'
|
r'\\Software\\Microsoft\\Office\\[0-9\.]+\\',
|
||||||
|
r'\\Software\\Microsoft\\Office\\Common\\Smart Tag\\',
|
||||||
|
r'\\Software\\Microsoft\\OfficeSoftwareProtectionPlatform\\',
|
||||||
|
r'\\Software\\Microsoft\\Shared Tools\\Panose\\',
|
||||||
|
r'\\Software\\Microsoft\\Tracing\\',
|
||||||
|
r'\\Software\\Microsoft\\Tracing\\powershell_RASAPI32\\',
|
||||||
|
r'\\Software\\Microsoft\\Tracing\\powershell_RASMANCS\\',
|
||||||
|
r'\\Software\\Microsoft\\Windows\\CurrentVersion\\Action Center\\',
|
||||||
|
r'\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU\\',
|
||||||
|
r'\\Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\',
|
||||||
|
r'\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\',
|
||||||
|
r'\\System\\CurrentControlSet\\Services\\RdyBoost\\',
|
||||||
|
r'\\Usage\\SpellingAndGrammarFiles'
|
||||||
}
|
}
|
||||||
item = item.replace('\\REGISTRY\\MACHINE\\', 'HKLM\\')
|
|
||||||
item = item.replace('\\REGISTRY\\USER\\', 'HKCU\\')
|
|
||||||
if list_in_string(noise_substrings, item, regex=True):
|
if list_in_string(noise_substrings, item, regex=True):
|
||||||
return None
|
return None
|
||||||
return item
|
return item
|
||||||
|
|
|
@ -93,6 +93,9 @@ def handler(q=False):
|
||||||
analysis_data = vmrayDownloadAnalysis(api, analysis_id)
|
analysis_data = vmrayDownloadAnalysis(api, analysis_id)
|
||||||
|
|
||||||
if analysis_data:
|
if analysis_data:
|
||||||
|
if "analysis_vti_patterns" in analysis_data:
|
||||||
|
p = vmrayVtiPatterns(analysis_data["analysis_vti_patterns"])
|
||||||
|
else:
|
||||||
p = vmrayVtiPatterns(analysis_data["vti_patterns"])
|
p = vmrayVtiPatterns(analysis_data["vti_patterns"])
|
||||||
if p and len(p["results"]) > 0:
|
if p and len(p["results"]) > 0:
|
||||||
vti_patterns_found = True
|
vti_patterns_found = True
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<report><rentity_id>2510</rentity_id><submission_code>E</submission_code><report_code>STR</report_code><submission_date>2018-02-22T08:34:16+00:00</submission_date><currency_code_local>EUR</currency_code_local><transaction><transactionnumber>TW00000901</transactionnumber><transaction_location>1 Manners Street Wellington</transaction_location><transmode_code>BG</transmode_code><date_transaction>2015-12-01T10:03:00</date_transaction><amount_local>12345</amount_local><transaction_description>when it transacts</transaction_description><t_from><from_funds_code>E</from_funds_code><from_account><status_code>A</status_code><personal_account_type>A</personal_account_type><currency_code>EUR</currency_code><account>31032027088</account><swift>ATTBVI</swift><institution_name>The bank</institution_name><signatory><t_person><last_name>Nick</last_name><first_name>Pitt</first_name><title>Sir</title><birthdate>1993-09-25</birthdate><birth_place>Mulhouse, France</birth_place><gender>Male</gender><addresses><address><city>Paris</city><country_code>France</country_code></address></addresses></t_person></signatory></from_account><from_country>FRA</from_country></t_from><t_to_my_client><to_funds_code>K</to_funds_code><to_person><last_name>Michel</last_name><first_name>Jean</first_name><title>Himself</title><gender>Prefer not to say</gender><addresses><address><city>Luxembourg</city><country_code>Luxembourg</country_code></address></addresses></to_person><to_country>LUX</to_country></t_to_my_client></transaction></report>
|
Loading…
Reference in New Issue