First commit
This commit is contained in:
		
						commit
						f0be826c6e
					
				
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					.**.swp
 | 
				
			||||||
 | 
					__pycache__/**
 | 
				
			||||||
 | 
					config
 | 
				
			||||||
							
								
								
									
										15
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										15
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					# Introduction
 | 
				
			||||||
 | 
					This tool can help SOC analyst to identify any threat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Implementation
 | 
				
			||||||
 | 
					First, you should create a virtualenv:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					$ virtualenv ~/venv/baoSOC
 | 
				
			||||||
 | 
					$ source ~/venv/baoSOC/bin/activate
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					And install all packages the tool need:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					$ pip install -r requirements.txt
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										21
									
								
								config.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										21
									
								
								config.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/venv python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PROJECT_NAME = "baoSOC"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VT_ATTRIBUTES_MAPPING = {
 | 
				
			||||||
 | 
					    'asn': 'str',
 | 
				
			||||||
 | 
					    'as_owner': 'int', 
 | 
				
			||||||
 | 
					    'continent': 'str',
 | 
				
			||||||
 | 
					    'country': 'str',
 | 
				
			||||||
 | 
					    'last_analysis_date': 'date',
 | 
				
			||||||
 | 
					    'regional_internet_registry': 'str',
 | 
				
			||||||
 | 
					    'network': 'str',
 | 
				
			||||||
 | 
					    'ip': 'str'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DNS_QUERIES_TYPE = {
 | 
				
			||||||
 | 
					    'A': 'address',
 | 
				
			||||||
 | 
					    'MX': ['exchange', 'preference'],
 | 
				
			||||||
 | 
					    'TXT': 'strings',
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										74
									
								
								dnschecker.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										74
									
								
								dnschecker.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/venv python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import whois
 | 
				
			||||||
 | 
					import dns.resolver
 | 
				
			||||||
 | 
					import dns.name
 | 
				
			||||||
 | 
					from config import DNS_QUERIES_TYPE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DNSChecker:
 | 
				
			||||||
 | 
					    def __init__(self, api_key, fqdn, rrtype=DNS_QUERIES_TYPE):
 | 
				
			||||||
 | 
					        self._fqdn = fqdn
 | 
				
			||||||
 | 
					        self._rrtype = rrtype
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def checkDomainExist(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        This function check if the domain exist
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            res_query = dns.resolver.resolve(self._fqdn, 'NS')
 | 
				
			||||||
 | 
					        except dns.resolver.NoAnswer:
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					        except dns.resolver.NXDOMAIN:
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def whois(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        This function will get an whois request for having some information
 | 
				
			||||||
 | 
					        regarding the domain
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        report = dict()
 | 
				
			||||||
 | 
					        w = whois.whois(self._fqdn)
 | 
				
			||||||
 | 
					        report['domain_name'] = w.domain_name
 | 
				
			||||||
 | 
					        report['expiration_date'] = w.expiration_date
 | 
				
			||||||
 | 
					        report['creation_date'] = w.creation_date
 | 
				
			||||||
 | 
					        report['updated_date'] = w.updated_date
 | 
				
			||||||
 | 
					        report['ns'] = w.name_servers
 | 
				
			||||||
 | 
					        report['admin_name'] = w.admin_name
 | 
				
			||||||
 | 
					        report['registrar'] = w.registrar
 | 
				
			||||||
 | 
					        return report
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def resolver(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        This function will resolv the FQDN with different type of RR
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        report = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for t in self._rrtype.keys():
 | 
				
			||||||
 | 
					            report[t] = self._resolving(self._fqdn, t, self._rrtype[t])
 | 
				
			||||||
 | 
					        return report
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _resolving(self, fqdn, t, attr):
 | 
				
			||||||
 | 
					        report = list()
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            res_query = dns.resolver.resolve(fqdn, t)
 | 
				
			||||||
 | 
					            for rdata in res_query:
 | 
				
			||||||
 | 
					                if isinstance(attr, list):
 | 
				
			||||||
 | 
					                    data = dict()
 | 
				
			||||||
 | 
					                    for a in attr:
 | 
				
			||||||
 | 
					                        data[a] = getattr(rdata, a)
 | 
				
			||||||
 | 
					                    report.append(data)
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    report.append({
 | 
				
			||||||
 | 
					                        attr: getattr(rdata, attr)
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					        except dns.resolver.NoAnswer:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					        except dns.resolver.NXDOMAIN:
 | 
				
			||||||
 | 
					            report.append({'error': 'Domain not exist'})
 | 
				
			||||||
 | 
					        except dns.resolver.NoNameservers:
 | 
				
			||||||
 | 
					            report.append({'error': 'Domain not exist'})
 | 
				
			||||||
 | 
					        return report
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										36
									
								
								emailchecker.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										36
									
								
								emailchecker.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from requests import get
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class EmailChecker:
 | 
				
			||||||
 | 
					    def __init__(self, key, email):
 | 
				
			||||||
 | 
					        self._url = "https://emailrep.io"
 | 
				
			||||||
 | 
					        self._headers = {
 | 
				
			||||||
 | 
					            'Key': key,
 | 
				
			||||||
 | 
					            'accept': 'application/json',
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        self._email = email
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def reportEmailRep(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        This function get the report of the email
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        report = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res = get(
 | 
				
			||||||
 | 
					            f"{self._url}/{self._email}",
 | 
				
			||||||
 | 
					            headers=self._headers
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        js = res.json()
 | 
				
			||||||
 | 
					        if res.status_code == 401:
 | 
				
			||||||
 | 
					            report['error'] = js['reason']
 | 
				
			||||||
 | 
					            return report
 | 
				
			||||||
 | 
					        if res.status_code != 200:
 | 
				
			||||||
 | 
					            report['error'] = 'Failed to get the report of the email'
 | 
				
			||||||
 | 
					            return report
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        report['reputation'] = js['reputation']
 | 
				
			||||||
 | 
					        report['suspicious'] = js['suspicious']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return report
 | 
				
			||||||
							
								
								
									
										38
									
								
								hashing.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										38
									
								
								hashing.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import hashlib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Hash:
 | 
				
			||||||
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def hashMd5(self, f):
 | 
				
			||||||
 | 
					        md5 = hashlib.md5()
 | 
				
			||||||
 | 
					        with open(f, "rb") as data:
 | 
				
			||||||
 | 
					            md5.update(data.read())
 | 
				
			||||||
 | 
					        return md5.hexdigest()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def hashSha1(self, f):
 | 
				
			||||||
 | 
					        sha1 = hashlib.sha1()
 | 
				
			||||||
 | 
					        with open(f, "rb") as data:
 | 
				
			||||||
 | 
					            sha1.update(data.read())
 | 
				
			||||||
 | 
					        return sha1.hexdigest()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def hashSha256(self, f):
 | 
				
			||||||
 | 
					        sha256 = hashlib.sha256()
 | 
				
			||||||
 | 
					        with open(f, "rb") as data:
 | 
				
			||||||
 | 
					            sha256.update(data.read())
 | 
				
			||||||
 | 
					        return sha256.hexdigest()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def hashSha384(self, f):
 | 
				
			||||||
 | 
					        sha384 = hashlib.sha384()
 | 
				
			||||||
 | 
					        with open(f, "rb") as data:
 | 
				
			||||||
 | 
					            sha384.update(data.read())
 | 
				
			||||||
 | 
					        return sha384.hexdigest()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def hashSha512(self, f):
 | 
				
			||||||
 | 
					        sha512 = hashlib.sha512()
 | 
				
			||||||
 | 
					        with open(f, "rb") as data:
 | 
				
			||||||
 | 
					            sha512.update(data.read())
 | 
				
			||||||
 | 
					        return sha512.hexdigest()
 | 
				
			||||||
							
								
								
									
										78
									
								
								macchecker.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										78
									
								
								macchecker.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from requests import get
 | 
				
			||||||
 | 
					from os.path import isfile
 | 
				
			||||||
 | 
					from re import compile, match
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MACChecker:
 | 
				
			||||||
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
					        self._url = "https://standards-oui.ieee.org/oui/oui.txt"
 | 
				
			||||||
 | 
					        self._ouiTextFile = "oui.txt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def updateOUIDb(self):
 | 
				
			||||||
 | 
					        print("Updating the OUI database from IEEE")
 | 
				
			||||||
 | 
					        report = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # We download the data from IEEE
 | 
				
			||||||
 | 
					        oui = get(self._url)
 | 
				
			||||||
 | 
					        if oui.status_code != 200:
 | 
				
			||||||
 | 
					            report['success'] = False
 | 
				
			||||||
 | 
					            exit(1)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        with open(self._ouiTextFile, "w") as f:
 | 
				
			||||||
 | 
					            f.write(oui.text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        report['success'] = True
 | 
				
			||||||
 | 
					        return report
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def parseMACAddress(self, mac):
 | 
				
			||||||
 | 
					        report = dict()
 | 
				
			||||||
 | 
					        report['hw'] = mac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ':' in mac:
 | 
				
			||||||
 | 
					            mac = mac.replace(":", "-")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Check if mac is valid
 | 
				
			||||||
 | 
					        regex = "[a-fA-F0-9]{2}-[a-fA-F0-9]{2}-[a-fA-F0-9]{2}-[a-fA-F0-9]{2}-[a-fA-F0-9]{2}-[a-fA-F0-9]{2}"
 | 
				
			||||||
 | 
					        compiled = compile(regex)
 | 
				
			||||||
 | 
					        if not compiled.match(mac):
 | 
				
			||||||
 | 
					            print("Not a valid MAC address")
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Check if the oui.txt file exist
 | 
				
			||||||
 | 
					        if not isfile(self._ouiTextFile):
 | 
				
			||||||
 | 
					            report['db'] = self.updateOUIDb() 
 | 
				
			||||||
 | 
					        entries = self._parseOUIFile()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        macSplitted = mac.split("-")
 | 
				
			||||||
 | 
					        oui = macSplitted[0] + macSplitted[1] + macSplitted[2]
 | 
				
			||||||
 | 
					        oui = oui.upper()
 | 
				
			||||||
 | 
					        report['oui'] = oui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        f = self._parseOUIFile()
 | 
				
			||||||
 | 
					        for entries in f.keys():
 | 
				
			||||||
 | 
					            if oui == entries:
 | 
				
			||||||
 | 
					                report['vendor'] = f[entries][0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return report
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _parseOUIFile(self):
 | 
				
			||||||
 | 
					        data = list()
 | 
				
			||||||
 | 
					        entries = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with open(self._ouiTextFile, "r") as f:
 | 
				
			||||||
 | 
					            data = f.readlines()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Remove the "header" on the file
 | 
				
			||||||
 | 
					        d = data[4:]
 | 
				
			||||||
 | 
					        regex = "[a-zA-Z0-9]{6}"
 | 
				
			||||||
 | 
					        compiled = compile(regex)
 | 
				
			||||||
 | 
					        for entry in d:
 | 
				
			||||||
 | 
					            s_entry = entry.split("\t")
 | 
				
			||||||
 | 
					            s = len(s_entry)
 | 
				
			||||||
 | 
					            if compiled.match(s_entry[0]):
 | 
				
			||||||
 | 
					                oui = s_entry[0].split(" ")
 | 
				
			||||||
 | 
					                entries[oui[0]] = s_entry[s - 1: s]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return entries
 | 
				
			||||||
							
								
								
									
										338
									
								
								main.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										338
									
								
								main.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,338 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/venv python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from argparse import ArgumentParser
 | 
				
			||||||
 | 
					from config import VT_ATTRIBUTES_MAPPING, PROJECT_NAME
 | 
				
			||||||
 | 
					from vt import VT
 | 
				
			||||||
 | 
					from dnschecker import DNSChecker as DNS
 | 
				
			||||||
 | 
					from emailchecker import EmailChecker
 | 
				
			||||||
 | 
					from macchecker import MACChecker 
 | 
				
			||||||
 | 
					import ipaddress
 | 
				
			||||||
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					from hashing import Hash
 | 
				
			||||||
 | 
					from os.path import exists
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def checkArguments():
 | 
				
			||||||
 | 
					    parser = ArgumentParser(description=PROJECT_NAME)
 | 
				
			||||||
 | 
					    parser.add_argument('-c', '--config', help='Config file')
 | 
				
			||||||
 | 
					    # For dns command
 | 
				
			||||||
 | 
					    parser.add_argument('--dns', help='Get domain name information', action="store_true")
 | 
				
			||||||
 | 
					    parser.add_argument('--domain', help='Get domain name information')
 | 
				
			||||||
 | 
					    parser.add_argument('--host', help='Get domain name information')
 | 
				
			||||||
 | 
					    parser.add_argument('--ip', help='Get IP information')
 | 
				
			||||||
 | 
					    # For hash command
 | 
				
			||||||
 | 
					    parser.add_argument('--hashfile', help='Hash file', action='store_true')
 | 
				
			||||||
 | 
					    parser.add_argument('--scanvt', help='If specified, scan the hash with VirusTotal', action='store_true')
 | 
				
			||||||
 | 
					    parser.add_argument('--md5', help='Hash file')
 | 
				
			||||||
 | 
					    parser.add_argument('--sha1', help='Hash file')
 | 
				
			||||||
 | 
					    parser.add_argument('--sha256', help='Hash file')
 | 
				
			||||||
 | 
					    parser.add_argument('--sha384', help='Hash file')
 | 
				
			||||||
 | 
					    parser.add_argument('--sha512', help='Hash file')
 | 
				
			||||||
 | 
					    parser.add_argument('--hash', help='Get information about the hash')
 | 
				
			||||||
 | 
					    # For email command
 | 
				
			||||||
 | 
					    parser.add_argument('--email', help='Get email reputation', action='store_true')
 | 
				
			||||||
 | 
					    parser.add_argument('--emailrep', help='Get email reputation')
 | 
				
			||||||
 | 
					    # For mac command
 | 
				
			||||||
 | 
					    parser.add_argument('--mac', help='Get mac information')
 | 
				
			||||||
 | 
					    parser.add_argument('--macdb', help='Update database of OUI', action="store_true")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def usage():
 | 
				
			||||||
 | 
					    print("------------------------------")
 | 
				
			||||||
 | 
					    print(f"|           {PROJECT_NAME}           |")
 | 
				
			||||||
 | 
					    print("------------------------------\n")
 | 
				
			||||||
 | 
					    print("A tool for SOC analyst\n")
 | 
				
			||||||
 | 
					    print("Usage: main.py [COMMAND]")
 | 
				
			||||||
 | 
					    print("-c PATH, --config PATH\t\tConfig file - mandatory")
 | 
				
			||||||
 | 
					    print("--hashfile\t\t\tHash the file and check in VirusTotal")
 | 
				
			||||||
 | 
					    print("--hash HASH\t\t\tAnalyse the hash from VirusTotal")
 | 
				
			||||||
 | 
					    print("--dns \t\t\t\tGet information regarding the domain with whois and VirusTotal")
 | 
				
			||||||
 | 
					    print("--email\t\t\t\tGet informations about an email and check if has been compromised")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print("\n--dns command:")
 | 
				
			||||||
 | 
					    print("\t --domain FQDN\t\tScan and get domain information")
 | 
				
			||||||
 | 
					    print("\t --host HOST\t\tScan and get host information")
 | 
				
			||||||
 | 
					    print("\t --ip IP\t\tScan and get IP information")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print("\n--hashfile command:")
 | 
				
			||||||
 | 
					    print("\t --md5 FILE\t\tGet the MD5 hash of the file")
 | 
				
			||||||
 | 
					    print("\t --sha1 FILE\t\tGet the SHA256 of the file")
 | 
				
			||||||
 | 
					    print("\t --sha256 FILE\t\tGet the SHA256 of the file")
 | 
				
			||||||
 | 
					    print("\t --sha384 FILE\t\tGet the SHA384 of the file")
 | 
				
			||||||
 | 
					    print("\t --sha512 FILE\t\tGet the SHA512 of the file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print("\n--email command")
 | 
				
			||||||
 | 
					    print("\t --emailrep\t\tGet the email reputation report")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print("\n--mac command")
 | 
				
			||||||
 | 
					    print("--mac MAC\t\t\tGet mac information")
 | 
				
			||||||
 | 
					    print("--macdb\t\t\t\tUpdate the OUI database")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def readConfigFile(config):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					        This function read the config file
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    data = {}
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        with open(config, 'r') as f:
 | 
				
			||||||
 | 
					            lines = f.readlines()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Split each line into te dictionary
 | 
				
			||||||
 | 
					        for line in lines:
 | 
				
			||||||
 | 
					            l = line.split(":")
 | 
				
			||||||
 | 
					            lineParsed = l[1].replace(" ", "")
 | 
				
			||||||
 | 
					            lineParsed = lineParsed.replace("\n", "")
 | 
				
			||||||
 | 
					            data[l[0]] = lineParsed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    except FileNotFoundError:
 | 
				
			||||||
 | 
					        return None
 | 
				
			||||||
 | 
					    return data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    args = checkArguments()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not args.config:
 | 
				
			||||||
 | 
					        usage()
 | 
				
			||||||
 | 
					        exit(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Read the config file
 | 
				
			||||||
 | 
					    config = readConfigFile(args.config)
 | 
				
			||||||
 | 
					    if config is None:
 | 
				
			||||||
 | 
					        print("Failed to read the config file")
 | 
				
			||||||
 | 
					        exit(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    report = dict()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Analyse DNS
 | 
				
			||||||
 | 
					    if args.dns:
 | 
				
			||||||
 | 
					        if args.domain:
 | 
				
			||||||
 | 
					            _parsingDomain(config, args.domain, report)
 | 
				
			||||||
 | 
					        if args.host:
 | 
				
			||||||
 | 
					            _parsingHost(config, args.host, report)
 | 
				
			||||||
 | 
					        if args.ip:
 | 
				
			||||||
 | 
					            _parsingIP(config, args.ip, report)
 | 
				
			||||||
 | 
					    # Analyse hash file
 | 
				
			||||||
 | 
					    if args.hashfile:
 | 
				
			||||||
 | 
					        h = Hash()
 | 
				
			||||||
 | 
					        dispatcher = {
 | 
				
			||||||
 | 
					           "MD5": h.hashMd5,
 | 
				
			||||||
 | 
					           "SHA1": h.hashSha1,
 | 
				
			||||||
 | 
					           "SHA256": h.hashSha256,
 | 
				
			||||||
 | 
					           "SHA384": h.hashSha384,
 | 
				
			||||||
 | 
					           "SHA512": h.hashSha512,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if args.md5:
 | 
				
			||||||
 | 
					            hashType = "MD5"
 | 
				
			||||||
 | 
					            filename = args.md5
 | 
				
			||||||
 | 
					        if args.sha1:
 | 
				
			||||||
 | 
					            hashType = "SHA1"
 | 
				
			||||||
 | 
					            filename = args.sha1
 | 
				
			||||||
 | 
					        if args.sha256:
 | 
				
			||||||
 | 
					            hashType = "SHA256"
 | 
				
			||||||
 | 
					            filename = args.sha256
 | 
				
			||||||
 | 
					        if args.sha384:
 | 
				
			||||||
 | 
					            hashType = "SHA384"
 | 
				
			||||||
 | 
					            filename = args.sha384
 | 
				
			||||||
 | 
					        if args.sha512:
 | 
				
			||||||
 | 
					            hashType = "SHA512"
 | 
				
			||||||
 | 
					            filename = args.sha512
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if not exists(filename):
 | 
				
			||||||
 | 
					            print(f"File {filename} do not exist")
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            res = dispatcher[hashType](filename)
 | 
				
			||||||
 | 
					            print(f"{hashType} hash: {res}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if args.scanvt:
 | 
				
			||||||
 | 
					                _parsingHash(config, res, report)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Analyse the hash
 | 
				
			||||||
 | 
					    if args.hash:
 | 
				
			||||||
 | 
					        _parsingHash(config, args.hash, report)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Analyse the email
 | 
				
			||||||
 | 
					    if args.email:
 | 
				
			||||||
 | 
					        if args.emailrep:
 | 
				
			||||||
 | 
					            _parsingEmail(config, args.emailrep)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Analyse mac address
 | 
				
			||||||
 | 
					    if args.macdb:
 | 
				
			||||||
 | 
					        _parseMACAddress(mac=None, db=True)
 | 
				
			||||||
 | 
					    if args.mac:
 | 
				
			||||||
 | 
					        _parseMACAddress(mac=args.mac)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _parseMACAddress(mac=None, db=False):
 | 
				
			||||||
 | 
					    macchecker = MACChecker()
 | 
				
			||||||
 | 
					    report = dict()
 | 
				
			||||||
 | 
					    if db: 
 | 
				
			||||||
 | 
					        report['db'] = macchecker.updateOUIDb()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if mac is not None:
 | 
				
			||||||
 | 
					        report['mac'] = macchecker.parseMACAddress(mac)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print("----------------------------")
 | 
				
			||||||
 | 
					    print("|        MAC report        |")
 | 
				
			||||||
 | 
					    print("----------------------------")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if 'db' in report:
 | 
				
			||||||
 | 
					        print(f"The update of the OUI db: {report['db']['success']}") 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if 'mac' in report:
 | 
				
			||||||
 | 
					        print(f"MAC address: {report['mac']['hw']}")
 | 
				
			||||||
 | 
					        print(f"OUI: {report['mac']['oui']}")
 | 
				
			||||||
 | 
					        print(f"Vendor: {report['mac']['vendor']}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _parsingEmail(config, email):
 | 
				
			||||||
 | 
					    # Check if the email specified is correct
 | 
				
			||||||
 | 
					    regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b'
 | 
				
			||||||
 | 
					    if not search(regex, email):
 | 
				
			||||||
 | 
					        print("Please, specify a valid email address")
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    report = dict()
 | 
				
			||||||
 | 
					    emailChecker = EmailChecker(config['api_key_emailrep'], email)
 | 
				
			||||||
 | 
					    report['emailrep'] = emailChecker.reportEmailRep()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print("----------------------------")
 | 
				
			||||||
 | 
					    print("|     Email reputation     |")
 | 
				
			||||||
 | 
					    print("----------------------------")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if 'error' in report['emailrep']:
 | 
				
			||||||
 | 
					        print(f"Error: {report['emailrep']['error']}")
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    emailrep = report['emailrep']
 | 
				
			||||||
 | 
					    print(f"Reputation: {emailrep['reputation']}")
 | 
				
			||||||
 | 
					    print(f"Suspicious: {emailrep['suspicious']}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _parsingHash(config, h, report):
 | 
				
			||||||
 | 
					    report = dict() 
 | 
				
			||||||
 | 
					    vt = VT(config['api_key_vt'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vt.getRateFromHash(h, report)
 | 
				
			||||||
 | 
					    print("\n----------------------")
 | 
				
			||||||
 | 
					    print("|     VirusTotal     |")
 | 
				
			||||||
 | 
					    print("----------------------")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if 'error' in report:
 | 
				
			||||||
 | 
					        print("Error, can not find any informations")
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # File
 | 
				
			||||||
 | 
					    print("\nFile information:")
 | 
				
			||||||
 | 
					    f = report['results']['file']
 | 
				
			||||||
 | 
					    print(f"\tMD5: {f['md5']}")
 | 
				
			||||||
 | 
					    print(f"\tSHA1: {f['sha1']}")
 | 
				
			||||||
 | 
					    print(f"\tMagic: {f['magic']}")
 | 
				
			||||||
 | 
					    print(f"\tFile type: {f['filetype']}")
 | 
				
			||||||
 | 
					    print(f"\tSize: {f['size']}")
 | 
				
			||||||
 | 
					    print(f"\tExtension: {f['extension']}")
 | 
				
			||||||
 | 
					    print(f"\tFirst seen: {f['first_seen']}")
 | 
				
			||||||
 | 
					    print(f"\tLast analysis: {f['last_analysis']}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Vendors
 | 
				
			||||||
 | 
					    vendors = report['results']['vendors']
 | 
				
			||||||
 | 
					    print("\nVendors:")
 | 
				
			||||||
 | 
					    print(f"\tTotal vendors: {vendors['total_vendors']}")
 | 
				
			||||||
 | 
					    print(f"\tCategorized as malicious: {vendors['total_malicious']}\n")
 | 
				
			||||||
 | 
					    for key in vendors['result']:
 | 
				
			||||||
 | 
					        print(f"\t{key}: {vendors['result'][key]}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _parsingIP(config, ip, report):
 | 
				
			||||||
 | 
					    # Check if it's an IP address
 | 
				
			||||||
 | 
					    vt = VT(config['api_key_vt'])
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        ip_obj = ipaddress.ip_address(ip)
 | 
				
			||||||
 | 
					    except ValueError:
 | 
				
			||||||
 | 
					        print("The IP is not valid")
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    report['ip'] = dict()
 | 
				
			||||||
 | 
					    report['ip'] = vt.getIPVirusTotal(ip)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if 'error' not in report['ip']:
 | 
				
			||||||
 | 
					        print("----------------------------")
 | 
				
			||||||
 | 
					        print("|      IP Informations     |")
 | 
				
			||||||
 | 
					        print("----------------------------")
 | 
				
			||||||
 | 
					        for vt in VT_ATTRIBUTES_MAPPING.keys():
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                vtAttributes = VT_ATTRIBUTES_MAPPING[vt]
 | 
				
			||||||
 | 
					                if 'date' in vtAttributes:
 | 
				
			||||||
 | 
					                    value = datetime.fromtimestamp(int(report['ip'][vt]))
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    value = report['ip'][vt]
 | 
				
			||||||
 | 
					                print(f"{vt}: {value}")
 | 
				
			||||||
 | 
					            except KeyError:
 | 
				
			||||||
 | 
					                print(f"Cannot find the key {vt}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _parsingHost(config, fqdn, report):
 | 
				
			||||||
 | 
					    vt = VT(config['api_key_vt'])
 | 
				
			||||||
 | 
					    dns = DNS(config['api_key_vt'], fqdn, {'A': 'address'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Resolv and print results
 | 
				
			||||||
 | 
					    report['resolving'] = dns.resolver()
 | 
				
			||||||
 | 
					    _printDNSResolving(report['resolving'])
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Print VirusTotal
 | 
				
			||||||
 | 
					    report['vt'] = dict()
 | 
				
			||||||
 | 
					    vt.getDomainReport(fqdn, report['vt'])
 | 
				
			||||||
 | 
					    _printDNSVirusTotal(report['vt'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _parsingDomain(config, fqdn, report):
 | 
				
			||||||
 | 
					    vt = VT(config['api_key_vt'])
 | 
				
			||||||
 | 
					    dns = DNS(config['api_key_vt'], fqdn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Check if domain exist
 | 
				
			||||||
 | 
					    if not dns.checkDomainExist():
 | 
				
			||||||
 | 
					        print(f"The domain {fqdn} do not exist")
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Resolving domain
 | 
				
			||||||
 | 
					    report['resolving'] = dns.resolver()
 | 
				
			||||||
 | 
					    _printDNSResolving(report['resolving'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Whois request and print the result
 | 
				
			||||||
 | 
					    report['whois'] = dns.whois()
 | 
				
			||||||
 | 
					    _printDNSWhois(report['whois'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Print VirusTotal
 | 
				
			||||||
 | 
					    report['vt'] = dict()
 | 
				
			||||||
 | 
					    vt.getDomainReport(fqdn, report['vt'])
 | 
				
			||||||
 | 
					    _printDNSVirusTotal(report['vt'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _printDNSResolving(report):
 | 
				
			||||||
 | 
					    print("----------------------")
 | 
				
			||||||
 | 
					    print("|     resolving      |")
 | 
				
			||||||
 | 
					    print("----------------------")
 | 
				
			||||||
 | 
					    for key in report.keys():
 | 
				
			||||||
 | 
					        print(f"{key}: ")
 | 
				
			||||||
 | 
					        for entry in report[key]:
 | 
				
			||||||
 | 
					            for subkey in entry.keys():
 | 
				
			||||||
 | 
					                value = entry[subkey]
 | 
				
			||||||
 | 
					                if isinstance(value, bytes):
 | 
				
			||||||
 | 
					                    value = value.decode()
 | 
				
			||||||
 | 
					                print(f"\t{subkey}: {value}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _printDNSVirusTotal(report):
 | 
				
			||||||
 | 
					    print("\n----------------------")
 | 
				
			||||||
 | 
					    print("|     VirusTotal     |")
 | 
				
			||||||
 | 
					    print("----------------------")
 | 
				
			||||||
 | 
					    for key in report:
 | 
				
			||||||
 | 
					        print(f"{key}: {report[key]}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _printDNSWhois(report):
 | 
				
			||||||
 | 
					    print("\n----------------------")
 | 
				
			||||||
 | 
					    print("|        whois       |")
 | 
				
			||||||
 | 
					    print("----------------------")
 | 
				
			||||||
 | 
					    for key in report.keys():
 | 
				
			||||||
 | 
					        if isinstance(report[key], list):
 | 
				
			||||||
 | 
					            print(f"{key}:")
 | 
				
			||||||
 | 
					            for value in report[key]:
 | 
				
			||||||
 | 
					                print(f"\t{value}")
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print(f"{key}: {report[key]}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
							
								
								
									
										157
									
								
								reports.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										157
									
								
								reports.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/venv python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					from os import mkdir
 | 
				
			||||||
 | 
					from config import VT_ATTRIBUTES_MAPPING
 | 
				
			||||||
 | 
					import jinja2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def generateHtmlReport(data):
 | 
				
			||||||
 | 
					    env = jinja2.Environment(
 | 
				
			||||||
 | 
					        loader=jinja2.FileSystemLoader("reports/templates"),
 | 
				
			||||||
 | 
					        autoescape=jinja2.select_autoescape()
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _queriesReport(data['queries'], env)
 | 
				
			||||||
 | 
					    _graphicsReport(data['graphics'], env)
 | 
				
			||||||
 | 
					    _vtReport(data['vt'], env)
 | 
				
			||||||
 | 
					    _dnsTunnelingReports(data['dnstunneling'], env)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _indexReport():
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _queriesReport(queries, env):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    This function generate the report for queries
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    today = getTodayDate()
 | 
				
			||||||
 | 
					    dataJinja2 = dict()
 | 
				
			||||||
 | 
					    dataJinja2['title'] = 'Queries'
 | 
				
			||||||
 | 
					    dataJinja2['year'] = '2023'
 | 
				
			||||||
 | 
					    dataJinja2['queries'] = queries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tmpl = env.get_template('queries.html.j2')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render = tmpl.render(data=dataJinja2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with open(f"reports/{today}/reports_queries.html", "w") as f:
 | 
				
			||||||
 | 
					        f.write(render)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _graphicsReport(graphics, env):
 | 
				
			||||||
 | 
					    today = getTodayDate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dataJinja2 = dict()
 | 
				
			||||||
 | 
					    dataJinja2['title'] = 'Graphics'
 | 
				
			||||||
 | 
					    dataJinja2['year'] = '2023'
 | 
				
			||||||
 | 
					    dataJinja2['graphics'] = graphics
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tmpl = env.get_template('graphics.html.j2')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render = tmpl.render(data=dataJinja2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with open(f"reports/{today}/reports_graphics.html", "w") as f:
 | 
				
			||||||
 | 
					        f.write(render)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _vtReport(vt, env):
 | 
				
			||||||
 | 
					    today = getTodayDate()
 | 
				
			||||||
 | 
					    # For testing
 | 
				
			||||||
 | 
					    #vt = list()
 | 
				
			||||||
 | 
					    #vt.append({
 | 
				
			||||||
 | 
					    #    'ip': '1.2.3.4',
 | 
				
			||||||
 | 
					    #    'asn': 3215,
 | 
				
			||||||
 | 
					    #    'as_owner': 'Orange',
 | 
				
			||||||
 | 
					    #    'continent': 'EU',
 | 
				
			||||||
 | 
					    #    'country': 'FR',
 | 
				
			||||||
 | 
					    #    'last_analysis_date': 1686839532,
 | 
				
			||||||
 | 
					    #    'regional_internet_registry': 'RIPE NCC',
 | 
				
			||||||
 | 
					    #    'network': '1.2.3.0/24'
 | 
				
			||||||
 | 
					    #})
 | 
				
			||||||
 | 
					    #vt.append({
 | 
				
			||||||
 | 
					    #    'ip': '2.2.2.1',
 | 
				
			||||||
 | 
					    #    'asn': 3215,
 | 
				
			||||||
 | 
					    #    'as_owner': 'Orange',
 | 
				
			||||||
 | 
					    #    'continent': 'EU',
 | 
				
			||||||
 | 
					    #    'country': 'FR',
 | 
				
			||||||
 | 
					    #    'last_analysis_date': 1686839532,
 | 
				
			||||||
 | 
					    #    'regional_internet_registry': 'RIPE NCC',
 | 
				
			||||||
 | 
					    #    'network': '2.2.2.0/24'
 | 
				
			||||||
 | 
					    #})
 | 
				
			||||||
 | 
					    #vt.append({
 | 
				
			||||||
 | 
					    #    'ip': '3.3.3.1',
 | 
				
			||||||
 | 
					    #    'asn': 3215,
 | 
				
			||||||
 | 
					    #    'as_owner': 'Orange',
 | 
				
			||||||
 | 
					    #    'continent': 'EU',
 | 
				
			||||||
 | 
					    #    'country': 'FR',
 | 
				
			||||||
 | 
					    #    'last_analysis_date': 1686839532,
 | 
				
			||||||
 | 
					    #    'regional_internet_registry': 'RIPE NCC',
 | 
				
			||||||
 | 
					    #    'network': '3.3.3.0/24'
 | 
				
			||||||
 | 
					    #})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dataJinja2 = dict()
 | 
				
			||||||
 | 
					    dataJinja2['title'] = 'VirusTotal'
 | 
				
			||||||
 | 
					    dataJinja2['year'] = '2023'
 | 
				
			||||||
 | 
					    dataJinja2['vt'] = list()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tmpl = env.get_template('vt.html.j2')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    body = str()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for entry in vt:
 | 
				
			||||||
 | 
					        vtEntry = dict()
 | 
				
			||||||
 | 
					        if 'error' not in entry:
 | 
				
			||||||
 | 
					            for vt in VT_ATTRIBUTES_MAPPING.keys():
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    vtAttributes = VT_ATTRIBUTES_MAPPING[vt]
 | 
				
			||||||
 | 
					                    if 'date' in vtAttributes:
 | 
				
			||||||
 | 
					                        value = datetime.fromtimestamp(int(entry[vt]))
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        value = entry[vt]
 | 
				
			||||||
 | 
					                    vtEntry[vt] = value
 | 
				
			||||||
 | 
					                except KeyError:
 | 
				
			||||||
 | 
					                    pass
 | 
				
			||||||
 | 
					            dataJinja2['vt'].append({
 | 
				
			||||||
 | 
					                'ip': entry['ip'],
 | 
				
			||||||
 | 
					                'data': vtEntry
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render = tmpl.render(data=dataJinja2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with open(f"reports/{today}/reports_vt.html", "w") as f:
 | 
				
			||||||
 | 
					        f.write(render)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _dnsTunnelingReports(dnstunneling, env):
 | 
				
			||||||
 | 
					    today = getTodayDate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dataJinja2 = dict()
 | 
				
			||||||
 | 
					    dataJinja2['title'] = 'DNS Tunneling'
 | 
				
			||||||
 | 
					    dataJinja2['year'] = '2023'
 | 
				
			||||||
 | 
					    dataJinja2['dnstunneling'] = dnstunneling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tmpl = env.get_template('dnsTunneling.html.j2')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    render = tmpl.render(data=dataJinja2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with open(f"reports/{today}/reports_dns_tunneling.html", "w") as f:
 | 
				
			||||||
 | 
					        f.write(render)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def createReportsDirectory():
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    This function will create the reports directory
 | 
				
			||||||
 | 
					    Return the report name or None if failed
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    today = getTodayDate()
 | 
				
			||||||
 | 
					    name = f"reports/{today}"
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        mkdir(name)
 | 
				
			||||||
 | 
					    except FileExistsError: 
 | 
				
			||||||
 | 
					        print("Reports directory already created")
 | 
				
			||||||
 | 
					        return name
 | 
				
			||||||
 | 
					    return name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def getTodayDate():
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    This function genrate the today datetime at this format:
 | 
				
			||||||
 | 
					        year_month_day
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    return datetime.now().isoformat()[0:10].replace("-", "_")
 | 
				
			||||||
							
								
								
									
										10
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										10
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					pip
 | 
				
			||||||
 | 
					scapy
 | 
				
			||||||
 | 
					ArgumentParser
 | 
				
			||||||
 | 
					matplotlib
 | 
				
			||||||
 | 
					numpy
 | 
				
			||||||
 | 
					vt-py
 | 
				
			||||||
 | 
					requests
 | 
				
			||||||
 | 
					jinja2
 | 
				
			||||||
 | 
					python-whois
 | 
				
			||||||
 | 
					git+https://github.com/rthalley/dnspython.git
 | 
				
			||||||
							
								
								
									
										31
									
								
								tests/oui.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										31
									
								
								tests/oui.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					import requests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					data = str()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# We download the data from IEEE
 | 
				
			||||||
 | 
					oui = requests.get("https://standards-oui.ieee.org/oui/oui.txt")
 | 
				
			||||||
 | 
					if oui.status_code != 200:
 | 
				
			||||||
 | 
					    exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Convert to list
 | 
				
			||||||
 | 
					l = list()
 | 
				
			||||||
 | 
					line = str()
 | 
				
			||||||
 | 
					for c in oui.text:
 | 
				
			||||||
 | 
					    line += c
 | 
				
			||||||
 | 
					    if c == "\n":
 | 
				
			||||||
 | 
					        l.append(line)
 | 
				
			||||||
 | 
					        line = str()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Remove the "header" on the file
 | 
				
			||||||
 | 
					d = l[4:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# We get all OUI
 | 
				
			||||||
 | 
					regex = "[a-zA-Z0-9]{6}"
 | 
				
			||||||
 | 
					compiled = re.compile(regex)
 | 
				
			||||||
 | 
					for entry in d:
 | 
				
			||||||
 | 
					    s_entry = entry.split(" ")
 | 
				
			||||||
 | 
					    if compiled.match(s_entry[0]):
 | 
				
			||||||
 | 
					        print(s_entry[0])
 | 
				
			||||||
							
								
								
									
										123
									
								
								vt.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										123
									
								
								vt.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,123 @@
 | 
				
			|||||||
 | 
					#!/ur/bin/env python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import requests
 | 
				
			||||||
 | 
					from config import VT_ATTRIBUTES_MAPPING
 | 
				
			||||||
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VT:
 | 
				
			||||||
 | 
					    def __init__(self, api_key):
 | 
				
			||||||
 | 
					        self._url = "https://www.virustotal.com/api/v3"
 | 
				
			||||||
 | 
					        self._headers = {
 | 
				
			||||||
 | 
					            'x-apikey': api_key,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getIPVirusTotal(self, ip):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        This function get IP information from VirusTotal
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        res = requests.get(
 | 
				
			||||||
 | 
					            f"{self._url}/ip_addresses/{ip}",
 | 
				
			||||||
 | 
					            headers=self._headers
 | 
				
			||||||
 | 
					        ).json()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        data = dict()
 | 
				
			||||||
 | 
					        data['ip'] = ip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'error' in res:
 | 
				
			||||||
 | 
					            report.append({
 | 
				
			||||||
 | 
					                'error': res['error']['message'],
 | 
				
			||||||
 | 
					                'ip': ip
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vt = res['data']['attributes']
 | 
				
			||||||
 | 
					        for entry in VT_ATTRIBUTES_MAPPING.keys():
 | 
				
			||||||
 | 
					            if entry in vt:
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    data[entry] = vt[entry]
 | 
				
			||||||
 | 
					                except KeyError:
 | 
				
			||||||
 | 
					                    data[entry] = 'Unknown'
 | 
				
			||||||
 | 
					        return data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getDomainReport(self, fqdn, report):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        This function get the report for the specific domain 
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        res = requests.get(
 | 
				
			||||||
 | 
					            f"{self._url}/domains/{fqdn}",
 | 
				
			||||||
 | 
					            headers=self._headers
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        js = res.json()
 | 
				
			||||||
 | 
					        report['reputation'] = js['data']['attributes']['reputation']
 | 
				
			||||||
 | 
					        report['last_update'] = \
 | 
				
			||||||
 | 
					            datetime.fromtimestamp(js['data']['attributes']['last_update_date'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Get number of security vendors
 | 
				
			||||||
 | 
					        report['total_vendors'] = 0
 | 
				
			||||||
 | 
					        report['clean'] = 0
 | 
				
			||||||
 | 
					        report['unrated'] = 0
 | 
				
			||||||
 | 
					        report['malicious'] = 0
 | 
				
			||||||
 | 
					        vendors = js['data']['attributes']['last_analysis_results']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for entry in vendors:
 | 
				
			||||||
 | 
					            report['total_vendors'] += 1
 | 
				
			||||||
 | 
					            if vendors[entry]['result'] == 'clean':
 | 
				
			||||||
 | 
					                report['clean'] += 1
 | 
				
			||||||
 | 
					            elif vendors[entry]['result'] == 'unrated':
 | 
				
			||||||
 | 
					                report['unrated'] += 1
 | 
				
			||||||
 | 
					            elif vendors[entry]['result'] == 'malicious':
 | 
				
			||||||
 | 
					                report['malicious'] += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getRateFromHash(self, h, report):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        This function get the report of the hash specified by the parameter h
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        headers = self._headers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        res = requests.get(
 | 
				
			||||||
 | 
					            f"{self._url}/files/{h}",
 | 
				
			||||||
 | 
					            headers=self._headers
 | 
				
			||||||
 | 
					        ).json()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'error' in res:
 | 
				
			||||||
 | 
					            report["error"] = "Can not find the result"
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        attributes = res['data']['attributes']
 | 
				
			||||||
 | 
					        report['results'] = dict()
 | 
				
			||||||
 | 
					        report['results']['file'] = dict()
 | 
				
			||||||
 | 
					        report['results']['file']['magic'] = attributes['magic']
 | 
				
			||||||
 | 
					        report['results']['file']['sha1'] = attributes['sha1']
 | 
				
			||||||
 | 
					        report['results']['file']['md5'] = attributes['md5']
 | 
				
			||||||
 | 
					        report['results']['file']['filetype'] = attributes['detectiteasy']['filetype']
 | 
				
			||||||
 | 
					        report['results']['file']['size'] = attributes['size']
 | 
				
			||||||
 | 
					        report['results']['file']['extension'] = attributes['type_extension']
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            report['results']['file']['first_seen'] = \
 | 
				
			||||||
 | 
					                datetime.fromtimestamp(attributes['first_seen_itw_date'])
 | 
				
			||||||
 | 
					        except KeyError:
 | 
				
			||||||
 | 
					            report['results']['file']['first_seen'] = "Unknown"
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        report['results']['file']['last_analysis'] = \
 | 
				
			||||||
 | 
					            datetime.fromtimestamp(attributes['last_analysis_date'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Identify vendors 
 | 
				
			||||||
 | 
					        report['results']['vendors'] = dict()
 | 
				
			||||||
 | 
					        report['results']['vendors']['total_vendors'] = 0
 | 
				
			||||||
 | 
					        report['results']['vendors']['total_malicious'] = 0
 | 
				
			||||||
 | 
					        report['results']['vendors']['result'] = dict()
 | 
				
			||||||
 | 
					        report['results']['vendors']['result']['undetected'] = 0
 | 
				
			||||||
 | 
					        results = res['data']['attributes']['last_analysis_results']
 | 
				
			||||||
 | 
					        for entry in results:
 | 
				
			||||||
 | 
					            report['results']['vendors']['total_vendors'] += 1
 | 
				
			||||||
 | 
					            if results[entry]['category'] == 'undetected':
 | 
				
			||||||
 | 
					                report['results']['vendors']['result']['undetected'] += 1
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                result = results[entry]['result']
 | 
				
			||||||
 | 
					                if result not in report['results']['vendors']['result']:
 | 
				
			||||||
 | 
					                    report['results']['vendors']['result'][result] = 0
 | 
				
			||||||
 | 
					                report['results']['vendors']['result'][result] += 1
 | 
				
			||||||
 | 
					                report['results']['vendors']['total_malicious'] += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user