├── arethesebad.py └── readme.md /arethesebad.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | import json 5 | import urllib 6 | import urllib2 7 | import hashlib 8 | import argparse 9 | 10 | VIRUSTOTAL_FILE_URL = 'https://www.virustotal.com/vtapi/v2/file/report' 11 | API_KEY = '' 12 | 13 | TPL_SECTION = "[*] ({0}):" 14 | TPL_MATCH = "\t\_ Results: {0}/{1} {2}\n\t SHA256: {3}\n\t Scan Date: {4}" 15 | TPL_SIGNATURES = "\t Signatures:\n\t\t{0}" 16 | 17 | def color(text, color_code): 18 | if sys.platform == "win32" and os.getenv("TERM") != "xterm": 19 | return text 20 | 21 | return '\x1b[%dm%s\x1b[0m' % (color_code, text) 22 | 23 | def red(text): 24 | return color(text, 31) 25 | 26 | def blink(text): 27 | return color(text, 05) 28 | 29 | def Green(text): 30 | return color(text, 32) 31 | 32 | def yellow(text): 33 | return color(text, 34) 34 | 35 | class Hash(object): 36 | def __init__(self, path): 37 | self.path = path 38 | self.md5 = '' 39 | self.sha256 = '' 40 | 41 | def get_chunks(self): 42 | fd = open(self.path, 'rb') 43 | while True: 44 | chunk = fd.read(16 * 1024) 45 | if not chunk: 46 | break 47 | 48 | yield chunk 49 | fd.close() 50 | 51 | def calculate(self): 52 | md5 = hashlib.md5() 53 | sha256 = hashlib.sha256() 54 | 55 | for chunk in self.get_chunks(): 56 | md5.update(chunk) 57 | sha256.update(chunk) 58 | 59 | self.md5 = md5.hexdigest() 60 | self.sha256 = sha256.hexdigest() 61 | 62 | class Scanner(object): 63 | def __init__(self, key, path): 64 | self.key = key 65 | self.path = path 66 | self.list = [] 67 | 68 | def populate(self): 69 | paths = [] 70 | 71 | if os.path.isfile(self.path): 72 | paths.append(self.path) 73 | else: 74 | for root, folders, files in os.walk(self.path): 75 | for file_name in files: 76 | # Skip hidden files, might need an option for this. 77 | if file_name.startswith('.'): 78 | continue 79 | 80 | file_path = os.path.join(root, file_name) 81 | if os.path.exists(file_path): 82 | paths.append(file_path) 83 | 84 | for path in paths: 85 | hashes = Hash(path) 86 | hashes.calculate() 87 | 88 | self.list.append({ 89 | 'path' : path, 90 | 'md5' : hashes.md5, 91 | 'sha256' : hashes.sha256 92 | }) 93 | 94 | def scan(self): 95 | hashes = [] 96 | for entry in self.list: 97 | if entry['sha256'] not in hashes: 98 | hashes.append(entry['sha256']) 99 | 100 | data = urllib.urlencode({ 101 | 'resource' : ','.join(hashes), 102 | 'apikey' : self.key 103 | }) 104 | 105 | try: 106 | request = urllib2.Request(VIRUSTOTAL_FILE_URL, data) 107 | response = urllib2.urlopen(request) 108 | report = json.loads(response.read()) 109 | except Exception as e: 110 | print(red("[!] ERROR: Cannot obtain results from VirusTotal: {0}\n".format(e))) 111 | return 112 | 113 | results = [] 114 | CHECK = 0 115 | VIRUS = 0 116 | CLEAN = 0 117 | 118 | if type(report) is dict: 119 | results.append(report) 120 | elif type(report) is list: 121 | results = report 122 | 123 | for entry in results: 124 | 125 | sha256 = entry['resource'] 126 | 127 | entry_paths = [] 128 | for item in self.list: 129 | if item['sha256'] == sha256: 130 | if item['path'] not in entry_paths: 131 | entry_paths.append(item['path']) 132 | 133 | print(TPL_SECTION.format('\n '.join(entry_paths))), 134 | 135 | if entry['response_code'] == 0: 136 | CHECK = CHECK + 1 137 | print(yellow('< VirusTotal Hasnt Seen This File! Manually Verify!')) 138 | 139 | elif entry['positives'] < 1: 140 | CLEAN = CLEAN + 1 141 | continue 142 | 143 | elif entry['positives'] > 0: 144 | VIRUS = VIRUS +1 145 | print (red(blink('< This is a virus!!!!!!'))) 146 | 147 | 148 | # PRINT STATS 149 | print ('\n') 150 | print ('Scanned %0.f files with virustotal.com:') % (CLEAN+CHECK+VIRUS) 151 | print (Green('%0.f files are virus free.')) % CLEAN 152 | print (yellow('%0.f files need to be manually verified.')) % CHECK 153 | print (red('%0.f files are infected.')) % VIRUS 154 | 155 | def run(self): 156 | if not self.key: 157 | print(red("[!] ERROR: You didn't specify a valid VirusTotal API key.\n")) 158 | return 159 | 160 | if not os.path.exists(self.path): 161 | print(red("[!] ERROR: The target path {0} does not exist.\n".format(self.path))) 162 | return 163 | 164 | self.populate() 165 | self.scan() 166 | 167 | if __name__ == '__main__': 168 | parser = argparse.ArgumentParser() 169 | parser.add_argument('path', type=str, help='Path to the file or folder to lookup on VirusTotal') 170 | parser.add_argument('--key', type=str, action='store', default=API_KEY, help='VirusTotal API key') 171 | 172 | try: 173 | args = parser.parse_args() 174 | except IOError as e: 175 | parser.error(e) 176 | sys.exit() 177 | 178 | scan = Scanner(args.key, args.path) 179 | scan.run() -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ### Are These Bad? 2 | 3 | Are These Bad? is a python script that will automatically lookup all files contained in a directory on virustotal.com. I wrote this to quickly check portable media on my rasbperry pi for known viruses. 4 | 5 | 6 | # Usage 7 | 8 | python arethesebad.py ../Directory/To/Scan 9 | 10 | python arethesebad.py /media/usb/ 11 | 12 | 13 | # Notes 14 | You will need an API Key from Virustotal.com for this script to work: 15 | https://www.virustotal.com/en/documentation/public-api/ 16 | 17 | For ease of use past key into API_KEY ='' on Line11. 18 | 19 | 20 | #Important Notice 21 | *I dont know what I am doing. This will likely break your system.* 22 | 23 | --------------------------------------------------------------------------------