Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Clark committed Jul 1, 2015
0 parents commit 98835f5
Show file tree
Hide file tree
Showing 3 changed files with 354 additions and 0 deletions.
131 changes: 131 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
## Information
This is a simple tool to utilize the basic functionality of the Private API From Virus Total, with this tool you can eaisly scan a hash or file (script will automatically hash the file and submit the HASH to VT not the file). You can download malware based on hash, download pcaps, write the full VT Json report to file, and force a rescan of a previously uploaded file with new AV definitions. Advanced queries and bulk downloads can be accomplished via VT Provided Scripts available on the Intelligence portal. (or a bash loop if you want to bulk DL with this)

NOTE: You need your own premium VT API to use this tool. API Key Goes on Line 13!

NOTE2: If you have a free VT Public API (you do) then you can use VTlite.py with limited functionality (Check Hash/Path/Rescan/DownloadJson/VerboseDetections) four checks per minute are allowed.

## Authors & Licence
Original Script Author: Adam Meyers

Rewritten & Modified: Chris Clark

License: Do whatever you want with it :)

## Example
<pre>
Usage is as follows with an example of a basic search + hitting all of
the switches below:

usage: vt.py [-h] [-s] [-v] [-j] [-d] [-p] [-r] HashorPath

Search and Download from VirusTotal

positional arguments:
HashorPath Enter the MD5 Hash or Path to File

optional arguments:
-h, --help show this help message and exit
-s, --search Search VirusTotal
-v, --verbose Turn on verbosity of VT reports
-j, --jsondump Dumps the full VT report to file (VTDLXXX.json)
-d, --download Download File from Virustotal (VTDLXXX.danger)
-p, --pcap Download Network Traffic (VTDLXXX.pcap)
-r, --rescan Force Rescan with Current A/V Definitions

Example Basic Scan:

xen0ph0n@pir8ship:~/tools$ python vt.py ../../VirtualBox_Share/wsusservice.dll -s

Results for MD5: 92d37a92138659fa75f45ccb87242910

Detected by: 30 / 43
Sophos Detection: Troj/Briba-A
Kaspersky Detection: Backdoor.Win32.Agent.clfe
TrendMicro Detection: BKDR_BRIBA.A
Scanned on: 2012-09-28 02:44:37
First Seen: 2012-08-15 12:36:02
Last Seen: 2012-09-28 02:44:37
Unique Sources 3
Submission Names:
92d37a92138659fa75f45ccb87242910
wsusservice.dll_
wsusservice2.dll_
file-4567337_



Example Verbose Scan + Download + Pcap + Json Save + Force Rescan:

xen0ph0n@pir8ship:~/tools$ python vt.py 287f3dda64b830a5ac5a6df3266f7d08 -pdvjr

Results for MD5: 287f3dda64b830a5ac5a6df3266f7d08

Detected by: 38 / 46
Sophos Detection: Troj/Hurgyu-A
Kaspersky Detection: Trojan-Dropper.Win32.Dapato.bnnu
TrendMicro Detection: TROJ_GEN.RCBC8HQ
Scanned on: 2013-03-25 21:38:35
First Seen: 2012-09-25 09:14:13
Last Seen: 2012-09-25 09:14:13
Unique Sources 1
Submission Names:
7DkduxxH

JSON Written to File -- VTDL287F3DDA64B830A5AC5A6DF3266F7D08.json

Verbose VirusTotal Information Output:

MicroWorld-eScan True Trojan.Generic.7705996
nProtect True Trojan/W32.Small.29184.SN
CAT-QuickHeal True TrojanDropper.Dapato.bnnu
McAfee True Generic Dropper!ff3
Malwarebytes True Trojan.Inject
K7AntiVirus True Riskware
TheHacker False None
NANO-Antivirus True Trojan.Win32.Dapato.vpmxh
F-Prot False None
Symantec True Trojan.Gen.2
Norman True Suspicious_Gen4.AWDSR
TotalDefense False None
TrendMicro-HouseCall True TROJ_GEN.RCBC8HQ
Avast True MX97:ShellCode-I [Expl]
eSafe False None
ClamAV False None
Kaspersky True Trojan-Dropper.Win32.Dapato.bnnu
BitDefender True Trojan.Generic.7705996
Agnitum True Trojan.DR.Dapato!qkvVtOGNQlE
SUPERAntiSpyware False None
Emsisoft True Trojan.Generic.7705996 (B)
Comodo True UnclassifiedMalware
F-Secure True Trojan:W32/Agent.DUDB
DrWeb True Trojan.DownLoader6.49674
VIPRE True Trojan.Win32.Generic!BT
AntiVir True TR/Agent.29184.170
TrendMicro True TROJ_GEN.RCBC8HQ
McAfee-GW-Edition True Generic Dropper!ff3
Sophos True Troj/Hurgyu-A
Jiangmin True TrojanDropper.Dapato.mfq
Antiy-AVL True Trojan/Win32.Dapato.gen
Kingsoft True Win32.Troj.Dapato.(kcloud)
Microsoft True VirTool:Win32/Obfuscator.ABD
ViRobot True Dropper.A.Dapato.29184.J
AhnLab-V3 True Trojan/Win32.Inject
GData True Trojan.Generic.7705996
Commtouch False None
ByteHero False None
VBA32 True Trojan-Dropper.Dapato.bnnu
PCTools True Trojan.Gen
ESET-NOD32 True a variant of Win32/Inject.NFV
Rising True Suspicious
Ikarus True Win32.SuspectCrc
Fortinet True W32/Inject.NFV!tr
AVG True Dropper.Generic6.APFX
Panda True Generic Trojan

Malware Downloaded to File -- VTDL287F3DDA64B830A5AC5A6DF3266F7D08.danger

PCAP Downloaded to File -- VTDL287F3DDA64B830A5AC5A6DF3266F7D08.pcap

Virus Total Rescan Initiated for -- 287F3DDA64B830A5AC5A6DF3266F7D08 (Requery in 10 Mins)
</pre>
128 changes: 128 additions & 0 deletions vt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/usr/bin/python
# Virus Total API Integration Script
# Built on VT Test Script from: Adam Meyers ~ CrowdStrike
# Rewirtten / Modified / Personalized: Chris Clark ~ GD Fidelis CyberSecurity
# If things are broken let me know chris@xenosec.org
# No Licence or warranty expressed or implied, use however you wish!

import json, urllib, urllib2, argparse, hashlib, re, sys
from pprint import pprint

class vtAPI():
def __init__(self):
self.api = '<--------------PUBLIC-API-KEY-GOES-HERE----->'
self.base = 'https://www.virustotal.com/vtapi/v2/'

def getReport(self,md5):
param = {'resource':md5,'apikey':self.api,'allinfo': '1'}
url = self.base + "file/report"
data = urllib.urlencode(param)
result = urllib2.urlopen(url,data)
jdata = json.loads(result.read())
return jdata

def downloadFile(self,md5,name):
try:
param = {'hash':md5,'apikey':self.api}
url = self.base + "file/download"
data = urllib.urlencode(param)
req = urllib2.Request(url,data)
result = urllib2.urlopen(req)
downloadedfile = result.read()
if len(downloadedfile) > 0:
fo = open(name,"wb")
fo.write(downloadedfile)
fo.close()
print "\n\tMalware Downloaded to File -- " + name
else:
print md5 + " -- Not Found for Download"
except Exception:
print md5 + " -- Not Found for Download"

def downloadPcap(self,md5,name):
try:
req = urllib2.Request("https://www.virustotal.com/vtapi/v2/file/network-traffic?apikey="+self.api+"&hash="+md5)
result = urllib2.urlopen(req)
pcapfile = result.read()
if len(pcapfile) > 0 and '{"response_code": 0, "hash":' not in pcapfile :
fo = open(name,"wb")
fo.write(pcapfile)
fo.close()
print "\n\tPCAP Downloaded to File -- " + name
else:
print md5 + " -- PCAP Not Available"
except Exception:
print md5 + " -- PCAP Not Available"
def rescan(self,md5):
param = {'resource':md5,'apikey':self.api}
url = self.base + "file/rescan"
data = urllib.urlencode(param)
result = urllib2.urlopen(url,data)
print "\n\tVirus Total Rescan Initiated for -- " + md5 + " (Requery in 10 Mins)"


# Md5 Function

def checkMD5(checkval):
if re.match(r"([a-fA-F\d]{32})", checkval) == None:
md5 = md5sum(checkval)
return md5.upper()
else:
return checkval.upper()

def md5sum(filename):
fh = open(filename, 'rb')
m = hashlib.md5()
while True:
data = fh.read(8192)
if not data:
break
m.update(data)
return m.hexdigest()

def parse(it, md5, verbose, jsondump):
if it['response_code'] == 0:
print md5 + " -- Not Found in VT"
return 0
print "\n\tResults for MD5: ",it['md5'],"\n\n\tDetected by: ",it['positives'],'/',it['total'],'\n\tSophos Detection:',it['scans']['Sophos']['result'] ,'\n\tKaspersky Detection:',it['scans']['Kaspersky']['result'], '\n\tTrendMicro Detection:',it['scans']['TrendMicro']['result'],'\n\tScanned on:',it['scan_date'],'\n\tFirst Seen:',it['first_seen'],'\n\tLast Seen:',it['last_seen'],'\n\tUnique Sources',it['unique_sources'],'\n\tSubmission Names:'
for x in it['submission_names']:
print "\t\t",x
if jsondump == True:
jsondumpfile = open("VTDL" + md5 + ".json", "w")
pprint(it, jsondumpfile)
jsondumpfile.close()
print "\n\tJSON Written to File -- " + "VTDL" + md5 + ".json"

if verbose == True:
print '\n\tVerbose VirusTotal Information Output:\n'
for x in it['scans']:
print '\t', x,'\t' if len(x) < 7 else '','\t' if len(x) < 14 else '','\t',it['scans'][x]['detected'], '\t',it['scans'][x]['result']

def main():
opt=argparse.ArgumentParser(description="Search and Download from VirusTotal")
opt.add_argument("HashorPath", help="Enter the MD5 Hash or Path to File")
opt.add_argument("-s", "--search", action="store_true", help="Search VirusTotal")
opt.add_argument("-v", "--verbose", action="store_true", dest="verbose", help="Turn on verbosity of VT reports")
opt.add_argument("-j", "--jsondump", action="store_true",help="Dumps the full VT report to file (VTDLXXX.json)")
opt.add_argument("-d", "--download", action="store_true", help="Download File from Virustotal (VTDLXXX.danger)")
opt.add_argument("-p", "--pcap", action="store_true", help="Download Network Traffic (VTDLXXX.pcap)")
opt.add_argument("-r", "--rescan",action="store_true", help="Force Rescan with Current A/V Definitions")
if len(sys.argv)<=2:
opt.print_help()
sys.exit(1)
options= opt.parse_args()
vt=vtAPI()
md5 = checkMD5(options.HashorPath)
if options.search or options.jsondump or options.verbose:
parse(vt.getReport(md5), md5 ,options.verbose, options.jsondump)
if options.download:
name = "VTDL" + md5 + ".danger"
vt.downloadFile(md5,name)
if options.pcap:
name = "VTDL" + md5 + ".pcap"
vt.downloadPcap(md5,name)
if options.rescan:
vt.rescan(md5)

if __name__ == '__main__':
main()
95 changes: 95 additions & 0 deletions vtlite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/python
# Virus Total API Integration Script
# Built on VT Test Script from: Adam Meyers ~ CrowdStrike
# Rewirtten / Modified / Personalized: Chris Clark ~ GD Fidelis CyberSecurity
# If things are broken let me know chris@xenosec.org
# No Licence or warranty expressed or implied, use however you wish!

import json, urllib, urllib2, argparse, hashlib, re, sys
from pprint import pprint

class vtAPI():
def __init__(self):
self.api = '<--------------PUBLIC-API-KEY-GOES-HERE----->'
self.base = 'https://www.virustotal.com/vtapi/v2/'

def getReport(self,md5):
param = {'resource':md5,'apikey':self.api}
url = self.base + "file/report"
data = urllib.urlencode(param)
result = urllib2.urlopen(url,data)
jdata = json.loads(result.read())
return jdata

def rescan(self,md5):
param = {'resource':md5,'apikey':self.api}
url = self.base + "file/rescan"
data = urllib.urlencode(param)
result = urllib2.urlopen(url,data)
print "\n\tVirus Total Rescan Initiated for -- " + md5 + " (Requery in 10 Mins)"


# Md5 Function

def checkMD5(checkval):
if re.match(r"([a-fA-F\d]{32})", checkval) == None:
md5 = md5sum(checkval)
return md5.upper()
else:
return checkval.upper()

def md5sum(filename):
fh = open(filename, 'rb')
m = hashlib.md5()
while True:
data = fh.read(8192)
if not data:
break
m.update(data)
return m.hexdigest()

def parse(it, md5, verbose, jsondump):
if it['response_code'] == 0:
print md5 + " -- Not Found in VT"
return 0
print "\n\tResults for MD5: ",it['md5'],"\n\n\tDetected by: ",it['positives'],'/',it['total'],'\n'
if 'Sophos' in it['scans']:
print '\tSophos Detection:',it['scans']['Sophos']['result'],'\n'
if 'Kaspersky' in it['scans']:
print '\tKaspersky Detection:',it['scans']['Kaspersky']['result'], '\n'
if 'ESET-NOD32' in it['scans']:
print '\tESET Detection:',it['scans']['ESET-NOD32']['result'],'\n'

print '\tScanned on:',it['scan_date']

if jsondump == True:
jsondumpfile = open("VTDL" + md5 + ".json", "w")
pprint(it, jsondumpfile)
jsondumpfile.close()
print "\n\tJSON Written to File -- " + "VTDL" + md5 + ".json"

if verbose == True:
print '\n\tVerbose VirusTotal Information Output:\n'
for x in it['scans']:
print '\t', x,'\t' if len(x) < 7 else '','\t' if len(x) < 14 else '','\t',it['scans'][x]['detected'], '\t',it['scans'][x]['result']

def main():
opt=argparse.ArgumentParser(description="Search and Download from VirusTotal")
opt.add_argument("HashorPath", help="Enter the MD5/SHA1/256 Hash or Path to File")
opt.add_argument("-s", "--search", action="store_true", help="Search VirusTotal")
opt.add_argument("-v", "--verbose", action="store_true", dest="verbose", help="Turn on verbosity of VT reports")
opt.add_argument("-j", "--jsondump", action="store_true",help="Dumps the full VT report to file (VTDLXXX.json)")
opt.add_argument("-r", "--rescan",action="store_true", help="Force Rescan with Current A/V Definitions")
if len(sys.argv)<=2:
opt.print_help()
sys.exit(1)
options= opt.parse_args()
vt=vtAPI()
md5 = checkMD5(options.HashorPath)
if options.search or options.jsondump or options.verbose:
parse(vt.getReport(md5), md5 ,options.verbose, options.jsondump)
if options.rescan:
vt.rescan(md5)

if __name__ == '__main__':
main()

1 comment on commit 98835f5

@syadamalfian
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.