Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 219 lines (192 sloc) 7.43 KB
#!/usr/bin/env python
from optparse import OptionParser
import hashlib, os, urllib, urllib2, json, httplib, mimetypes, time, magic
import peinfos, yaraScan
from datetime import date
from cymru.mhr.dns import DNSClient as mhr
# {{{ (r1)
def post_multipart(host, selector, fields, files):
Post fields and files to an http host as multipart/form-data.
fields is a sequence of (name, value) elements for regular form fields.
files is a sequence of (name, filename, value) elements for data to be uploaded as files
Return the server's response page.
content_type, body = encode_multipart_formdata(fields, files)
h = httplib.HTTP(host)
h.putrequest('POST', selector)
h.putheader('content-type', content_type)
h.putheader('content-length', str(len(body)))
errcode, errmsg, headers = h.getreply()
def encode_multipart_formdata(fields, files):
fields is a sequence of (name, value) elements for regular form fields.
files is a sequence of (name, filename, value) elements for data to be uploaded as files
Return (content_type, body) ready for httplib.HTTP instance
BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
CRLF = '\r\n'
L = []
for (key, value) in fields:
L.append('--' + BOUNDARY)
L.append('Content-Disposition: form-data; name="%s"' % key)
for (key, filename, value) in files:
L.append('--' + BOUNDARY)
L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
L.append('Content-Type: %s' % get_content_type(filename))
L.append('--' + BOUNDARY + '--')
body = CRLF.join(L)
content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
return content_type, body
def get_content_type(filename):
return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
# end of }}}
def calculateHash(file_path):
"""docstring for calculateHash"""
if os.path.isfile(file_path):
file_content = open(file_path, 'rb')
return hashlib.sha256(
def teamCymruCheck(file_path):
"""docstring for teamCymruCheck"""
client = mhr()
h = hashlib.sha1(file(file_path, 'r').read()).hexdigest()
return client.lookup(h)
class VirusTotalUploader:
def __init__(self, path, recursive, yes, days):
"""docstring for __init__"""
self.apikey = ''
self.url_report = ''
self.url_scan = ''
self.av_list = ['Avast', 'ClamAV', 'F-Secure', 'Kaspersky', 'Microsoft']
self.path = path
if os.path.isdir(path):
self.recursive = recursive
self.recursive = False
self.yes = yes
self.days = days
self.curr_timestamp = time.time()
def check_report(self, file_path):
"""Check if a report for a binary exists on VirusTotal"""
#if os.path.isfile(file_path):
print "Check report on VT for file : %s" % file_path
file_hash = calculateHash(file_path)
print "Sha256 : %s" % file_hash
# Prepare HTTP request
parameters = {'resource' : file_hash,
'apikey' : self.apikey}
data = urllib.urlencode(parameters)
req = urllib2.Request(self.url_report, data)
# Send request
response = urllib2.urlopen(req)
json_res = json.loads(
# Show results
#print 'RESPONSE CODE', json_res['response_code']
if json_res['response_code'] == 1:
print "File type : %s" % (magic.from_file(file_path)) #Can fail with some version of magic module
print """
Scan date %s
Detection rate : %d/%d
Report URL : %s
""" % (json_res['scan_date'], json_res['positives'], json_res['total'], json_res['permalink'])
print " AV result summary :"
for av in self.av_list:
print " %s : %s" % (av, json_res['scans'][av]['result'])
except KeyError, e:
print " %s : No results" % (av)
# TeamCymru infos : Detection rate / timestamp
cymru = teamCymruCheck(file_path)
if cymru.ts is not None:
print """
TeamCymru :
Detection rate : %s%%
Date : %s
""" % (cymru.detection, date.fromtimestamp(long(cymru.ts)).strftime('%d/%m/%Y'))
yara = yaraScan.YaraScan(file_path)
#PE infos
pe = peinfos.PeInfos(file_path)
print '-'*80, '\n'*5
print ' |-> ', json_res['verbose_msg']
return json_res['response_code']
# print "/!\\ %s is not a file or doesn't exist !" % file_path
def scan_binary(self, file_path):
"""Scan a binary on VirusTotal"""
print "Scanning file %s" % file_path
parameters = [('apikey', self.apikey)]
file_content = open(file_path, 'rb').read()
file_to_upload = [("file", os.path.basename(file_path), file_content)]
json_res = json.loads(post_multipart('', self.url_scan, parameters, file_to_upload))
#print repr(json_data)
if json_res['response_code'] != 1:
print ' |-> ', json_res['verbose_msg']
print ' |-> Upload OK'
print ' |-> Permalink : %s' % json_res['permalink']
return json_res['response_code']
def blah(self, file_path):
"""docstring for blah"""
if self.days != 0:
file_timestamp = os.path.getmtime(file_path)
if ((self.curr_timestamp - file_timestamp) <= (3600*24*self.days)):
# check file if it has less than X days
check_file = True
# file too old, don't check
check_file = False
# don't look file's date, and check file
check_file = True
if check_file:
do_scan = self.yes
if (self.check_report(file_path) == 0):
if not self.yes:
res = None
while res not in ['y', 'Y', 'n', 'N', '']:
res = raw_input("Do you want to upload file %s to VirusTotal ? [y/n] " % file_path)
if res.lower() == 'y':
do_scan = True
if do_scan:
def execute(self):
"""docstring for execute"""
if os.path.isfile(self.path):
elif os.path.isdir(self.path):
for root, dirs, files in os.walk(self.path):
for f in files:
self.blah(os.path.join(root, f))
if not self.recursive:
if __name__ == "__main__":
usage = "usage: %prog [options] [file|directory]"
parser = OptionParser(usage=usage)
parser.add_option('-r', '--recursive', dest='recursive', action='store_true', default=False, help='Check and/or Upload binairies in all sub-directories')
parser.add_option('-y', '--yes', dest='yes', action='store_true', default=False, help='Upload all binairies to VirusTotal whithout ask to user')
parser.add_option('-d', '--days', dest='days', type='int', default=0, help='Check file if it is younger than X days')
(option, args) = parser.parse_args()
if len(args) == 0:
vt = VirusTotalUploader(args[0], option.recursive, option.yes, option.days)