-
Notifications
You must be signed in to change notification settings - Fork 115
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Chris Clark
committed
Jul 1, 2015
0 parents
commit 98835f5
Showing
3 changed files
with
354 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
98835f5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#12 #10