From 48d38c28212c0b3ac8bb8ee324221d94b07e84ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Mon, 28 Nov 2016 18:12:31 +0100 Subject: [PATCH 01/10] Add initial Domain Tools module --- misp_modules/modules/expansion/domaintools.py | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100755 misp_modules/modules/expansion/domaintools.py diff --git a/misp_modules/modules/expansion/domaintools.py b/misp_modules/modules/expansion/domaintools.py new file mode 100755 index 0000000..19903df --- /dev/null +++ b/misp_modules/modules/expansion/domaintools.py @@ -0,0 +1,124 @@ +import json +import logging +import sys + +from domaintools import API + + +log = logging.getLogger('domaintools') +log.setLevel(logging.DEBUG) +ch = logging.StreamHandler(sys.stdout) +ch.setLevel(logging.DEBUG) +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +ch.setFormatter(formatter) +log.addHandler(ch) + +misperrors = {'error': 'Error'} +mispattributes = { + 'input': ['domain'], + 'output': ['whois-registrant-email', 'whois-registrant-phone', 'whois-registrant-name', + 'whois-registrar', 'whois-creation-date', 'freetext'] +} + +moduleinfo = { + 'version': '0.1', + 'author': 'Raphaƫl Vinot', + 'description': 'DomainTools MISP expansion module.', + 'module-type': ['expansion', 'hover'] +} + +moduleconfig = ['username', 'api_key'] + + +class DomainTools(object): + + def __init__(self): + self.reg_mail = set() + self.reg_phone = set() + self.reg_name = set() + self.registrar = set() + self.creation_date = set() + self.freetext = '' + + def dump(self): + to_return = [] + if self.reg_mail: + to_return.append({'type': ['whois-registrant-email'], 'values': list(self.reg_mail)}) + if self.reg_phone: + to_return.append({'type': ['whois-registrant-phone'], 'values': list(self.reg_phone)}) + if self.reg_name: + to_return.append({'type': ['whois-registrant-name'], 'values': list(self.reg_name)}) + if self.registrar: + to_return.append({'type': ['whois-registrar'], 'values': list(self.registrar)}) + if self.creation_date: + to_return.append({'type': ['whois-creation-date'], 'values': list(self.creation_date)}) + if self.freetext: + to_return.append({'type': ['freetext'], 'values': [self.freetext]}) + return to_return + + +def handler(q=False): + if not q: + return q + + request = json.loads(q) + to_query = None + for t in mispattributes['input']: + to_query = request.get(t) + if to_query: + break + if not to_query: + misperrors['error'] = "Unsupported attributes type" + return misperrors + + if request.get('config'): + if (request['config'].get('username') is None) or (request['config'].get('api_key') is None): + misperrors['error'] = 'DomainTools authentication is incomplete' + return misperrors + else: + domtools = API(request['config'].get('username'), request['config'].get('api_key')) + else: + misperrors['error'] = 'DomainTools authentication is missing' + return misperrors + + whois_entry = domtools.parsed_whois(to_query) + values = DomainTools() + + if whois_entry.has_key('error'): + misperrors['error'] = whois_entry['error']['message'] + return misperrors + + if whois_entry.has_key('registrant'): + values.reg_name.add(whois_entry['registrant']) + + if whois_entry.has_key('registration'): + values.creation_date.add(whois_entry['registration']['created']) + + if whois_entry.has_key('whois'): + values.freetext = whois_entry['whois']['record'] + if whois_entry.emails(): + # NOTE: not sure we want to do that (contains registrar emails) + values.reg_mail |= whois_entry.emails() + if whois_entry.has_key('parsed_whois'): + if whois_entry['parsed_whois']['created_date']: + values.creation_date.add(whois_entry['parsed_whois']['created_date']) + if whois_entry['parsed_whois']['registrar']['name']: + values.registrar.add(whois_entry['parsed_whois']['registrar']['name']) + for key, entry in whois_entry['parsed_whois']['contacts'].items(): + # TODO: pass key as comment + if entry['email']: + values.reg_mail.add(entry['email']) + if entry['phone']: + values.reg_phone.add(entry['phone']) + if entry['name']: + values.reg_name.add(entry['name']) + return json.dumps({'results': values.dump()}) + + +def introspection(): + return mispattributes + + +def version(): + moduleinfo['config'] = moduleconfig + return moduleinfo From 7c6153478eef9f9342bb4fdcee9f13aa08bad62d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Wed, 30 Nov 2016 18:09:11 +0100 Subject: [PATCH 02/10] Add comments to fields when possible --- misp_modules/modules/expansion/domaintools.py | 60 ++++++++++++------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/misp_modules/modules/expansion/domaintools.py b/misp_modules/modules/expansion/domaintools.py index 19903df..1aeb7b6 100755 --- a/misp_modules/modules/expansion/domaintools.py +++ b/misp_modules/modules/expansion/domaintools.py @@ -33,27 +33,47 @@ moduleconfig = ['username', 'api_key'] class DomainTools(object): def __init__(self): - self.reg_mail = set() - self.reg_phone = set() - self.reg_name = set() + self.reg_mail = {} + self.reg_phone = {} + self.reg_name = {} self.registrar = set() self.creation_date = set() self.freetext = '' + def _add_value(self, value_type, value, comment): + if value_type.get(value): + if comment: + value_type[value] += ' - {}'.format(comment) + else: + value_type[value] = comment + return value_type + + def add_mail(self, mail, comment=None): + self.reg_mail = self._add_value(self.reg_mail, mail, comment) + + def add_phone(self, phone, comment=None): + self.reg_phone = self._add_value(self.reg_phone, phone, comment) + + def add_name(self, name, comment=None): + self.reg_name = self._add_value(self.reg_name, name, comment) + def dump(self): to_return = [] if self.reg_mail: - to_return.append({'type': ['whois-registrant-email'], 'values': list(self.reg_mail)}) + for mail, comment in self.reg_mail.items(): + to_return.append({'type': ['whois-registrant-email'], 'values': [mail], 'comment': comment}) if self.reg_phone: - to_return.append({'type': ['whois-registrant-phone'], 'values': list(self.reg_phone)}) + for phone, comment in self.reg_phone.items(): + to_return.append({'type': ['whois-registrant-phone'], 'values': [phone], 'comment': comment}) if self.reg_name: - to_return.append({'type': ['whois-registrant-name'], 'values': list(self.reg_name)}) + for name, comment in self.reg_name.items(): + to_return.append({'type': ['whois-registrant-name'], 'values': [name], 'comment': comment}) if self.registrar: to_return.append({'type': ['whois-registrar'], 'values': list(self.registrar)}) if self.creation_date: to_return.append({'type': ['whois-creation-date'], 'values': list(self.creation_date)}) if self.freetext: - to_return.append({'type': ['freetext'], 'values': [self.freetext]}) + to_return.append({'type': ['freetext'], 'values': [self.freetext], 'comment': 'Freetext import'}) return to_return @@ -82,36 +102,36 @@ def handler(q=False): return misperrors whois_entry = domtools.parsed_whois(to_query) + print(whois_entry) values = DomainTools() - if whois_entry.has_key('error'): + if whois_entry.get('error'): misperrors['error'] = whois_entry['error']['message'] return misperrors - if whois_entry.has_key('registrant'): - values.reg_name.add(whois_entry['registrant']) + if whois_entry.get('registrant'): + values.add_name(whois_entry['registrant'], 'Parsed registrant') - if whois_entry.has_key('registration'): + if whois_entry.get('registration'): values.creation_date.add(whois_entry['registration']['created']) - if whois_entry.has_key('whois'): + if whois_entry.get('whois'): values.freetext = whois_entry['whois']['record'] - if whois_entry.emails(): - # NOTE: not sure we want to do that (contains registrar emails) - values.reg_mail |= whois_entry.emails() - if whois_entry.has_key('parsed_whois'): + if whois_entry.get('parsed_whois'): if whois_entry['parsed_whois']['created_date']: values.creation_date.add(whois_entry['parsed_whois']['created_date']) if whois_entry['parsed_whois']['registrar']['name']: values.registrar.add(whois_entry['parsed_whois']['registrar']['name']) for key, entry in whois_entry['parsed_whois']['contacts'].items(): - # TODO: pass key as comment if entry['email']: - values.reg_mail.add(entry['email']) + values.add_mail(entry['email'], key) if entry['phone']: - values.reg_phone.add(entry['phone']) + values.add_phone(entry['phone'], key) if entry['name']: - values.reg_name.add(entry['name']) + values.add_name(entry['name'], key) + if whois_entry.emails(): + for mail in whois_entry.emails(): + values.add_mail(mail) return json.dumps({'results': values.dump()}) From afd8b71349270ad9a7054931cdb51fa2ff040b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Dec 2016 10:26:40 +0100 Subject: [PATCH 03/10] Avoid passing None in comments --- misp_modules/modules/expansion/domaintools.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/misp_modules/modules/expansion/domaintools.py b/misp_modules/modules/expansion/domaintools.py index 1aeb7b6..521100e 100755 --- a/misp_modules/modules/expansion/domaintools.py +++ b/misp_modules/modules/expansion/domaintools.py @@ -61,13 +61,13 @@ class DomainTools(object): to_return = [] if self.reg_mail: for mail, comment in self.reg_mail.items(): - to_return.append({'type': ['whois-registrant-email'], 'values': [mail], 'comment': comment}) + to_return.append({'type': ['whois-registrant-email'], 'values': [mail], 'comment': comment or ''}) if self.reg_phone: for phone, comment in self.reg_phone.items(): - to_return.append({'type': ['whois-registrant-phone'], 'values': [phone], 'comment': comment}) + to_return.append({'type': ['whois-registrant-phone'], 'values': [phone], 'comment': comment or ''}) if self.reg_name: for name, comment in self.reg_name.items(): - to_return.append({'type': ['whois-registrant-name'], 'values': [name], 'comment': comment}) + to_return.append({'type': ['whois-registrant-name'], 'values': [name], 'comment': comment or ''}) if self.registrar: to_return.append({'type': ['whois-registrar'], 'values': list(self.registrar)}) if self.creation_date: From 6db5436c6287802af053bea4c490207c60c9265e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Dec 2016 11:54:04 +0100 Subject: [PATCH 04/10] remove json.dumps --- misp_modules/modules/expansion/domaintools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misp_modules/modules/expansion/domaintools.py b/misp_modules/modules/expansion/domaintools.py index 521100e..f483b38 100755 --- a/misp_modules/modules/expansion/domaintools.py +++ b/misp_modules/modules/expansion/domaintools.py @@ -132,7 +132,7 @@ def handler(q=False): if whois_entry.emails(): for mail in whois_entry.emails(): values.add_mail(mail) - return json.dumps({'results': values.dump()}) + return {'results': values.dump()} def introspection(): From 9dbd241e636104b41ccf243582395c1040cfa607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Dec 2016 12:14:16 +0100 Subject: [PATCH 05/10] fix typo --- misp_modules/modules/expansion/domaintools.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/misp_modules/modules/expansion/domaintools.py b/misp_modules/modules/expansion/domaintools.py index f483b38..2e8262e 100755 --- a/misp_modules/modules/expansion/domaintools.py +++ b/misp_modules/modules/expansion/domaintools.py @@ -61,19 +61,19 @@ class DomainTools(object): to_return = [] if self.reg_mail: for mail, comment in self.reg_mail.items(): - to_return.append({'type': ['whois-registrant-email'], 'values': [mail], 'comment': comment or ''}) + to_return.append({'types': ['whois-registrant-email'], 'values': [mail], 'comment': comment or ''}) if self.reg_phone: for phone, comment in self.reg_phone.items(): - to_return.append({'type': ['whois-registrant-phone'], 'values': [phone], 'comment': comment or ''}) + to_return.append({'types': ['whois-registrant-phone'], 'values': [phone], 'comment': comment or ''}) if self.reg_name: for name, comment in self.reg_name.items(): - to_return.append({'type': ['whois-registrant-name'], 'values': [name], 'comment': comment or ''}) + to_return.append({'types': ['whois-registrant-name'], 'values': [name], 'comment': comment or ''}) if self.registrar: - to_return.append({'type': ['whois-registrar'], 'values': list(self.registrar)}) + to_return.append({'types': ['whois-registrar'], 'values': list(self.registrar)}) if self.creation_date: - to_return.append({'type': ['whois-creation-date'], 'values': list(self.creation_date)}) + to_return.append({'types': ['whois-creation-date'], 'values': list(self.creation_date)}) if self.freetext: - to_return.append({'type': ['freetext'], 'values': [self.freetext], 'comment': 'Freetext import'}) + to_return.append({'types': ['freetext'], 'values': [self.freetext], 'comment': 'Freetext import'}) return to_return From 7db1216efb6685ec443d2e9d661dbfe8c30e7a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Dec 2016 13:43:37 +0100 Subject: [PATCH 06/10] Add more comments --- misp_modules/modules/expansion/domaintools.py | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/misp_modules/modules/expansion/domaintools.py b/misp_modules/modules/expansion/domaintools.py index 2e8262e..94a2e10 100755 --- a/misp_modules/modules/expansion/domaintools.py +++ b/misp_modules/modules/expansion/domaintools.py @@ -36,8 +36,8 @@ class DomainTools(object): self.reg_mail = {} self.reg_phone = {} self.reg_name = {} - self.registrar = set() - self.creation_date = set() + self.registrar = {} + self.creation_date = {} self.freetext = '' def _add_value(self, value_type, value, comment): @@ -45,7 +45,7 @@ class DomainTools(object): if comment: value_type[value] += ' - {}'.format(comment) else: - value_type[value] = comment + value_type[value] = comment or '' return value_type def add_mail(self, mail, comment=None): @@ -57,23 +57,31 @@ class DomainTools(object): def add_name(self, name, comment=None): self.reg_name = self._add_value(self.reg_name, name, comment) + def add_registrar(self, reg, comment=None): + self.registrar = self._add_value(self.registrar, reg, comment) + + def add_creation_date(self, date, comment=None): + self.creation_date = self._add_value(self.creation_date, date, comment) + def dump(self): to_return = [] if self.reg_mail: for mail, comment in self.reg_mail.items(): - to_return.append({'types': ['whois-registrant-email'], 'values': [mail], 'comment': comment or ''}) + to_return.append({'type': 'whois-registrant-email', 'values': [mail], 'comment': comment or ''}) if self.reg_phone: for phone, comment in self.reg_phone.items(): - to_return.append({'types': ['whois-registrant-phone'], 'values': [phone], 'comment': comment or ''}) + to_return.append({'type': 'whois-registrant-phone', 'values': [phone], 'comment': comment or ''}) if self.reg_name: for name, comment in self.reg_name.items(): - to_return.append({'types': ['whois-registrant-name'], 'values': [name], 'comment': comment or ''}) + to_return.append({'type': 'whois-registrant-name', 'values': [name], 'comment': comment or ''}) if self.registrar: - to_return.append({'types': ['whois-registrar'], 'values': list(self.registrar)}) + for reg, comment in self.registrar.items(): + to_return.append({'type': 'whois-registrar', 'values': [reg], 'comment': comment or ''}) if self.creation_date: - to_return.append({'types': ['whois-creation-date'], 'values': list(self.creation_date)}) + for date, comment in self.creation_date.items(): + to_return.append({'type': 'whois-creation-date', 'values': [date], 'comment': comment or ''}) if self.freetext: - to_return.append({'types': ['freetext'], 'values': [self.freetext], 'comment': 'Freetext import'}) + to_return.append({'type': 'freetext', 'values': [self.freetext], 'comment': 'Freetext import'}) return to_return @@ -113,15 +121,19 @@ def handler(q=False): values.add_name(whois_entry['registrant'], 'Parsed registrant') if whois_entry.get('registration'): - values.creation_date.add(whois_entry['registration']['created']) + values.add_creation_date(whois_entry['registration']['created'], 'timestamp') if whois_entry.get('whois'): values.freetext = whois_entry['whois']['record'] if whois_entry.get('parsed_whois'): if whois_entry['parsed_whois']['created_date']: - values.creation_date.add(whois_entry['parsed_whois']['created_date']) + values.add_creation_date(whois_entry['parsed_whois']['created_date']) if whois_entry['parsed_whois']['registrar']['name']: - values.registrar.add(whois_entry['parsed_whois']['registrar']['name']) + values.add_registrar(whois_entry['parsed_whois']['registrar']['name'], 'name') + if whois_entry['parsed_whois']['registrar']['url']: + values.add_registrar(whois_entry['parsed_whois']['registrar']['url'], 'url') + if whois_entry['parsed_whois']['registrar']['iana_id']: + values.add_registrar(whois_entry['parsed_whois']['registrar']['iana_id'], 'iana_id') for key, entry in whois_entry['parsed_whois']['contacts'].items(): if entry['email']: values.add_mail(entry['email'], key) @@ -131,7 +143,8 @@ def handler(q=False): values.add_name(entry['name'], key) if whois_entry.emails(): for mail in whois_entry.emails(): - values.add_mail(mail) + if mail not in values.reg_mail.keys(): + values.add_mail(mail, 'Maybe registrar') return {'results': values.dump()} From 17205a19134626d912ca1d5e0800912d3a9a078b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Dec 2016 16:41:50 +0100 Subject: [PATCH 07/10] Add domain profile and reputation --- misp_modules/modules/expansion/domaintools.py | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/misp_modules/modules/expansion/domaintools.py b/misp_modules/modules/expansion/domaintools.py index 94a2e10..79b345e 100755 --- a/misp_modules/modules/expansion/domaintools.py +++ b/misp_modules/modules/expansion/domaintools.py @@ -38,11 +38,13 @@ class DomainTools(object): self.reg_name = {} self.registrar = {} self.creation_date = {} + self.domain_ip = {} + self.risk = () self.freetext = '' def _add_value(self, value_type, value, comment): if value_type.get(value): - if comment: + if comment and comment not in value_type[value]: value_type[value] += ' - {}'.format(comment) else: value_type[value] = comment or '' @@ -63,6 +65,9 @@ class DomainTools(object): def add_creation_date(self, date, comment=None): self.creation_date = self._add_value(self.creation_date, date, comment) + def add_ip(self, ip, comment=None): + self.domain_ip = self._add_value(self.domain_ip, ip, comment) + def dump(self): to_return = [] if self.reg_mail: @@ -80,8 +85,13 @@ class DomainTools(object): if self.creation_date: for date, comment in self.creation_date.items(): to_return.append({'type': 'whois-creation-date', 'values': [date], 'comment': comment or ''}) + if self.domain_ip: + for ip, comment in self.domain_ip.items(): + to_return.append({'types': ['dst-ip', 'src-ip'], 'values': [ip], 'comment': comment or ''}) if self.freetext: to_return.append({'type': 'freetext', 'values': [self.freetext], 'comment': 'Freetext import'}) + if self.risk: + to_return.append({'type': 'text', 'values': [self.risk[0]], 'comment': self.risk[1]}) return to_return @@ -110,15 +120,40 @@ def handler(q=False): return misperrors whois_entry = domtools.parsed_whois(to_query) - print(whois_entry) + profile = domtools.domain_profile(to_query) + # NOTE: profile['website_data']['response_code'] could be used to see if the host is still up. Maybe set a tag. + reputation = domtools.reputation(to_query, include_reasons=True) + # NOTE: use that value in a tag when we will have attribute level tagging values = DomainTools() if whois_entry.get('error'): misperrors['error'] = whois_entry['error']['message'] return misperrors + if profile.get('error'): + misperrors['error'] = profile['error']['message'] + return misperrors + + if reputation and not reputation.get('error'): + reasons = ', '.join(reputation['reasons']) + values.risk = [reputation['risk_score'], 'Risk value of {} (via Domain Tools), Reasons: {}'.format(to_query, reasons)] + if whois_entry.get('registrant'): values.add_name(whois_entry['registrant'], 'Parsed registrant') + if profile.get('registrant'): + values.add_name(profile['registrant']['name'], 'Profile registrant') + + if profile.get('server'): + other_domains = profile['server']['other_domains'] + values.add_ip(profile['server']['ip_address'], 'IP of {} (via DomainTools). Has {} other domains.'.format(to_query, other_domains)) + + if profile.get('registration'): + if profile['registration'].get('created'): + values.add_creation_date(profile['registration']['created'], 'created') + if profile['registration'].get('updated'): + values.add_creation_date(profile['registration']['updated'], 'updated') + if profile['registration'].get('registrar'): + values.add_registrar(profile['registration']['registrar'], 'name') if whois_entry.get('registration'): values.add_creation_date(whois_entry['registration']['created'], 'timestamp') @@ -127,7 +162,7 @@ def handler(q=False): values.freetext = whois_entry['whois']['record'] if whois_entry.get('parsed_whois'): if whois_entry['parsed_whois']['created_date']: - values.add_creation_date(whois_entry['parsed_whois']['created_date']) + values.add_creation_date(whois_entry['parsed_whois']['created_date'], 'created') if whois_entry['parsed_whois']['registrar']['name']: values.add_registrar(whois_entry['parsed_whois']['registrar']['name'], 'name') if whois_entry['parsed_whois']['registrar']['url']: From 0f8fa4aaec6abc899eab1403a06e8194d403788d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Dec 2016 16:44:29 +0100 Subject: [PATCH 08/10] Fix Typo --- misp_modules/modules/expansion/domaintools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misp_modules/modules/expansion/domaintools.py b/misp_modules/modules/expansion/domaintools.py index 79b345e..6382726 100755 --- a/misp_modules/modules/expansion/domaintools.py +++ b/misp_modules/modules/expansion/domaintools.py @@ -87,7 +87,7 @@ class DomainTools(object): to_return.append({'type': 'whois-creation-date', 'values': [date], 'comment': comment or ''}) if self.domain_ip: for ip, comment in self.domain_ip.items(): - to_return.append({'types': ['dst-ip', 'src-ip'], 'values': [ip], 'comment': comment or ''}) + to_return.append({'types': ['ip-dst', 'ip-src'], 'values': [ip], 'comment': comment or ''}) if self.freetext: to_return.append({'type': 'freetext', 'values': [self.freetext], 'comment': 'Freetext import'}) if self.risk: From 2e3119b5f45a65f585e34b1239764d73b41c65fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Dec 2016 17:36:40 +0100 Subject: [PATCH 09/10] Add domaintools to the import list --- misp_modules/modules/expansion/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/misp_modules/modules/expansion/__init__.py b/misp_modules/modules/expansion/__init__.py index 62a6ecd..548eb82 100644 --- a/misp_modules/modules/expansion/__init__.py +++ b/misp_modules/modules/expansion/__init__.py @@ -1,4 +1,5 @@ from . import _vmray -__all__ = ['vmray_submit', 'asn_history', 'circl_passivedns', 'circl_passivessl', 'countrycode', 'cve', 'dns', - 'eupi', 'ipasn', 'passivetotal', 'sourcecache', 'virustotal', 'whois', 'shodan', 'reversedns', 'wiki'] +__all__ = ['vmray_submit', 'asn_history', 'circl_passivedns', 'circl_passivessl', + 'countrycode', 'cve', 'dns', 'domaintools', 'eupi', 'ipasn', 'passivetotal', 'sourcecache', + 'virustotal', 'whois', 'shodan', 'reversedns', 'wiki'] From a14c5b749a62c73774fec9070c131f44361684bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Vinot?= Date: Thu, 1 Dec 2016 17:42:10 +0100 Subject: [PATCH 10/10] Update requirements list --- REQUIREMENTS | 1 + 1 file changed, 1 insertion(+) diff --git a/REQUIREMENTS b/REQUIREMENTS index 16f5512..8340c82 100644 --- a/REQUIREMENTS +++ b/REQUIREMENTS @@ -17,3 +17,4 @@ git+https://github.com/CIRCL/PyMISP.git#egg=pymisp pillow pytesseract SPARQLWrapper +domaintools_api