├── requirements.txt ├── README.md ├── Scraper.py ├── Hell0.py ├── Utils.py ├── Systeminfo.py └── DBInterface.py /requirements.txt: -------------------------------------------------------------------------------- 1 | pysocks 2 | mechanize 3 | fuzzywuzzy[speedup] 4 | beautifulsoup4 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | At first, I am not a developer! I am just an information security enthusiast interested in automating security operations. I hope my interest matches yours, and by your contribution, we could enhance this program and make it more beneficial for those concerned about their privacy and security in cyberspace. 4 | So, let's get down to business. **Hello Zero** is a straightforward yet powerful and effective tool **designed to be a part of the organization's vulnerability and risk management program**. It has been designed to gather zero-day system exploits by extracting information about all hardware and software installed on your system. **It automatically scrapes the dark web every day to track zero-day exploits that affect your system**. The current version is 1.0, which only supports the **`Windows`** platform at the moment. 5 | 6 | 7 | ## Prerequisites 8 | 9 | Required libraries: 10 | 11 | - Python-Levenshtein 12 | - FuzzyWuzzy 13 | - PySocks 14 | - Mechanize 15 | - BeautifulSoup4 16 | - PyQt5 17 | - Packaging 18 | - PySimpleGUI 19 | 20 | 21 | The prerequisites can be effortlessly installed via `pip install -r requirements.txt` command. 22 | 23 | It also requires TOR, MySQL (or any other databases), and Python 3. 24 | 25 | 26 | ## Getting Started 27 | The only thing you need to do is run the app and set the E-mail address you would like to receive alerts in "Emails.txt," and **Hello Zero** will do the rest for you. 28 | 29 | 30 | ## How it works 31 | 32 | After collecting all information about software/hardware installed on your system and their corresponding version, Hello Zero **automatically crawls the dark web for you to track any zero-day exploits that might affect your system**. After finding any defects, it will e-mail you with suitable information about what you should notice to reduce the risk of these exploits in your environment. 33 | 34 | NOTE: Hello Zero uses **fuzzy string matching** as well as string metrics to calculate the difference between sequences. 35 | 36 | ## Why do I need to use this tool? 37 | 38 | As mentioned earlier, Hello Zero has been designed to **complement your vulnerability and risk management programs**. Aside from patch management policies, we must be aware of the vulnerabilities traded on the dark web which affect our systems without any available patches. Therefore, if you are concerned about zero-day threats, this tool might be right for you. 39 | -------------------------------------------------------------------------------- /Scraper.py: -------------------------------------------------------------------------------- 1 | import socks 2 | import socket 3 | from mechanize import Browser 4 | from mechanize import HTTPError,URLError,BrowserStateError,FormNotFoundError 5 | from bs4 import BeautifulSoup 6 | 7 | class Scraper: 8 | 9 | def __init__(self): 10 | self.socks_proxy_host = '127.0.0.1' 11 | self.socks_proxy_port = 9150 12 | socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5,self.socks_proxy_host,self.socks_proxy_port) 13 | socket.socket = socks.socksocket 14 | socket.create_connection = self.create_connection 15 | 16 | def create_connection(self,address, timeout=None, source_address=None): 17 | sock = socks.socksocket() 18 | sock.connect(address) 19 | return sock 20 | 21 | def scrape(self,url): 22 | br = Browser() 23 | br.set_handle_robots(False) 24 | br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')] 25 | try: 26 | br.open(url) 27 | br.select_form(nr=0) 28 | resp=br.submit(name="agree",label="Yes, I agree") 29 | soup = BeautifulSoup(resp.read(),'html.parser') 30 | Exploits = [] 31 | exploit_table_contents = soup.find_all('div',{'class':'ExploitTableContent'}) 32 | for item in exploit_table_contents: 33 | exploit = {} 34 | tds = item.find_all('div',{'class':'td'}) 35 | exploit['Date'] = tds[0].text 36 | exploit['DESCRIPTION'] = tds[1].find('a').text 37 | exploit['Link'] = 'http://mvfjfugdwgc5uwho.onion'+tds[1].find('a')['href'] 38 | exploit['TYPE'] = tds[2].text 39 | exploit['HITS'] = tds[3].text 40 | exploit['GOLD'] = tds[9].text.replace('\t','') 41 | exploit['AUTHOR'] = tds[10].find('a').text 42 | Exploits.append(exploit) 43 | return Exploits 44 | except (HTTPError,URLError,BrowserStateError,FormNotFoundError) as e: 45 | print(e) 46 | return [] 47 | 48 | 49 | def get_exploit_info(self,url): 50 | br = Browser() 51 | br.set_handle_robots(False) 52 | br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')] 53 | try: 54 | br.open(url) 55 | br.select_form(nr=0) 56 | resp=br.submit(name="agree",label="Yes, I agree") 57 | soup = BeautifulSoup(resp.read(),'html.parser') 58 | exploit_view_table = soup.find_all('div',{'class':'exploit_view_table_content'}) 59 | exploit_info = {} 60 | exploit_info['link'] = url 61 | for item in exploit_view_table: 62 | tds = item.find_all('div',{'class':'td'}) 63 | if(tds[0].text == 'Full title'): 64 | exploit_info[tds[0].text] = tds[1].find('a').text 65 | else: 66 | exploit_info[tds[0].text] = tds[1].text 67 | 68 | return exploit_info 69 | except (HTTPError,URLError,BrowserStateError,FormNotFoundError) as e: 70 | print(e) 71 | return {} -------------------------------------------------------------------------------- /Hell0.py: -------------------------------------------------------------------------------- 1 | from Systeminfo import SystemInfo 2 | from DBInterface import DB 3 | from Scraper import Scraper 4 | import argparse 5 | import textwrap 6 | import time 7 | from Utils import * 8 | 9 | # ------------------------------------------------------------------------------------------------------------ 10 | if __name__=="__main__": 11 | 12 | parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, 13 | description=textwrap.dedent(''' 14 | ---------------------------------------------- 15 | With this software you can extract your system 16 | hardware and software information and find last 17 | exploits related to your system. 18 | ---------------------------------------------- 19 | ''')) 20 | parser.add_argument('-db','--dbname',type=str, action='store', help="databse file name ,usage: -c ") 21 | parser.add_argument('-u','--update', action='store_true', help="update system information in database file") 22 | parser.add_argument('-s','--show', action='store_true', help="show your system softwares/hardwares information") 23 | parser.add_argument('-w','--windows', action='store_true', help="find windows exploits") 24 | parser.add_argument('-hw','--hardware', action='store_true', help="find hardware exploits") 25 | parser.add_argument('-m','--multiple', action='store_true', help="find multiple exploits") 26 | parser.add_argument('-d','--date', action='store',default=time.strftime('%d-%m-%Y'), help="find exploits of this date,usage: -d "+time.strftime('%d-%m-%y')) 27 | parser.add_argument('-e','--emails', action='store', help="emails list text file name, usage: -e emails.txt") 28 | 29 | 30 | 31 | args = parser.parse_args() 32 | date = args.date 33 | types = [] 34 | 35 | if args.windows: 36 | types.append('windows') 37 | types.append('win32') 38 | if args.hardware: 39 | types.append('hardware') 40 | if args.multiple: 41 | types.append('multiple') 42 | 43 | if args.dbname: 44 | DB_NAME = args.dbname 45 | if args.update: 46 | print('DB updating started...\n'+'-'*50) 47 | print('Finding system information started...\n'+'-'*50) 48 | sysinfo = SystemInfo() 49 | db = DB() 50 | conn = db.create_connection(DB_NAME) 51 | db.create_tables(conn,DB_NAME) 52 | system_id = db.insert_system_info(conn,sysinfo.host_name,sysinfo.os_name,sysinfo.os_architecture,sysinfo.os_version, 53 | sysinfo.cpu_name,sysinfo.cpu_cores,str(sysinfo.gpu),sysinfo.bios_name,sysinfo.bios_version,sysinfo.bios_manufacturer) 54 | print('Saving system information into DB done!\n'+'-'*50) 55 | if system_id is not None: 56 | print('Finding system softwares information started,please wait...\n'+'-'*50) 57 | softwares = sysinfo.get_system_softwares() 58 | print('Finding system softwares information Done!\n'+'-'*50) 59 | for item in softwares: 60 | item.append(system_id) 61 | db.insert_softwares(conn,softwares) 62 | print('Saving system softwares information into DB done!\n'+'-'*50) 63 | conn.close() 64 | if args.emails: 65 | with open(args.emails,'r+') as f: 66 | emails = f.readlines() 67 | if args.windows or args.hardware or args.multiple: 68 | db = DB() 69 | conn = db.create_connection(DB_NAME) 70 | softwares = db.select_softwares_name(conn) 71 | sysinfo = SystemInfo() 72 | if args.show: 73 | attrs = vars(sysinfo) 74 | print('Here is Your System Hardware Information:\n'+'-'*50) 75 | print('\n'.join("%s: %s" % item for item in attrs.items())) 76 | print('Here is Your System Softwares Information:\n'+'-'*50) 77 | print('\n'.join("%s" % item for item in softwares)) 78 | conn.close() 79 | if len(softwares)==0: 80 | print('System softwares not found! Add -u to the previous command\n'+'-'*50) 81 | else: 82 | scraper = Scraper() 83 | print('Finding exploits started,please wait...\n'+'-'*50) 84 | url = 'http://mvfjfugdwgc5uwho.onion/date/{0}'.format(date) 85 | exploits = scraper.scrape(url) 86 | if len(exploits)>0: 87 | print('Founded Exploits:\n'+'-'*50) 88 | for item in exploits: 89 | print(item['DESCRIPTION'] + '| Type: ' + item['TYPE']) 90 | print('Finding exploits done!\n'+'-'*50) 91 | matched_exploits = compare(exploits,softwares,vars(sysinfo),date,types) 92 | send_exploits_to_emails(matched_exploits,emails,DB_NAME) 93 | else: 94 | print('Error!Enter emails text file name,usage: -e emails.txt\n'+'-'*50) 95 | else: 96 | print('Error!Enter database file name,usage: -db \n'+'-'*50) 97 | -------------------------------------------------------------------------------- /Utils.py: -------------------------------------------------------------------------------- 1 | from fuzzywuzzy import fuzz 2 | import smtplib, ssl 3 | from email.mime.text import MIMEText 4 | from email.mime.multipart import MIMEMultipart 5 | from DBInterface import DB 6 | from Scraper import Scraper 7 | import time 8 | 9 | Email = 'mr.developer0111@gmail.com' 10 | Password = 'yqsxdryjgqvuyegz' 11 | 12 | # https://myaccount.google.com/lesssecureapps 13 | 14 | def compare(exploits,softwares,sysinfo,date,types): 15 | print('Comparing exploits and system info started...') 16 | matched_items = [] 17 | for exploit in exploits: 18 | if exploit['Date'] == date and exploit['TYPE'] in types: 19 | for software_name in softwares: 20 | ratio = fuzz.token_set_ratio(software_name[0].lower(),exploit['DESCRIPTION'].lower()) 21 | if ratio>=75 and exploit not in matched_items: 22 | print('Your Software: ' + software_name[0] + ' | Exploit: ' + exploit['DESCRIPTION'] + ' | Ratio:' + str(ratio)) 23 | matched_items.append(exploit) 24 | if 'hardware' in types: 25 | for key,value in sysinfo.items(): 26 | if key in ['os_name','cpu_name','gpu','bios_name','bios_manufacturer']: 27 | ratio = fuzz.token_set_ratio(str(value).lower(),exploit['DESCRIPTION'].lower()) 28 | if ratio>=75 and exploit not in matched_items: 29 | print('Your System: ' + str(value) + ' | Exploit: ' + exploit['DESCRIPTION'] + ' | Ratio:' + str(ratio)) 30 | matched_items.append(exploit) 31 | print('Comparing exploits and system info done!') 32 | print(str(len(matched_items)) + ' matched item(s) found!') 33 | return matched_items 34 | 35 | # ------------------------------------------------------------------------------------------------------------ 36 | def send_mail(server,sender_email,subject,receiver_email,content): 37 | message = MIMEMultipart("alternative") 38 | message["Subject"] = subject 39 | message["From"] = sender_email 40 | message["To"] = receiver_email 41 | 42 | # Create the plain-text and HTML version of your message 43 | html_data = '' 44 | for item in content: 45 | more_info = '' 46 | full_title = '' 53 | html_data += full_title 54 | 55 | html = ''' 56 | 57 | 58 | 59 |

new exploits of 0day.today

60 | {0} 61 | 62 | '''.format(html_data) 63 | 64 | # Turn these into plain/html MIMEText objects 65 | # part1 = MIMEText(text, "plain") 66 | content = MIMEText(html, "html") 67 | 68 | # Add HTML/plain-text parts to MIMEMultipart message 69 | # The email client will try to render the last part first 70 | message.attach(content) 71 | 72 | # Create secure connection with server and send email 73 | try: 74 | server.sendmail(sender_email, receiver_email, message.as_string()) 75 | return True 76 | except Exception: 77 | print("Can't send mail!") 78 | return False 79 | # ------------------------------------------------------------------------------------------------------------ 80 | def send_exploits_to_emails(exploits,emails,DB_NAME): 81 | print('Checking the emails to be sent started...') 82 | db = DB() 83 | conn = db.create_connection(DB_NAME) 84 | email2exploits = dict() 85 | links2info = dict() 86 | for email in emails: 87 | exploits_of_email = [] 88 | for exploit in exploits: 89 | if not db.link_was_sent_to_email(conn,exploit['Link'],email): 90 | exploits_of_email.append(exploit['Link']) 91 | links2info[exploit['Link']] = None 92 | if len(exploits_of_email)>0: 93 | email2exploits[email] = exploits_of_email 94 | 95 | emails_count = len(email2exploits.keys()) 96 | print('{0} email(s) must be sent!'.format(emails_count)) 97 | 98 | if emails_count !=0: 99 | scraper = Scraper() 100 | print('Scraping exploits information strated!please wait...') 101 | i=1 102 | for link in links2info.keys(): 103 | print(str(i) + '/' + str(len(links2info.keys()))) 104 | link_info = scraper.get_exploit_info(link) 105 | if link_info != {}: 106 | links2info[link] = link_info 107 | else: 108 | links2info.pop(link,None) 109 | i = i+1 110 | print('Scraping exploits information done!') 111 | try: 112 | print('Sending emails started!please wait...') 113 | context = ssl.create_default_context() 114 | with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server: 115 | server.login(Email,Password) 116 | for email,links in email2exploits.items(): 117 | if send_mail(server,Email,'New exploits of 0day.today',email,[value for key,value in links2info.items() if key in links]): 118 | emails_to_db = [[link,email,time.strftime('%d-%m-%Y')] for link in links] 119 | db.insert_emails(conn,emails_to_db) 120 | print('Sending emails done!') 121 | except Exception: 122 | print("Can't login to mail server!! Please check your mail server authentication policy!") -------------------------------------------------------------------------------- /Systeminfo.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import re 3 | import errno, os, winreg 4 | 5 | class SystemInfo: 6 | def __init__(self): 7 | self.host_name = self.get_host_name() 8 | self.os_name = self.get_os_name() 9 | self.os_architecture = self.get_os_architecture() 10 | self.os_version = self.get_os_version() 11 | self.cpu_name = self.get_cpu_name() 12 | self.cpu_cores = self.get_cpu_cores() 13 | self.gpu = self.get_gpu() 14 | self.bios_name = self.get_bios_name() 15 | self.bios_version = self.get_bios_version() 16 | self.bios_manufacturer = self.get_bios_manufacturer() 17 | self.softwares = list() 18 | 19 | 20 | def get_system_softwares(self): 21 | """ 22 | description: 23 | ------------ 24 | return system all installed programs, apps or packages 25 | by search in registry key 26 | 27 | args: 28 | ------------ 29 | 30 | return: 31 | ------------ 32 | :list like [[software1_name,version],[software2_name,version],...] or None if error occured 33 | 34 | """ 35 | try: 36 | proc_arch = os.environ['PROCESSOR_ARCHITECTURE'].lower() 37 | except: 38 | pass 39 | try: 40 | proc_arch64 = os.environ['PROCESSOR_ARCHITEW6432'].lower() 41 | except: 42 | pass 43 | if proc_arch == 'x86' and not proc_arch64: 44 | arch_keys = {0} 45 | elif proc_arch == 'x86' or proc_arch == 'amd64': 46 | arch_keys = {winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY} 47 | else: 48 | raise Exception("Unhandled arch: %s" % proc_arch) 49 | for arch_key in arch_keys: 50 | key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", 0, winreg.KEY_READ | arch_key) 51 | for i in range(0, winreg.QueryInfoKey(key)[0]): 52 | skey_name = winreg.EnumKey(key, i) 53 | skey = winreg.OpenKey(key, skey_name) 54 | software_name = None 55 | software_version = None 56 | try: 57 | software_name = winreg.QueryValueEx(skey, 'DisplayName')[0] 58 | except OSError as e: 59 | if e.errno == errno.ENOENT: 60 | pass 61 | try: 62 | software_version = winreg.QueryValueEx(skey, 'DisplayVersion')[0] 63 | except OSError as e: 64 | if e.errno == errno.ENOENT: 65 | pass 66 | finally: 67 | skey.Close() 68 | if software_name is not None: 69 | self.softwares.append([software_name,software_version]) 70 | 71 | return self.softwares 72 | 73 | def get_host_name(self): 74 | """ 75 | description: 76 | ------------ 77 | get system host name 78 | 79 | args: 80 | ------------ 81 | 82 | return: 83 | ------------ 84 | system host name 85 | 86 | """ 87 | process = subprocess.Popen(["wmic", "computersystem", "get", "name"], stdout=subprocess.PIPE) 88 | stdout, err = process.communicate() 89 | self.host_name = str(stdout).split('\\r\\r\\n')[1].strip() 90 | return self.host_name 91 | 92 | def get_os_name(self): 93 | """ 94 | description: 95 | ------------ 96 | get system os name 97 | 98 | args: 99 | ------------ 100 | 101 | return: 102 | ------------ 103 | system os name 104 | 105 | """ 106 | process = subprocess.Popen(["wmic", "os", "get", "name"], stdout=subprocess.PIPE) 107 | stdout, err = process.communicate() 108 | self.os_name = str(stdout).split('\\r\\r\\n')[1].strip().split('|')[0] 109 | return self.os_name 110 | 111 | def get_os_version(self): 112 | """ 113 | description: 114 | ------------ 115 | get system os version 116 | 117 | args: 118 | ------------ 119 | 120 | return: 121 | ------------ 122 | system os version 123 | 124 | """ 125 | process = subprocess.Popen(["wmic", "os", "get", "version"], stdout=subprocess.PIPE) 126 | stdout, err = process.communicate() 127 | self.os_version = str(stdout).split('\\r\\r\\n')[1].strip() 128 | return self.os_version 129 | 130 | 131 | def get_os_architecture(self): 132 | """ 133 | description: 134 | ------------ 135 | get system os architecture 136 | 137 | args: 138 | ------------ 139 | 140 | return: 141 | ------------ 142 | system os architecture 143 | 144 | """ 145 | process = subprocess.Popen(["wmic", "os", "get", "OSArchitecture"], stdout=subprocess.PIPE) 146 | stdout, err = process.communicate() 147 | self.os_architecture = str(stdout).split('\\r\\r\\n')[1].strip() 148 | return self.os_architecture 149 | 150 | def get_cpu_name(self): 151 | """ 152 | description: 153 | ------------ 154 | get system cpu name 155 | 156 | args: 157 | ------------ 158 | 159 | return: 160 | ------------ 161 | system cpu name 162 | 163 | """ 164 | process = subprocess.Popen(["wmic", "cpu", "get", "name"], stdout=subprocess.PIPE) 165 | stdout, err = process.communicate() 166 | self.cpu_name = str(stdout).split('\\r\\r\\n')[1].strip() 167 | return self.cpu_name 168 | 169 | def get_gpu(self): 170 | """ 171 | description: 172 | ------------ 173 | get system number of cpu cores 174 | 175 | args: 176 | ------------ 177 | 178 | return: 179 | ------------ 180 | system number of cpu cores 181 | 182 | """ 183 | process = subprocess.Popen(["wmic", "cpu", "get", "NumberOfCores"], stdout=subprocess.PIPE) 184 | stdout, err = process.communicate() 185 | self.cpu_cores = str(stdout).split('\\r\\r\\n')[1].strip() 186 | return self.cpu_cores 187 | 188 | def get_cpu_cores(self): 189 | """ 190 | description: 191 | ------------ 192 | get system number of cpu cores 193 | 194 | args: 195 | ------------ 196 | 197 | return: 198 | ------------ 199 | system number of cpu cores 200 | 201 | """ 202 | process = subprocess.Popen(["wmic", "cpu", "get", "NumberOfCores"], stdout=subprocess.PIPE) 203 | stdout, err = process.communicate() 204 | self.cpu_cores = str(stdout).split('\\r\\r\\n')[1].strip() 205 | return self.cpu_cores 206 | 207 | def get_gpu(self): 208 | """ 209 | description: 210 | ------------ 211 | get system gpu informations 212 | 213 | args: 214 | ------------ 215 | 216 | return: 217 | ------------ 218 | system gpu informations 219 | 220 | """ 221 | process = subprocess.Popen(["wmic" ,"path" ,"win32_VideoController", "get" ,"name"], stdout=subprocess.PIPE) 222 | stdout, err = process.communicate() 223 | self.gpu = [item for item in re.sub(' +','',str(stdout)).split('\\r\\r\\n')[1:] if len(item)>2] 224 | return self.gpu 225 | 226 | def get_bios_name(self): 227 | """ 228 | description: 229 | ------------ 230 | get system bios name 231 | 232 | args: 233 | ------------ 234 | 235 | return: 236 | ------------ 237 | system bios name 238 | 239 | """ 240 | process = subprocess.Popen(["wmic" ,"bios" ,"get", "name"], stdout=subprocess.PIPE) 241 | stdout, err = process.communicate() 242 | self.bios_name = str(stdout).split('\\r\\r\\n')[1].strip() 243 | return self.bios_name 244 | 245 | def get_bios_version(self): 246 | """ 247 | description: 248 | ------------ 249 | get system bios version 250 | 251 | args: 252 | ------------ 253 | 254 | return: 255 | ------------ 256 | system bios version 257 | 258 | """ 259 | process = subprocess.Popen(["wmic" ,"bios" ,"get", "version"], stdout=subprocess.PIPE) 260 | stdout, err = process.communicate() 261 | self.bios_version = str(stdout).split('\\r\\r\\n')[1].strip() 262 | return self.bios_name 263 | 264 | 265 | def get_bios_manufacturer(self): 266 | """ 267 | description: 268 | ------------ 269 | get system bios manufacturer 270 | 271 | args: 272 | ------------ 273 | 274 | return: 275 | ------------ 276 | system bios manufacturer 277 | 278 | """ 279 | process = subprocess.Popen(["wmic" ,"bios" ,"get", "Manufacturer"], stdout=subprocess.PIPE) 280 | stdout, err = process.communicate() 281 | self.bios_manufacturer = str(stdout).split('\\r\\r\\n')[1].strip() 282 | return self.bios_manufacturer -------------------------------------------------------------------------------- /DBInterface.py: -------------------------------------------------------------------------------- 1 | from sqlite3 import Error 2 | import sqlite3 3 | 4 | class DB: 5 | def __init__(self): 6 | pass 7 | 8 | def create_connection(self,db_file): 9 | """ 10 | description: 11 | ------------ 12 | create a database connection to the SQLite database 13 | specified by the db_file 14 | 15 | args: 16 | ------------ 17 | :param db_file: database file 18 | 19 | return: 20 | ------------ 21 | :return: Connection object or None 22 | """ 23 | try: 24 | conn = sqlite3.connect(db_file,check_same_thread=False) 25 | return conn 26 | except Error as e: 27 | print(e) 28 | 29 | return None 30 | # --------------------------------------------------------------------------------------------- 31 | def create_table(self,conn,create_table_sql): 32 | """ 33 | description: 34 | ------------ 35 | create a table from the create_table_sql statement 36 | 37 | args: 38 | ------------ 39 | :param conn: Connection object 40 | :param create_table_sql: a CREATE TABLE statement 41 | 42 | return: 43 | ------------ 44 | """ 45 | 46 | try: 47 | c = conn.cursor() 48 | c.execute(create_table_sql) 49 | except Error as e: 50 | print(e) 51 | 52 | # --------------------------------------------------------------------------------------------- 53 | def create_tables(self,conn,dbname): 54 | """ 55 | description: 56 | ------------ 57 | create a tables in database 58 | 59 | args: 60 | ------------ 61 | 62 | :param conn: Connection object 63 | :param dbname: a database name 64 | return: 65 | ------------ 66 | """ 67 | sql_create_systems_table = """CREATE TABLE IF NOT EXISTS Systems ( 68 | id INTEGER PRIMARY KEY, 69 | host_name TEXT NOT NULL, 70 | os_name TEXT, 71 | os_architecture TEXT, 72 | os_version TEXT, 73 | cpu_name TEXT, 74 | cpu_cores TEXT, 75 | gpu TEXT, 76 | bios_name TEXT, 77 | bios_version TEXT, 78 | bios_manufacturer TEXT 79 | ); 80 | """ 81 | sql_create_softwares_table = """ CREATE TABLE IF NOT EXISTS Softwares ( 82 | id INTEGER PRIMARY KEY, 83 | system_id INTEGER, 84 | name TEXT NOT NULL, 85 | version TEXT, 86 | FOREIGN KEY (system_id) REFERENCES Systems (id) 87 | ); """ 88 | sql_create_emails_table = """ CREATE TABLE IF NOT EXISTS Emails ( 89 | id INTEGER PRIMARY KEY, 90 | link TEXT NOT NULL, 91 | receiver_email TEXT NOT NULL, 92 | date TEXT NOT NULL 93 | ); """ 94 | if conn is not None: 95 | # create systems table 96 | self.create_table(conn,sql_create_systems_table) 97 | # create softwares table 98 | self.create_table(conn,sql_create_softwares_table) 99 | # create emails table 100 | self.create_table(conn,sql_create_emails_table) 101 | print('OK. tables created successfully\n'+'-'*50) 102 | else: 103 | print('Error! cannot create the database connection.\n'+'-'*50) 104 | # --------------------------------------------------------------------------------------------- 105 | def query_execution(self,conn,sql): 106 | """ 107 | description: 108 | ------------ 109 | execute sql query on input db connection 110 | 111 | args: 112 | ------------ 113 | :param conn: current connection to database 114 | :param sql: input sql query 115 | 116 | return: 117 | ------------ 118 | :return ID: inserted ID 119 | """ 120 | curser = conn.cursor() 121 | curser.execute(sql) 122 | rows = curser.fetchall() 123 | conn.commit() 124 | 125 | return rows 126 | # --------------------------------------------------------------------------------------------- 127 | 128 | def insert_softwares(self,conn,softwares): 129 | """ 130 | description: 131 | ------------ 132 | insert new software information 133 | 134 | args: 135 | ------------ 136 | :param conn: current connection to database 137 | :param softwares : list like [[system_id,software1_name,version],[system_id,software2_name,version],...] 138 | 139 | return: 140 | ------------ 141 | :return ID : inserted ID 142 | """ 143 | try: 144 | curser = conn.cursor() 145 | curser.execute('''DELETE FROM Softwares WHERE system_id=?''',(str(softwares[0][2]))) 146 | curser.executemany('''INSERT INTO Softwares(name,version,system_id) VALUES(?,?,?)''',softwares) 147 | conn.commit() 148 | return curser.lastrowid 149 | except Exception: 150 | print('Error in inserting data') 151 | # --------------------------------------------------------------------------------------------- 152 | def select_softwares_name(self,conn): 153 | """ 154 | description: 155 | ------------ 156 | select softwares name 157 | 158 | args: 159 | ------------ 160 | :param conn: current connection to database 161 | 162 | return: 163 | ------------ 164 | :return row : fotwares name 165 | """ 166 | curser = conn.cursor() 167 | curser.execute("SELECT name FROM softwares") 168 | rows = curser.fetchall() 169 | return rows 170 | # ------------------------------------------------------------------------------------------------ 171 | def insert_system_info(self,conn,host_name,os_name,os_architecture,os_version,cpu_name,cpu_cores,gpu,bios_name,bios_version,bios_manufacturer): 172 | """ 173 | description: 174 | ------------ 175 | insert system information into database 176 | 177 | args: 178 | ------------ 179 | :param host_name : system name 180 | :param os_name : system os name 181 | :param os_architecture : system os architecture 182 | :param os_version : system os version 183 | :param cpu_name : system cpu name 184 | :param cpu_cores : system cpu cores 185 | :param gpu : system gpu name 186 | :param bios_name : system bios name 187 | :param bios_version : system bios version 188 | :param bios_manufacturer : system bios manufacturer 189 | 190 | return: 191 | ------------ 192 | :return ID : inserted ID 193 | """ 194 | try: 195 | curser = conn.cursor() 196 | curser.execute('''SELECT DISTINCT id FROM Systems WHERE host_name = ?''',(host_name,)) 197 | rows = curser.fetchall() 198 | if(len(rows)==0): 199 | curser.execute('''INSERT INTO Systems(host_name,os_name,os_architecture,os_version,cpu_name,cpu_cores,gpu,bios_name,bios_version,bios_manufacturer) VALUES(?,?,?,?,?,?,?,?,?,?)''', 200 | (host_name,os_name,os_architecture,os_version,cpu_name,cpu_cores,gpu,bios_name,bios_version,bios_manufacturer)) 201 | conn.commit() 202 | return curser.lastrowid 203 | else: 204 | return rows[0][0] 205 | except Exception: 206 | print('Error in inserting data') 207 | return None 208 | # ------------------------------------------------------------------------------------------------ 209 | def insert_emails(self,conn,emails): 210 | """ 211 | description: 212 | ------------ 213 | insert new email 214 | 215 | args: 216 | ------------ 217 | :param conn: current connection to database 218 | :param emails : list like [[exploit1_link,receiver_email,date],[exploit2_link,receiver_email,date],...] 219 | 220 | return: 221 | ------------ 222 | :return ID : inserted ID 223 | """ 224 | try: 225 | curser = conn.cursor() 226 | curser.executemany('''INSERT INTO Emails(link,receiver_email,date) VALUES(?,?,?)''',emails) 227 | conn.commit() 228 | return curser.lastrowid 229 | except Exception: 230 | print('Error in inserting data') 231 | # --------------------------------------------------------------------------------------------- 232 | def link_was_sent_to_email(self,conn,link,receiver_email): 233 | """ 234 | description: 235 | ------------ 236 | return True if the given link was sent to the given email else return False 237 | 238 | args: 239 | ------------ 240 | :param conn: current connection to database 241 | 242 | return: 243 | ------------ 244 | :return True or False : 245 | """ 246 | try: 247 | curser = conn.cursor() 248 | curser.execute('''SELECT id FROM Emails WHERE link = ? and receiver_email = ?''',(link,receiver_email)) 249 | rows = curser.fetchall() 250 | if len(rows)>0: 251 | return True 252 | else: 253 | return False 254 | except Exception: 255 | print('Error in selecting rows') 256 | return False 257 | # --------------------------------------------------------------------------------------------- 258 | --------------------------------------------------------------------------------