[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] [torbrowser/master 1/4] Example code for submitting samples to VirusTotal
Author: Steven Murdoch <Steven.Murdoch@xxxxxxxxxxxx>
Date: Sun, 24 Oct 2010 22:12:06 +0100
Subject: Example code for submitting samples to VirusTotal
Commit: fc7b945481fb20f8e78ea9a4a9eed4a651aace82
Written by Bryce Boe
Downloaded from http://www.bryceboe.com/2010/09/01/submitting-binaries-to-virustotal/
---
build-scripts/virus-scan.py | 93 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 93 insertions(+), 0 deletions(-)
create mode 100644 build-scripts/virus-scan.py
diff --git a/build-scripts/virus-scan.py b/build-scripts/virus-scan.py
new file mode 100644
index 0000000..3b14fcb
--- /dev/null
+++ b/build-scripts/virus-scan.py
@@ -0,0 +1,93 @@
+import hashlib, httplib, mimetypes, os, pprint, simplejson, sys, urlparse
+
+DEFAULT_TYPE = 'application/octet-stream'
+
+REPORT_URL = 'https://www.virustotal.com/api/get_file_report.json'
+SCAN_URL = 'https://www.virustotal.com/api/scan_file.json'
+
+API_KEY = 'YOUR KEY HERE'
+
+# The following function is modified from the snippet at:
+# http://code.activestate.com/recipes/146306/
+def encode_multipart_formdata(fields, files=()):
+ """
+ fields is a dictionary of name to value 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.items():
+ L.append('--' + BOUNDARY)
+ L.append('Content-Disposition: form-data; name="%s"' % key)
+ L.append('')
+ L.append(value)
+ for (key, filename, value) in files:
+ L.append('--' + BOUNDARY)
+ L.append('Content-Disposition: form-data; name="%s"; filename="%s"' %
+ (key, filename))
+ content_type = mimetypes.guess_type(filename)[0] or DEFAULT_TYPE
+ L.append('Content-Type: %s' % content_type)
+ L.append('')
+ L.append(value)
+ L.append('--' + BOUNDARY + '--')
+ L.append('')
+ body = CRLF.join(L)
+ content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
+ return content_type, body
+
+def post_multipart(url, fields, files=()):
+ """
+ url is the full to send the post request to.
+ fields is a dictionary of name to value for regular form fields.
+ files is a sequence of (name, filename, value) elements for data to be
+ uploaded as files.
+ Return body of http response.
+ """
+ content_type, data = encode_multipart_formdata(fields, files)
+ url_parts = urlparse.urlparse(url)
+ if url_parts.scheme == 'http':
+ h = httplib.HTTPConnection(url_parts.netloc)
+ elif url_parts.scheme == 'https':
+ h = httplib.HTTPSConnection(url_parts.netloc)
+ else:
+ raise Exception('Unsupported URL scheme')
+ path = urlparse.urlunparse(('', '') + url_parts[2:])
+ h.request('POST', path, data, {'content-type':content_type})
+ return h.getresponse().read()
+
+def scan_file(filename):
+ files = [('file', filename, open(filename, 'rb').read())]
+ json = post_multipart(SCAN_URL, {'key':API_KEY}, files)
+ return simplejson.loads(json)
+
+def get_report(filename):
+ md5sum = hashlib.md5(open(filename, 'rb').read()).hexdigest()
+ json = post_multipart(REPORT_URL, {'resource':md5sum, 'key':API_KEY})
+ data = simplejson.loads(json)
+ if data['result'] != 1:
+ print 'Result not found, submitting file.'
+ data = scan_file(filename)
+ if data['result'] == 1:
+ print 'Submit successful.'
+ print 'Please wait a few minutes and try again to receive report.'
+ else:
+ print 'Submit failed.'
+ pprint.pprint(data)
+ else:
+ pprint.pprint(data['report'])
+
+
+if __name__ == '__main__':
+ if len(sys.argv) != 2:
+ print 'Usage: %s filename' % sys.argv[0]
+ sys.exit(1)
+
+ filename = sys.argv[1]
+ if not os.path.isfile(filename):
+ print '%s is not a valid file' % filename
+ sys.exit(1)
+
+ get_report(filename)
--
1.7.1