Advertisement
opexxx

vt.py

May 27th, 2014
1,079
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 77.57 KB | None | 0 0
  1.  
  2. #!/usr/bin/env python2.7
  3.  
  4. # Full VT APIv2 functions added by Andriy (aka doomedraven) Brukhovetskyy (Twitter : @d00m3dr4v3n)
  5. # No Licence or warranty expressed or implied, use however you wish!
  6. # For more information look at:
  7. #
  8. # https://www.virustotal.com/en/documentation/public-api
  9. # https://www.virustotal.com/en/documentation/private-api
  10.  
  11. import os
  12. import re
  13. import sys
  14. import csv
  15. import time
  16. import json
  17. import glob
  18. import time
  19. import hashlib
  20. import argparse
  21. import requests
  22. import ConfigParser
  23. import texttable as tt
  24. from urlparse import urlparse
  25. from operator import methodcaller
  26. from dateutil.relativedelta import relativedelta
  27.  
  28. def private_api_access_error():
  29.       print '\n[!] You don\'t have permission for this operation, Looks like you trying to access to PRIVATE API functions\n'
  30.       sys.exit()
  31.  
  32. def get_adequate_table_sizes(scans, short = False, short_list = False):
  33.      
  34.       av_size     = 0
  35.       result_size = 0
  36.       version     = 0
  37.      
  38.       for engine in scans:
  39.            
  40.             if scans.get(engine) and scans[engine].get('result'):
  41.            
  42.                   if short and engine in short_list:
  43.                  
  44.                         if len(engine) < 30 and len(engine) > av_size:
  45.                             av_size = len(engine)
  46.                        
  47.                         if len(scans[engine]['result']) < 50 and len(scans[engine]['result']) > result_size:
  48.                             result_size = len(scans[engine]['result'])
  49.                            
  50.                         if scans[engine].has_key('version') and scans[engine]['version']:
  51.                              
  52.                               if len(scans[engine]['version']) < 20 and len(scans[engine]['version']) > version:
  53.                                     version = len(scans[engine]['version'])
  54.                                    
  55.                         else:
  56.                             version = 8
  57.            
  58.                   elif not short:
  59.                        
  60.                         if len(engine) < 30 and len(engine) > av_size:
  61.                             av_size = len(engine)
  62.                        
  63.                         if len(scans[engine]['result']) < 50 and len(scans[engine]['result']) > result_size:
  64.                             result_size = len(scans[engine]['result'])
  65.                            
  66.                         if scans[engine].has_key('version') and scans[engine]['version']:
  67.                              
  68.                               if len(scans[engine]['version']) < 20 and len(scans[engine]['version']) > version:
  69.                                     version = len(scans[engine]['version'])
  70.                                    
  71.                         else:
  72.                             version = 8      
  73.                        
  74.       return av_size, result_size, version
  75.  
  76. def parse_conf(file_name):
  77.      
  78.       try:
  79.             confpath = os.path.expanduser(file_name)
  80.            
  81.             if os.path.exists(confpath):
  82.                  
  83.                   config = ConfigParser.RawConfigParser()
  84.                   config.read(confpath)
  85.                   apikey = config.get('vt', 'apikey')
  86.                  
  87.                   return apikey
  88.            
  89.             else:
  90.                   sys.exit('\nFile {0} don\'t exists\n'.format(confpath))
  91.          
  92.       except Exception:
  93.             sys.exit('No API key provided and cannot read ~/.vtapi. Specify an API key in vt.py or in ~/.vtapi or  in your file')
  94.        
  95. def pretty_print(block, headers, sizes = False, align = False):
  96.  
  97.   tab = tt.Texttable()
  98.  
  99.   if isinstance(block, list):
  100.     plist = []
  101.    
  102.     for line in block:
  103.      
  104.       if len(headers) == 1:
  105.         plist.append([line])
  106.      
  107.       else:
  108.         plist.append(map(lambda key: line[key] if line.get(key) else ' -- ', headers))
  109.    
  110.     if len(plist) > 1 and isinstance(plist[0], list):
  111.       tab.add_rows(plist)
  112.    
  113.     else:
  114.       tab.add_row(plist[0])
  115.  
  116.   else:
  117.     row   = map(lambda key: block[key] if block.get(key) else ' -- ', headers)
  118.     tab.add_row(row)
  119.  
  120.   tab.header(headers)
  121.  
  122.   if not align:
  123.       align = map(lambda key: 'l', headers)
  124.  
  125.   if sizes:
  126.       tab.set_cols_width(sizes)
  127.  
  128.   tab.set_cols_align(align)
  129.  
  130.   print tab.draw()
  131.    
  132. def pretty_print_special(rows, headers, sizes = False, align = False):
  133.       tab = tt.Texttable()
  134.       tab.add_rows(rows)
  135.      
  136.       if sizes:
  137.             tab.set_cols_width(sizes)
  138.      
  139.       if align:
  140.             tab.set_cols_align(align)
  141.            
  142.       tab.header(headers)
  143.      
  144.       print '\n', tab.draw()
  145.    
  146. def is_file(value):
  147.       try:
  148.             if isinstance(value, list):
  149.                  
  150.                   if os.path.isfile(value[0]):
  151.                         return True, value[0]
  152.                  
  153.                   else:
  154.                         return False, value[0]
  155.            
  156.             elif isinstance(value, basestring):
  157.                  
  158.                   if os.path.isfile(value):
  159.                         return True, value
  160.                
  161.                   else:
  162.                         return False, value
  163.      
  164.       except IndexError:
  165.             print '\n[!] You need to provide some arguments\n'
  166.             sys.exit()
  167.  
  168. def jsondump(jdata, md5):
  169.          
  170.       jsondumpfile = open('VTDL_{name}.json'.format(name = md5), 'w')
  171.       json.dump(jdata, jsondumpfile)
  172.       jsondumpfile.close()
  173.            
  174.       print '\n\tJSON Written to File -- VTDL_{md5}.json\n'.format(md5 = md5)
  175.  
  176. def load_file(file_path):
  177.      
  178.       try:
  179.             log    = open(file_path, 'r').read()
  180.             jdata  =  json.loads(log)
  181.             return jdata
  182.      
  183.       except TypeError:
  184.             print '\n[!] Check your json dump file\n'
  185.  
  186. def print_results(jdata, undetected_downloaded_samples, detected_communicated,\
  187.                   undetected_communicated_samples, detected_urls):
  188.    
  189.        
  190.     if jdata.get('undetected_downloaded_samples') and undetected_downloaded_samples:
  191.        
  192.         print '\n[+] Latest undetected files that were downloaded from this domain/ip\n'
  193.         pretty_print(sorted(jdata['undetected_downloaded_samples'], key=methodcaller('get', 'date'), reverse=True), ['positives', 'total','date','sha256'], [15, 10, 20, 70], ['c', 'c', 'c', 'c'])
  194.            
  195.    
  196.     if jdata.get('detected_communicating_samples') and detected_communicated:
  197.        
  198.         print '\n[+] Latest detected files that communicate with this domain/ip\n'
  199.         pretty_print(sorted(jdata['detected_communicating_samples'] , key=methodcaller('get', 'scan_date'), reverse=True), ['positives', 'total','date','sha256'], [15, 10, 20, 70], ['c', 'c', 'c', 'c'])
  200.              
  201.          
  202.     if jdata.get('undetected_communicating_samples') and undetected_communicated_samples:
  203.        
  204.         print '\n[+] Latest undetected files that communicate with this domain/ip\n'
  205.         pretty_print(sorted(jdata['undetected_communicating_samples'], key=methodcaller('get', 'date'), reverse=True), ['positives', 'total','date','sha256'], [15, 10, 20, 70], ['c', 'c', 'c', 'c'])
  206.        
  207.      
  208.     if jdata.get('detected_urls') and detected_urls:
  209.        
  210.         print '\n[+] Latest detected URLs\n'
  211.         pretty_print(sorted(jdata['detected_urls'], key=methodcaller('get', 'scan_date'), reverse=True), ['positives', 'total','scan_date','url'], [15, 10, 20, 100], ['c', 'c', 'c', 'l'])
  212.  
  213. def get_detections(scans):
  214.      
  215.       plist   = [[]]
  216.       engines = ['Sophos', 'Kaspersky', 'TrendMicro']
  217.       cont    = 3
  218.  
  219.       for engine in engines:
  220.           if scans.get(engine) and scans[engine].get('result'):
  221.               plist.append([engine,
  222.                             scans[engine]['result'],
  223.                             scans[engine]['version'] if scans[engine].has_key('version') and scans[engine]['version'] else ' -- ' ,
  224.                             scans[engine]['update']  if scans[engine].has_key('update')  and scans[engine]['update']  else ' -- '
  225.                            ])
  226.               cont -= 1
  227.      
  228.       for engine in scans:
  229.             if scans.get(engine) and scans[engine].get('result') and cont > 0:
  230.                   plist.append([engine,
  231.                                 scans[engine]['result'],
  232.                                 scans[engine]['version'] if scans[engine].has_key('version') and scans[engine]['version'] else ' -- ' ,
  233.                                 scans[engine]['update']  if scans[engine].has_key('update')  and scans[engine]['update']  else ' -- '
  234.                                ])
  235.                   cont -= 1
  236.            
  237.             elif cont == 0:
  238.                   break
  239.            
  240.       if cont != 3:
  241.             av_size, result_size, version = get_adequate_table_sizes(scans, True, ['Sophos', 'Kaspersky', 'TrendMicro'])
  242.             pretty_print_special(plist,
  243.                                  ['Vendor name',  'Result', 'Version', 'Last Update'],
  244.                                  [av_size, result_size, version, 12],
  245.                                  ['r', 'l', 'l', 'c']
  246.                                 )
  247.  
  248. def dump_csv(filename, scans):
  249.     print filename
  250.     f = open('VTDL{0}.csv'.format(filename), 'w')
  251.     writer = csv.writer(f, delimiter=',')
  252.     writer.writerow(('Vendor name', 'Detected', 'Result', 'Version', 'Last Update'))
  253.      
  254.     for x in sorted(scans):
  255.       writer.writerow([x,
  256.                        'True' if scans[x]['detected'] else 'False', scans[x]['result'] if scans[x]['result'] else ' -- ',
  257.                        scans[x]['version'] if scans[x].has_key('version') and scans[x]['version'] else ' -- ' ,
  258.                        scans[x]['update']  if scans[x].has_key('update')  and scans[x]['update']  else ' -- '
  259.                       ])
  260.          
  261.     f.close()
  262.    
  263.     print '\n\tCSV file dumped as: VTDL{0}.csv'.format(filename)
  264.  
  265. def parse_report(jdata, hash_report, verbose, dump, csv_write, url_report = False, not_exit = False):
  266.  
  267.   filename = ''
  268.  
  269.   if jdata['response_code'] != 1:
  270.    
  271.     if not not_exit:
  272.       return False
  273.    
  274.     else:
  275.       print '\n[-] Status : {info}\n'.format(info=jdata['verbose_msg'])
  276.       sys.exit()
  277.  
  278.   if jdata.get('scan_date') : print '\nScanned on : \n\t{0}'.format(jdata['scan_date'])
  279.   if jdata.get('total') : print '\nDetections:\n\t {positives}/{total} Positives/Total'.format(positives = jdata['positives'], total = jdata['total'])
  280.    
  281.   if url_report:
  282.       if jdata.get('url') : print '\nScanned url :\n\t {url}'.format(url = jdata['url'])
  283.  
  284.   else:
  285.     if not verbose:
  286.       get_detections(jdata['scans'])
  287.      
  288.     print '\n\tResults for MD5    : {0}'.format(jdata['md5'])
  289.     print '\tResults for SHA1   : {0}'.format(jdata['sha1'])
  290.     print '\tResults for SHA256 : {0}'.format(jdata['sha256'])
  291.  
  292.   if verbose == True and jdata.get('scans'):
  293.     print '\nVerbose VirusTotal Information Output:'
  294.     plist = [[]]
  295.    
  296.     for x in sorted(jdata['scans']):
  297.            
  298.         plist.append([x,
  299.                       'True' if jdata['scans'][x]['detected'] else 'False',
  300.                       jdata['scans'][x]['result']  if jdata['scans'][x]['result'] else ' -- ',
  301.                       jdata['scans'][x]['version'] if jdata['scans'][x].has_key('version') and jdata['scans'][x]['version'] else ' -- ' ,
  302.                       jdata['scans'][x]['update']  if jdata['scans'][x].has_key('update')  and jdata['scans'][x]['update']  else ' -- '
  303.                      ])
  304.    
  305.     av_size, result_size, version = get_adequate_table_sizes(jdata['scans'])
  306.    
  307.     if version == 8:
  308.       version_align = 'c'
  309.      
  310.     else:
  311.       version_align = 'l'
  312.    
  313.     if av_size != 0 and result_size != 0 and version != 0:      
  314.       pretty_print_special(plist,
  315.                            ['Vendor name', 'Detected', 'Result', 'Version', 'Last Update'],
  316.                            [av_size, 9, result_size, version, 12],
  317.                            ['r', 'c', 'l', version_align, 'c']
  318.                            )
  319.    
  320.     else:
  321.       pretty_print_special(plist,
  322.                            ['Vendor name', 'Detected', 'Result', 'Version', 'Last Update'],
  323.                            [30, 9, 6, 15, 12],
  324.                            ['r', 'c', 'l', version_align, 'c']
  325.                            )
  326.  
  327.     del plist        
  328.  
  329.   if dump == True:
  330.     jsondump(jdata, hash_report)
  331.  
  332.   if csv_write:
  333.       filename = jdata['md5']
  334.       dump_csv(filename, jdata['scans'])
  335.  
  336.   if jdata.get('permalink') : print "\n\tPermanent Link : {0}\n".format(jdata['permalink'])
  337.  
  338.   return True
  339.  
  340. ## Static variable decorator for function
  341. def static_var(varname, value):
  342.     def decorate(func):
  343.        
  344.         setattr(func, varname, value)
  345.        
  346.         return func
  347.    
  348.     return decorate
  349.  
  350. ## Track how many times we issue a request
  351. @static_var("counter", 0)
  352. ## Track when the first request was sent
  353. @static_var("start_time", 0)
  354. def get_response(url, method="get", **kwargs):
  355.      
  356.       ## Set on first request
  357.       if get_response.start_time == 0:
  358.             get_response.start_time = time.time()
  359.  
  360.       ## Increment every request
  361.       get_response.counter = 1
  362.  
  363.       jdata    = ''
  364.       response = ''
  365.      
  366.       while True:
  367.             try:
  368.                   response = getattr(requests, method)(url, **kwargs)
  369.            
  370.             except requests.exceptions.ConnectionError:
  371.                   print '\n[!] Can\'t resolv hostname, check your internet conection\n'
  372.                   sys.exit()
  373.  
  374.             if response.status_code == 403:
  375.                   private_api_access_error()
  376.  
  377.             if response.status_code != 204:
  378.                  
  379.                   try:  
  380.                         jdata = response.json()  
  381.            
  382.                   except:
  383.                         jdata = response.json
  384.                  
  385.                   break
  386.            
  387.             ## Determine minimum time we need to wait for limit to reset
  388.             wait_time = 59 - int(time.time() - get_response.start_time)
  389.  
  390.             if wait_time < 0:
  391.                   wait_time = 60
  392.  
  393.             print "Reached per minute limit of {0:d}; waiting {1:d} seconds\n".format(get_response.counter, wait_time)
  394.  
  395.             time.sleep(wait_time)
  396.  
  397.             ## Reset static vars
  398.             get_response.counter    = 0
  399.             get_response.start_time = 0
  400.                  
  401.       return jdata, response
  402.  
  403. class vtAPI():
  404.    
  405.     def __init__(self, apikey):
  406.  
  407.         self.api   = apikey
  408.         self.base  = 'https://www.virustotal.com/vtapi/v2/'
  409.    
  410.     def getReport(self, hash_report, allinfo = False, verbose = False, dump = False, csv_write = False, not_exit = False):
  411.      
  412.       """
  413.      A md5/sha1/sha256 hash will retrieve the most recent report on a given sample. You may also specify a scan_id (sha256-timestamp as returned by the file upload API)
  414.      to access a specific report. You can also specify a CSV list made up of a combination of hashes and scan_ids (up to 4 items or 25 if you have private api with the
  415.      standard request rate), this allows you to perform a batch request with one single call.
  416.      """
  417.      
  418.       result, name = is_file(hash_report)
  419.      
  420.       if result:
  421.           jdata = load_file(name)
  422.           dump  = False
  423.            
  424.       else:
  425.             if isinstance(hash_report, list) and len(hash_report) == 1:
  426.                 hash_report = hash_report[0]
  427.            
  428.             elif isinstance(hash_report, basestring):
  429.                 hash_report = hash_report
  430.            
  431.             elif len(hash_report) > 25 and not isinstance(hash_report, basestring):
  432.                 print '[-] To many urls for scanning, MAX 25'
  433.                 sys.exit()
  434.            
  435.             else:
  436.                 hash_report = ', '.join(map(lambda hash_part: hash_part, hash_report))
  437.                 print hash_report
  438.            
  439.             params  = {'resource':hash_report,'apikey':self.api}
  440.            
  441.             if allinfo:
  442.               params.setdefault('allinfo', allinfo)
  443.                
  444.             url = self.base + 'file/report'
  445.            
  446.             jdata, response = get_response(url, params=params)
  447.              
  448.       if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  449.            
  450.             if not_exit:
  451.                 return False
  452.            
  453.             else:
  454.                   if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  455.                   sys.exit()
  456.  
  457.       if allinfo == '1':
  458.            
  459.           if dump:
  460.               jsondump(jdata, name)
  461.          
  462.           if jdata.get('md5')    : print '\nMD5    : {md5}'.format(    md5 = jdata['md5'])
  463.           if jdata.get('sha1')   : print 'SHA1   : {sha1}'.format(    sha1 = jdata['sha1'])
  464.           if jdata.get('sha256') : print 'SHA256 : {sha256}'.format(sha256 = jdata['sha256'])
  465.           if jdata.get('ssdeep') : print 'SSDEEP : {ssdeep}'.format(ssdeep = jdata['ssdeep'])
  466.          
  467.           if jdata.get('scan_date') : print '\nScan  Date     : {scan_date}'.format(  scan_date = jdata['scan_date'])
  468.           if jdata.get('first_seen'): print 'First Submission : {first_seen}'.format(first_seen = jdata['first_seen'])
  469.           if jdata.get('last_seen') : print 'Last  Submission : {last_seen}'.format(  last_seen = jdata['last_seen'])
  470.          
  471.           if jdata.get('submission_names'):
  472.             print '\nSubmission names:'
  473.             for name in jdata['submission_names']:
  474.                   print '\t{name}'.format(name = name)
  475.          
  476.           if jdata.get('type') : print '\nFile Type   : {type_f}'.format(type_f = jdata['type'])
  477.           if jdata.get('size') : print 'File Size   : {size}'.format(    size   = jdata['size'])
  478.           if jdata.get('tags') : print 'Tags   : {tags}'.format(tags = ', '.join(map(lambda tag: tag, jdata['tags'])))
  479.          
  480.           if jdata.get('additional_info'):
  481.             #[u'pe-resource-list', u'pe-resource-langs', u'pe-timestamp', u'imports', u'pe-entry-point', u'pe-resource-types', u'sections', u'pe-machine-type']
  482.             if jdata['additional_info']['magic'] : print 'Magic  : {magic}'.format(magic = jdata['additional_info']['magic'])
  483.            
  484.             if jdata['additional_info'].get('referers'):
  485.               print '\nReferers:'
  486.               for referer in jdata['additional_info']['referers']:
  487.                   print '\t{referer}'.format(referer = referer)
  488.            
  489.             if jdata['additional_info'].get('sigcheck'):
  490.                  
  491.                   print '\nPE signature block:'
  492.                   plist = [[]]
  493.                  
  494.                   for sig in jdata['additional_info']['sigcheck']:
  495.                       plist.append([sig, jdata['additional_info']['sigcheck'][sig]])
  496.                  
  497.                   pretty_print_special(plist, ['Name','Value'])
  498.                   del plist
  499.            
  500.             if jdata['additional_info'].get('exiftool'):
  501.                  
  502.                   print '\nExifTool file metadata:'
  503.                   plist = [[]]
  504.                  
  505.                   for exiftool in jdata['additional_info']['exiftool']:
  506.                         plist.append([exiftool, jdata['additional_info']['exiftool'][exiftool]])
  507.                        
  508.                   pretty_print_special(plist, ['Name','Value'])
  509.                   del plist
  510.            
  511.             if jdata['additional_info'].get('sections'):
  512.                 pretty_print_special(jdata['additional_info']['sections'],
  513.                                      ['Name', 'Virtual address', 'Virtual size', 'Raw size', 'Entropy', 'MD5'],
  514.                                      [10,10,10,10,10, 35],
  515.                                      ['c', 'c', 'c', 'c', 'c', 'c']
  516.                                     )
  517.            
  518.             if jdata['additional_info'].get('imports'):
  519.            
  520.                   print '\nImports:'
  521.            
  522.                   for imported in jdata['additional_info']['imports']:
  523.                        
  524.                         print '\t{0}'.format(imported)
  525.                        
  526.                         for valor in jdata['additional_info']['imports'][imported]:
  527.                               print '\t\t{0}'.format(valor)
  528.                        
  529.             if jdata['additional_info'].get('trid'):
  530.                   print '\nTrID:'                  
  531.                   print '\t{trid}'.format(trid = jdata['additional_info']['trid'].replace('\n', '\n\t'))
  532.                  
  533.           if jdata.get('total') : print '\nDetections:\n\t{positives}/{total} Positives/Total\n'.format(positives = jdata['positives'], total = jdata['total'])
  534.          
  535.           if jdata.get('scans'):
  536.            
  537.             plist = [[]]
  538.             for x in jdata['scans']:
  539.                plist.append([x,  'True' if jdata['scans'][x]['detected'] else 'False', jdata['scans'][x]['result']])
  540.            
  541.             pretty_print_special(plist,
  542.                                  ['Name', 'Detected', 'Result'],
  543.                                  [30, 9, 55],
  544.                                  ['l', 'c', 'l'])
  545.            
  546.             del plist
  547.            
  548.           if jdata.get('permalink') : print '\nPermanent link : {permalink}\n'.format(permalink = jdata['permalink'])
  549.           return True
  550.      
  551.       else:
  552.           result = parse_report(jdata, hash_report, verbose, dump, csv_write, False, not_exit)
  553.           return result
  554.    
  555.     def rescan(self, hash_rescan, date = False, period = False, repeat = False, notify_url = False, notify_changes_only = False, delete = False):
  556.        
  557.         """
  558.        This API allows you to rescan files in VirusTotal's file store without having to resubmit them, thus saving bandwidth.
  559.        """
  560.        
  561.         if len(hash_rescan) == 1:
  562.             hash_rescan = hash_rescan
  563.        
  564.         elif isinstance(hash_re, basestring):
  565.             hash_rescan = [hash_rescan]
  566.        
  567.         elif len(hash_rescan) > 25 and not isinstance(hash_rescan, basestring):
  568.             print '[-] To many urls for scanning, MAX 25'
  569.             sys.exit()
  570.        
  571.         else:
  572.             hash_rescan = ', '.join(map(lambda hash_part: hash_part, hash_rescan))
  573.        
  574.         url = self.base + 'file/rescan'      
  575.        
  576.         for hash_part in hash_rescan:
  577.            
  578.             params  = {'resource':hash_part,'apikey':self.api}
  579.            
  580.             if delete:
  581.                   url = url + '/delete'
  582.             else:
  583.                   if date:
  584.                    params.setdefault('date', date)
  585.                    
  586.                   if period:
  587.                     params.setdefault('period', period)
  588.                    
  589.                     if repeat:
  590.                       params.setdefault('repeat', repeat)
  591.                  
  592.                   if notify_url:
  593.                     params.setdefault('notify_url', notify_url)
  594.          
  595.                     if notify_changes_only:
  596.                       params.setdefault('notify_changes_only',notify_changes_only)
  597.                  
  598.            
  599.             jdata, response = get_response(url, params=params, method='post')
  600.            
  601.             if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  602.               if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  603.               sys.exit()
  604.            
  605.             if isinstance(jdata, list):
  606.                 for jdata_part in jdata:
  607.                   if jdata_part.get('sha256') : print '[+] Check rescan result with sha256 in few minuts : \n\tSHA256 : {sha256}'.format(sha256 = jdata_part['sha256'])
  608.                   if jdata.get('permalink')   : print '\tPermanent link : {permalink}\n'.format(permalink = jdata['permalink'])
  609.             else:
  610.               if jdata.get('sha256')    : print '[+] Check rescan result with sha256 in few minuts : \n\tSHA256 : {sha256}'.format(sha256 = jdata_part['sha256'])
  611.               if jdata.get('permalink') : print '\tPermanent link : {permalink}\n'.format(permalink = jdata['permalink'])
  612.    
  613.     def fileScan(self, files, verbose = False, notify_url = False, notify_changes_only = False, dump = False, csv_write = False, scan = False):
  614.  
  615.         """
  616.        Allows to send a file to be analysed by VirusTotal.
  617.        Before performing your submissions we encourage you to retrieve the latest report on the files,
  618.        if it is recent enough you might want to save time and bandwidth by making use of it. File size limit is 32MB,
  619.        in order to submmit files up to 200MB you must request an special upload URL.
  620.        
  621.        Before send to scan, file will be checked if not scanned before, for save bandwich and VT resources :)
  622.        """
  623.  
  624.         if len(files) == 1 and isinstance(files, list):
  625.             files = glob.glob('{files}'.format(files=files[0]))
  626.        
  627.         elif isinstance(files, basestring):
  628.             files = glob.glob('{files}'.format(files=files))
  629.      
  630.         params = {'apikey':self.api}
  631.        
  632.         if notify_url:
  633.           params.setdefault('notify_url', notify_url)
  634.          
  635.           if notify_changes_only:
  636.             params.setdefault('notify_changes_only',notify_changes_only)
  637.  
  638.         url = self.base+'file/scan'
  639.  
  640.         for submit_file in files:
  641.  
  642.             readed = open(submit_file, 'rb').read()
  643.             md5    = hashlib.md5(readed).hexdigest()
  644.          
  645.             not_exit = True
  646.          
  647.             result = self.getReport(md5, False, verbose, dump, csv_write, not_exit)
  648.            
  649.             if not result and scan == True:
  650.                  
  651.                   if (os.path.getsize(submit_file) / 1048576) <= 32:
  652.                        
  653.                     if os.path.isfile(submit_file):
  654.                        
  655.                       print 'Submiting file: {filename}'.format(filename = submit_file)
  656.      
  657.                       file_name = os.path.split(submit_file)[-1]
  658.                       files  = {"file": (file_name, open(submit_file, 'rb'))}
  659.                      
  660.                       try:
  661.                        
  662.                           jdata, response = get_response(url, files=files, params=params, method="post")
  663.                          
  664.                           if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  665.                             if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  666.                             sys.exit()
  667.                    
  668.                           if jdata.get('md5')    : print '\n\tResults for MD5    : {md5}'.format(md5 = jdata['md5'])
  669.                           if jdata.get('sha1')   : print '\tResults for SHA1   : {sha1}'.format(sha1 = jdata['sha1'])
  670.                           if jdata.get('sha256') : print '\tResults for SHA256 : {sha256}'.format(sha256 = jdata['sha256'])
  671.                    
  672.                           if jdata.get('verbose_msg') :  print '\n\tStatus         : {verb_msg}'.format(verb_msg = jdata['verbose_msg'])
  673.                           if jdata.get('permalink')   :  print '\tPermanent link : {permalink}\n'.format(permalink = jdata['permalink'])
  674.                      
  675.                       except UnicodeDecodeError:
  676.                         print '\n[!] Sorry filaname is not utf-8 format, other format not suported at the moment'
  677.                         print '[!] Ignored file: {file}\n'.format(file = submit_file)
  678.  
  679.                   else:
  680.                     print '[!] Ignored file: {file}'.format(file = submit_file)
  681.                  
  682.                    
  683.             elif not result and scan == False:
  684.                   print 'Report for file : {0} not fount'.format(submit_file)
  685.    
  686.     def url_scan_and_report(self, urls, key, verbose, dump=False, csv_write=False, add_to_scan='0'):
  687.        
  688.         """
  689.        Url scan:
  690.        URLs can also be submitted for scanning. Once again, before performing your submission we encourage you to retrieve the latest report on the URL,
  691.        if it is recent enough you might want to save time and bandwidth by making use of it.
  692.        
  693.        Url report:
  694.        A URL will retrieve the most recent report on the given URL. You may also specify a scan_id (sha256-timestamp as returned by the URL submission API)
  695.        to access a specific report. At the same time, you can specify a space separated list made up of a combination of hashes and scan_ids so as to perform a batch
  696.        request with one single call (up to 4 resources or 25 if you have private api, per call with the standard request rate).
  697.        """
  698.      
  699.         url_uploads = []
  700.         result = False
  701.         md5 = ''
  702.        
  703.         if os.path.basename(urls[0]) != 'urls_for_scan.txt':
  704.  
  705.           result, name = is_file(urls)
  706.      
  707.         else:
  708.             resutl = False
  709.            
  710.             if os.path.isfile(urls[0]):
  711.                   urls = open(urls[0], 'rb').readlines()
  712.  
  713.         if result:
  714.             jdata = load_file(name)
  715.             dump  = False
  716.          
  717.         else:
  718.            
  719.            if isinstance(urls, list) and len(urls) == 1:
  720.               url_uploads = [urls]
  721.                  
  722.            elif isinstance(urls, basestring):
  723.               url_uploads = [urls]  
  724.                  
  725.            elif len(urls) > 1 and not isinstance(urls, basestring):
  726.              
  727.               #ToDo add private api check here with posibility set 25 urls in one request
  728.              
  729.               start = -4
  730.               end   = 0
  731.               increment = 4
  732.              
  733.               while True:
  734.            
  735.                   start += increment
  736.                  
  737.                   if len(urls) > end+4:
  738.                         end   += increment
  739.                   elif len(urls) <= end+4:
  740.                         end = len(urls)
  741.  
  742.            
  743.                   if key == 'scan':
  744.                      url_uploads.append(['\n'.join(map(lambda url: url, urls[start:end]))])
  745.                            
  746.                   elif key == 'report':
  747.                      url_uploads.append([', '.join(map(lambda url: url.replace('\n',''), urls[start:end]))])
  748.                      
  749.                   if end == len(urls):
  750.                         break
  751.         cont = 0
  752.        
  753.         for url_upload in url_uploads:
  754.            
  755.             cont += 1
  756.            
  757.             if key == 'scan':
  758.               print 'Submitting url(s) for analysis: \n\t{url}'.format(url = url_upload[0].replace(', ','\n\t'))
  759.               params = {'url':url_upload[0],'apikey':self.api}
  760.               url   = self.base + 'url/scan'
  761.              
  762.             elif key == 'report':
  763.               print '\nSearching for url(s) report: \n\t{url}'.format(url = url_upload[0].replace(', ','\n\t'))
  764.               params = {'resource':url_upload[0],'apikey':self.api, 'scan':add_to_scan}
  765.               url   = self.base + 'url/report'
  766.  
  767.             jdata, response = get_response(url, params=params, method="post")  
  768.        
  769.             if isinstance(jdata, list):
  770.                
  771.               for jdata_part in jdata:
  772.                  
  773.                 if jdata_part['response_code'] == 0 or jdata_part['response_code'] == -1:
  774.                   if jdata_part.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata_part['verbose_msg'])
  775.                   break
  776.                  
  777.                 if dump:
  778.                   md5 = hashlib.md5(jdata_part['url']).hexdigest()
  779.                
  780.                 if key == 'report':
  781.                       url_report = True
  782.                       parse_report(jdata_part, md5, verbose, dump, url_report)
  783.                
  784.                 elif key == 'scan':
  785.                   if jdata_part.get('verbose_msg') : print '\n\tStatus : {verb_msg}\t{url}'.format(verb_msg  = jdata_part['verbose_msg'], url = jdata_part['url'])
  786.                   if jdata_part.get('permalink')   : print '\tPermanent link : {permalink}'.format(permalink = jdata_part['permalink'])
  787.    
  788.             else:
  789.              
  790.               if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  791.                 if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  792.                 sys.exit()
  793.              
  794.               if dump:
  795.                 md5 = hashlib.md5(jdata['url']).hexdigest()
  796.              
  797.               if key == 'report':
  798.                       url_report = True
  799.                       parse_report(jdata, md5, verbose, dump, csv_write, url_report)
  800.                      
  801.               elif key == 'scan':
  802.                   if jdata.get('verbose_msg') : print '\n\tStatus : {verb_msg}\t{url}'.format(verb_msg  = jdata['verbose_msg'], url = jdata['url'])
  803.                   if jdata.get('permalink')   : print '\tPermanent link : {permalink}'.format(permalink = jdata['permalink'])    
  804.  
  805.             if cont%4 == 0:
  806.                   print '[+] Sleep 60 seconds between the requests'
  807.                   time.sleep(60)
  808.      
  809.     def getIP(self, ip, dump=False, detected_urls=False, detected_downloaded_samples=False, undetected_downloaded_samples=False,\
  810.                                                          detected_communicated=False, undetected_communicated=False):
  811.  
  812.       """
  813.      A valid IPv4 address in dotted quad notation, for the time being only IPv4 addresses are supported.
  814.      """
  815.      
  816.       result, name = is_file(ip)
  817.      
  818.       if result:
  819.             jdata = load_file(name)
  820.             dump  = False
  821.             md5   = ''
  822.      
  823.       else:
  824.           params  = {'ip':ip,'apikey':self.api}
  825.           url     = self.base + 'ip-address/report'
  826.        
  827.           jdata, response = get_response(url, params=params)
  828.  
  829.              
  830.       if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  831.           if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  832.           sys.exit()  
  833.        
  834.       if jdata['response_code'] == 1:
  835.           if jdata.get('verbose_msg') : print '\nStatus: {verb_msg}'.format(verb_msg = jdata['verbose_msg'])
  836.        
  837.           if jdata.get('detected_downloaded_samples') and detected_downloaded_samples:
  838.               print '\n[+] Latest detected files that were downloaded from this domain/ip\n'
  839.               pretty_print(sorted(jdata['detected_downloaded_samples'], key=methodcaller('get', 'date'), reverse=True), ['positives', 'total','date','sha256'], [15, 10, 20, 70], ['c', 'c', 'c', 'c'])
  840.            
  841.           print_results(jdata, undetected_downloaded_samples, detected_communicated, undetected_communicated, detected_urls)
  842.            
  843.           if jdata.get('resolutions'):
  844.               print '\n[+] Lastest domain resolved\n'
  845.               pretty_print(sorted(jdata['resolutions'], key=methodcaller('get', 'last_resolved'), reverse=True), ['last_resolved', 'hostname'])
  846.        
  847.           if dump == True:
  848.               md5 = hashlib.md5(name).hexdigest()
  849.               jsondump(jdata, md5)
  850.            
  851.       else:
  852.             if jdata.get('verbose_msg') : print '\n[-] Status: {info}\n'.format(info=jdata['verbose_msg'])
  853.             sys.exit()  
  854.            
  855.     def getDomain(self, domain, dump=False, trendmicro=False, detected_urls=False, undetected_downloaded_samples=False, alexa_domain_info=False,\
  856.                   wot_domain_info=False, websense_threatseeker=False, bitdefender=False, webutation_domain=False,\
  857.                                          detected_communicated=False, undetected_communicated=False, pcaps=False):
  858.        
  859.         """
  860.        Get domain last scan, detected urls and resolved IPs
  861.        """
  862.        
  863.         result, name = is_file(domain)
  864.      
  865.         if result:
  866.             jdata = load_file(name)
  867.             dump  = False
  868.             md5   = ''
  869.            
  870.         else:
  871.             params  = {'domain':domain,'apikey':self.api}
  872.             url    = self.base + "domain/report"
  873.        
  874.             jdata, response = get_response(url, params=params)
  875.              
  876.         if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  877.           if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  878.           sys.exit()
  879.        
  880.         if jdata.get('response_code') and jdata['response_code'] == 1:
  881.                
  882.             if jdata.get('verbose_msg') : print '\nStatus : {verb_msg}'.format(verb_msg = jdata['verbose_msg'])
  883.            
  884.             if jdata.get('TrendMicro category') and trendmicro:
  885.                
  886.                 print '\n[+] TrendMicro category'
  887.                 print '\t',jdata['TrendMicro category']
  888.            
  889.             if jdata.get('Websense ThreatSeeker category') and websense_threatseeker:
  890.                
  891.                 print '\n[+] Websense ThreatSeeker category'
  892.                 print '\t', jdata['Websense ThreatSeeker category']
  893.            
  894.             if jdata.get('BitDefender category') and bitdefender:
  895.                
  896.                 print '\n[+] BitDefender category'
  897.                 print '\t', jdata['BitDefender category']
  898.            
  899.             if jdata.get('Alexa domain info') and alexa_domain_info:
  900.              
  901.               print '\n[+] Alexa domain info'
  902.               print '\t', jdata['Alexa domain info']
  903.            
  904.             if jdata.get('WOT domain info') and wot_domain_info:
  905.              
  906.               print '\n[+] WOT domain info'
  907.               plist = [[]]
  908.              
  909.               for jdata_part in jdata['WOT domain info']:
  910.                 plist.append([jdata_part, jdata['WOT domain info'][jdata_part]])
  911.              
  912.               pretty_print_special(plist, ['Name', 'Value'], [25, 20], ['c','c'])
  913.              
  914.               del plist
  915.              
  916.             if jdata.get('Webutation domain info') and webutation_domain:
  917.              
  918.               print "\n[+] Webutation"
  919.               plist = [[]]
  920.              
  921.               for jdata_part in jdata['Webutation domain info']:
  922.                 plist.append([jdata_part, jdata['Webutation domain info'][jdata_part]])
  923.                
  924.               pretty_print_special(plist, ['Name', 'Value'], [25, 20], ['c','c'])
  925.              
  926.               del plist
  927.              
  928.             print_results(jdata, undetected_downloaded_samples, detected_communicated, undetected_communicated, detected_urls)
  929.            
  930.             if jdata.get('pcaps') and pcaps:
  931.              
  932.               print '\n'
  933.               pretty_print(jdata['pcaps'], ['pcaps'], [70], ['c'])
  934.            
  935.             if jdata.get('resolutions'):
  936.              
  937.               print '\n[+] Passive DNS replication\n'
  938.               pretty_print(sorted(jdata['resolutions'], key=methodcaller('get', 'last_resolved'), reverse=True), ['last_resolved', 'ip_address'], [25, 20], ['c', 'c'])
  939.        
  940.             if dump == True:
  941.                 md5 = hashlib.md5(name).hexdigest()
  942.                 jsondump(jdata, md5)
  943.                
  944.         else:
  945.             print '\n[-] {info}\n'.format(info=jdata['verbose_msg'])
  946.    
  947.     def clusters(self, value, dump = False, by_id = False):
  948.      
  949.       """
  950.      VirusTotal has built its own in-house file similarity clustering functionality. At present,
  951.      this clustering works only on PE files and is based on a very basic PE feature hash, which
  952.      can be very often confused by certain compression and packing strategies. In other words,
  953.      this clustering logic is no holly grail.
  954.  
  955.      This API offers a programmatic access to the clustering section of VirusTotal Intelligence:
  956.  
  957.      https://www.virustotal.com/intelligence/clustering/
  958.  
  959.      Please note that you must be logged in with a valid VirusTotal Community user with access
  960.      to VirusTotal Intelligence in order to be able to view the clustering listing.
  961.  
  962.      All of the API responses are JSON objects, if no clusters were identified for the given
  963.      time frame, this JSON will have a response_code property equal to 0, if there was some
  964.      sort of error with your query this code will be set to -1, if your query succeded and
  965.      file similarity clusters were found it will have a value of 1 and the rest of the JSON
  966.      properties will contain the clustering information.
  967.      """
  968.      
  969.       result, name = is_file(value)
  970.      
  971.       if result:
  972.             jdata = load_file(name)
  973.             dump  = False
  974.             md5   = ''
  975.      
  976.       else:
  977.           url    = self.base + 'file/clusters'
  978.          
  979.           params = {'apikey': self.api}
  980.                    
  981.           if by_id:
  982.             params.setdefault('query', 'cluster:{0}'.format(value))
  983.          
  984.           else:
  985.             params.setdefault('date', name)
  986.          
  987.           jdata, response = get_response(url, params=params)
  988.          
  989.       if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  990.           if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  991.           sys.exit()
  992.      
  993.       if jdata.get('verbose_msg')    : print '\nStatus : {verb_msg}'.format(verb_msg = jdata['verbose_msg'])
  994.       if jdata.get('size_top200')    : print '\n\tSize top 200   : {size_top200}'.format(size_top200 = jdata['size_top200'])  
  995.       if jdata.get('num_clusters')   : print '\tNum Clusters   : {num_clusters}'.format(num_clusters = jdata['num_clusters'])
  996.       if jdata.get('num_candidates') : print '\tNum Candidates : {num_candidates}'.format(num_candidates = jdata['num_candidates'])
  997.  
  998.       if jdata.get('clusters'):
  999.        
  1000.           plist = [[]]
  1001.        
  1002.           for line in jdata['clusters']:
  1003.               plist.append([line['label'], line['avg_positives'], line['id'], line['size']])
  1004.            
  1005.           pretty_print_special(plist, ['Label', 'AV Detections', 'Id', 'Size'], [40, 15, 80, 8], ['l','c','l','c'])
  1006.      
  1007.       if dump:
  1008.           jsondump(jdata, 'clusters_{0}'.format(name))
  1009.                
  1010.     def comment(self, hash_co, action, dump = False, before_or_comment = False):
  1011.        
  1012.       """
  1013.      Add comment:
  1014.      The actual review, you can tag it using the "#" twitter-like syntax (e.g. #disinfection #zbot) and reference users using the "@" syntax (e.g. @VirusTotalTeam).
  1015.      
  1016.      Get comments:
  1017.      The application answers with the comments sorted in descending order according to their date. Please note that, for timeout reasons, the application will only
  1018.      answer back with at most 25 comments. If the answer contains less than 25 comments it means that there are no more comments for that item. On the other hand,
  1019.      if 25 comments were returned you should keep issuing further calls making use of the optional before parameter, this parameter should be fixed to the oldest
  1020.      (last in the list) comment's date token, exactly in the same way as returned by your previous API call (e.g. 20120404132340).
  1021.      """
  1022.      
  1023.       result, name = is_file(hash_co)
  1024.      
  1025.       if result:
  1026.             jdata = load_file(name)
  1027.             dump  = False
  1028.             md5   = ''
  1029.            
  1030.       else:
  1031.         params = {'resource':hash_co,'apikey':self.api}
  1032.        
  1033.         if action == 'add':
  1034.           url = self.base + 'comments/put'
  1035.           params.setdefault('comment',before_or_commentz)
  1036.          
  1037.           jdata, response = get_response(url, params=params, method="post")
  1038.          
  1039.         elif action == 'get':
  1040.           url = self.base + 'comments/get'
  1041.          
  1042.           if before_or_comment:
  1043.             params.setdefault('before', before_or_comment)
  1044.          
  1045.           jdata, response = get_response(url, params=params)
  1046.          
  1047.         else:
  1048.             print '\n[!] Support only get/add comments action \n'
  1049.             sys.exit()
  1050.      
  1051.       if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  1052.         if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  1053.         sys.exit()
  1054.        
  1055.       if action == 'add':
  1056.           if jdata.get('verbose_msg') : print '\nStatus : {0}\n'.format(jdata['verbose_msg'])
  1057.            
  1058.       else:
  1059.           if jdata['response_code'] == 0:
  1060.             print '\n[!] This analysis doen\'t have any comment\n'
  1061.            
  1062.           else:
  1063.             if jdata.get('comments'):
  1064.               for comment in jdata['comments']:
  1065.                
  1066.                 date_format   = time.strptime(comment['date'], '%Y%m%d%H%M%S')
  1067.                 date_formated = '{year}:{month}:{day} {hour}:{minuts}:{seconds}'.format(year = date_format.tm_year,month = date_format.tm_mon,\
  1068.                                                                                         day = date_format.tm_mday, hour = date_format.tm_hour,\
  1069.                                                                                         minuts = date_format.tm_min, seconds = date_format.tm_sec)
  1070.                
  1071.                 if comment.get('date')    : print 'Date    : {0}'.format(date_formated)
  1072.                 if comment.get('comment') : print 'Comment : {0}\n'.format(comment['comment'])
  1073.        
  1074.     def download(self, hash_file, file_type = False):
  1075.      
  1076.       """
  1077.        About pcaps
  1078.        VirusTotal runs a distributed setup of Cuckoo sandbox machines that execute the files we receive.
  1079.        Execution is attempted only once, upon first submission to VirusTotal, and only Portable Executables
  1080.        under 10MB in size are ran. The execution of files is a best effort process, hence, there are no guarantees
  1081.        about a report being generated for a given file in our dataset.
  1082.  
  1083.        Files that are successfully executed may communicate with certain network resources, all this communication
  1084.        is recorded in a network traffic dump (pcap file). This API allows you to retrieve the network traffic dump
  1085.        generated during the file's execution.
  1086.        
  1087.        The md5/sha1/sha256 hash of the file whose network traffic dump you want to retrieve.
  1088.      """
  1089.        
  1090.       result, name = is_file(hash_file)
  1091.      
  1092.       if result:
  1093.             print '\n[!]Hash cannot be file\n'
  1094.             sys.exit()
  1095.       else:
  1096.         params = {'apikey': self.api, 'hash': hash_file}
  1097.        
  1098.         if file_type == 'pcap':
  1099.           jdata, response = get_response(self.base + 'file/network-traffic', params=params)
  1100.           name = 'VTDL_{hash}.pcap'.format(hash = hash_file)
  1101.          
  1102.         elif file_type == 'file':
  1103.           jdata, response = get_response(self.base + 'file/download', params=params)
  1104.            
  1105.           if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  1106.             if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  1107.             sys.exit()
  1108.          
  1109.           name = 'VTDL_{hash}.dangerous'.format(hash = hash_file)
  1110.        
  1111.         else:
  1112.             print '\n[!] File_type must be pcap or file\n'
  1113.             sys.exit()
  1114.            
  1115.      
  1116.         file_save = response.content
  1117.         if len(file_save) > 0 and '{"response_code": 0, "hash":' not in file_save :
  1118.           fo = open(name,"w")
  1119.           fo.write(file_save)
  1120.           fo.close()
  1121.           print '\n\tDownloaded to File -- {name}\n'.format(name = name)
  1122.  
  1123.     def distribution(self, local_file, action, before = False, after = False, reports = False, limit = False, allinfo = False, dump = False):
  1124.      
  1125.       """
  1126.      Note that scan items are not kept forever in the distribution queue, they are automatically removed after 6 hours counting from the time
  1127.      they were put in the queue. You have a 6 hours time frame to get an item from the queue. The timestamp property value is what you need to
  1128.      iterate through your queue using the before and after call parameters.
  1129.      """
  1130.      
  1131.       result, name = is_file(local_file)
  1132.      
  1133.       if result:
  1134.             jdata = load_file(name)
  1135.             dump  = False  
  1136.      
  1137.       else:
  1138.             params = {'apikey':self.api}
  1139.                  
  1140.             if before:
  1141.                   params.setdefault('before', before)
  1142.                        
  1143.             if after:
  1144.                   params.setdefault('after', after)
  1145.                        
  1146.             if limit:
  1147.                   params.setdefault('limit', limit)
  1148.            
  1149.             if action == 'file':            
  1150.                  
  1151.                   if reports:
  1152.                         params.setdefault('reports', str(reports).lower())
  1153.                  
  1154.                   url = self.base + 'file/distribution'
  1155.            
  1156.             elif action == 'url':
  1157.                  
  1158.                   if allinfo:
  1159.                        
  1160.                         params.setdefault('allinfo', '1')
  1161.                  
  1162.                   url = self.base + 'url/distribution'
  1163.            
  1164.             jdata, response = get_response(url, params=params)
  1165.      
  1166.       if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  1167.         if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  1168.         sys.exit()
  1169.      
  1170.       for vt_file in jdata:
  1171.  
  1172.             if action == 'file':
  1173.              
  1174.               try:  
  1175.                  if vt_file.get('name') : print '\n\nName   : {name}'.format(name = vt_file['name'])
  1176.              
  1177.               except UnicodeEncodeError:
  1178.                 print ''
  1179.  
  1180.               if vt_file.get('md5')    : print '\nMD5    : {md5}'.format(    md5 = vt_file['md5'])
  1181.               if vt_file.get('sha1')   : print 'SHA1   : {sha1}'.format(    sha1 = vt_file['sha1'])
  1182.               if vt_file.get('sha256') : print 'SHA256 : {sha256}'.format(sha256 = vt_file['sha256'])
  1183.              
  1184.               if vt_file.get('filetype') : print '\nType   : {filetype}'.format(filetype = vt_file['filetype'])
  1185.               if vt_file.get('size')     : print 'Size   : {size}'.format(size = vt_file['size'])
  1186.              
  1187.               if vt_file.get('source_id')  : print 'Source Id  : {source_id}'.format(source_id   = vt_file['source_id'])  
  1188.               if vt_file.get('first_seen') : print 'First Seen : {first_seen}'.format(first_seen = vt_file['first_seen'])
  1189.               if vt_file.get('last_seen')  : print 'Last  Seen : {last_seen}'.format(  last_seen = vt_file['last_seen'])
  1190.              
  1191.               if vt_file.get('report'):
  1192.                
  1193.                 plist = [[]]
  1194.                
  1195.                 for key in vt_file['report']:
  1196.                   plist.append([key, 'True' if jdata[0]['report'][key][0] else 'False', jdata[0]['report'][key][1], jdata[0]['report'][key][2]])
  1197.      
  1198.                 pretty_print_special(plist, ['Vendor name', 'Detection', 'Version', 'Update'])
  1199.    
  1200.               if vt_file.get('link') : print '\nLink : {link}'.format(link = vt_file['link'])
  1201.          
  1202.             elif action == 'url':
  1203.              
  1204.               if vt_file.get('scan_date')  : print '\nScan Date : {scan_date}'.format(scan_date = vt_file['scan_date'])
  1205.               if vt_file.get('last_seen')  : print 'Last Seen : {last_seen}'.format(  last_seen = vt_file['last_seen'])
  1206.               if vt_file.get('positives') and vt_file.get('total') : print '\nDetections:\n\t{positives}/{total} Positives/Total\n'.format(positives = vt_file['positives'], total = vt_file['total'])
  1207.              
  1208.               if vt_file.get('score') : print 'Score     : {score}'.format(score = vt_file['score'])
  1209.               if vt_file.get('url')   : print 'Url       : {url}'.format(    url = vt_file['url'])
  1210.              
  1211.               if vt_file.get('timestamp') : print 'Timestamp : {timestamp}'.format(timestamp = vt_file['timestamp'])
  1212.              
  1213.               if vt_file.get('additional_info'):
  1214.                    
  1215.                     print '\n\nAdditional info:'
  1216.                     plist = [[]]
  1217.                    
  1218.                     for key in vt_file['additional_info']:
  1219.                        
  1220.                         if isinstance(vt_file['additional_info'][key], dict):
  1221.                           plist.append([key, ''.join(map(lambda key_temp:'{key_temp}:{value}\n'.format(key_temp=key_temp, value=vt_file['additional_info'][key][key_temp]), vt_file['additional_info'][key]))])
  1222.                          
  1223.                         elif isinstance(vt_file['additional_info'][key], list):
  1224.                           plist.append([key, '\n'.join(vt_file['additional_info'][key])])
  1225.                          
  1226.                         else:
  1227.                           plist.append([key, vt_file['additional_info'][key]])
  1228.              
  1229.                     pretty_print_special(plist, ['Name', 'Value'],[40, 70])
  1230.                    
  1231.               if vt_file.get('scans'):
  1232.                    
  1233.                     plist = [[]]
  1234.              
  1235.                     for key in vt_file['scans']:
  1236.                        
  1237.                           plist.append([key, 'True' if vt_file['scans'][key]['detected'] else 'False', vt_file['scans'][key]['result']])
  1238.                    
  1239.                     pretty_print_special(plist, ['Vendor name', 'Detection', 'Result'])
  1240.                    
  1241.              
  1242.               if vt_file.get('permalink') : print '\nPermanent link : {link}\n'.format(link = vt_file['permalink'])
  1243.                  
  1244.       if dump:
  1245.             jsondump(jdata, 'distribution_{date}'.format(date = time.strftime("%Y-%m-%d")))
  1246.    
  1247.     def behaviour(self, search_hash, dump = False, network = False, process = False, summary = False):
  1248.      
  1249.       result, name = is_file(search_hash)
  1250.      
  1251.       if result:
  1252.             jdata = load_file(name)
  1253.             dump  = False
  1254.            
  1255.       else:
  1256.             params = {'apikey': self.api, 'hash': search_hash}
  1257.             url    = self.base + 'file/behaviour'
  1258.            
  1259.             jdata, response = get_response(url, params=params)
  1260.      
  1261.       if jdata['response_code'] == 0 or jdata['response_code'] == -1:
  1262.           if jdata.get('verbose_msg') : print '\n[!] Status : {verb_msg}\n'.format(verb_msg = jdata['verbose_msg'])
  1263.           sys.exit()
  1264.      
  1265.       print '\nInfo\n'
  1266.      
  1267.       pretty_print(jdata['info'], ['started', 'ended', 'duration', 'version'])
  1268.      
  1269.       if network:
  1270.      
  1271.             print '\nHTTP requests\n'
  1272.            
  1273.             if jdata.get('network') and jdata['network'].get('http'):
  1274.               for http in jdata['network']['http']:
  1275.                  
  1276.                 if http.get('uri')  : print '\tURL        : {0}'.format(http['uri'])        
  1277.                 if http.get('host') : print '\tHost       : {0}'.format(http['host'])
  1278.                 #if http.get('port') : print 'port       : {0}'.format(http['port'])      
  1279.                 #if http.get('path') : print 'path       : {0}'.format(http['path'])
  1280.                 if http.get('method')     : print '\tMethod     : {0}'.format(http['method'])
  1281.                 if http.get('user-agent') : print '\tUser-agent : {0}'.format(http['user-agent'])
  1282.                 #if http.get('version') : print 'version    : {0}'.format(http['version'])    
  1283.                 #if http.get('data')    : print 'data       : {0}'.format(http['data'].replace('\r\n\r\n', '\n\t').replace('\r\n','\n\t\t'))
  1284.                 #if http.get('body')    : print 'body       : {0}'.format(http['body'])
  1285.                 print '\n'
  1286.      
  1287.             pretty_print(jdata['network']['hosts'], ['hosts'])
  1288.            
  1289.             print '\nDNS requests\n'
  1290.             pretty_print(jdata['network']['dns'],   ['ip', 'hostname'])
  1291.            
  1292.             print '\nTCP Connections\n'
  1293.  
  1294.             unique = []
  1295.            
  1296.             for block in jdata['network']['tcp']:
  1297.                  
  1298.                   if not [block['src'],  block['dst'], block['sport'], block['dport']] in unique:
  1299.                        
  1300.                         unique.append([block['src'], block['dst'], block['sport'], block['dport']])
  1301.            
  1302.             pretty_print_special(unique,   ['src', 'dst', 'sport', 'dport'])
  1303.            
  1304.             del unique
  1305.            
  1306.             print '\nUDP Connections'
  1307.  
  1308.             unique = []
  1309.            
  1310.             for block in jdata['network']['udp']:
  1311.            
  1312.                   if not [block['src'],  block['dst'], block['sport'], block['dport']] in unique:
  1313.            
  1314.                         unique.append([block['src'], block['dst'], block['sport'], block['dport']])
  1315.            
  1316.             pretty_print_special(unique,   ['src', 'dst', 'sport', 'dport'])
  1317.            
  1318.             del unique
  1319.      
  1320.       if process:
  1321.             print '\nBehavior\n'
  1322.             print '\nProcesses\n'
  1323.            
  1324.             for process_id in jdata['behavior']['processes']:
  1325.                
  1326.                 plist = []
  1327.                
  1328.                 if process_id.get('parent_id')  : print '\nParent  Id : {0}'.format(process_id['parent_id'])
  1329.                 if process_id.get('process_id') : print 'Process Id : {0}'.format(process_id['process_id'])
  1330.                
  1331.                 if process_id.get('first_seen') :
  1332.                  
  1333.                     date_format   = time.strptime(process_id['first_seen'][:14], '%Y%m%d%H%M%S')
  1334.                     date_formated = '{year}:{month}:{day} {hour}:{minuts}:{seconds}'.format(year = date_format.tm_year,month = date_format.tm_mon,\
  1335.                                                                                               day = date_format.tm_mday, hour = date_format.tm_hour,\
  1336.                                                                                               minuts = date_format.tm_min, seconds = date_format.tm_sec)
  1337.                     print 'First Seen : {0}'.format(date_formated)
  1338.                
  1339.                 if process_id.get('process_name') : print '\nProcess Name : {0}'.format(process_id['process_name'])
  1340.            
  1341.                 if process_id.get('calls'):
  1342.                  
  1343.                     for process_part in process_id['calls']:
  1344.                      
  1345.                         plist = [[]]
  1346.                      
  1347.                         for key in process_part:
  1348.                
  1349.                               if isinstance(process_part[key], list):
  1350.                                     if process_part[key] != [] and isinstance(process_part[key][0], dict):
  1351.                                        
  1352.                                         temp_list = []
  1353.                                        
  1354.                                         for part in process_part[key]:
  1355.                                        
  1356.                                             temp_list.append('\n'.join(map(lambda key_temp:'{key_temp}:{value}\n'.format(key_temp=key_temp, value=part[key_temp]), part.keys())))
  1357.                                        
  1358.                                         plist.append([key, ''.join(temp_list)])
  1359.                                        
  1360.                                         del temp_list
  1361.                                     else:
  1362.                                         plist.append([key, '\n'.join(process_part[key])])
  1363.                                  
  1364.                               elif isinstance(process_part[key], dict):
  1365.                                  
  1366.                                   temp_list = []
  1367.                                  
  1368.                                   for part in process_part[key]:
  1369.                                       temp_list += map(lambda key_temp:'{key_temp}:{value}\n'.format(key_temp=key_temp, value=part[key_temp]), part.keys())
  1370.                                  
  1371.                                   plist.append([key, ''.join(temp_list)])
  1372.                                  
  1373.                                   del temp_list
  1374.                               else:
  1375.                                   plist.append([key, process_part[key]])
  1376.                      
  1377.                         pretty_print_special(plist, ['Name', 'Value'], [10, 50])
  1378.  
  1379.                         del plist
  1380.            
  1381.                     print '\n'+'='*20+' FIN '+'='*20
  1382.            
  1383.            
  1384.             print '\nProcess Tree\n'
  1385.             for tree in jdata['behavior']['processtree']:
  1386.               for key in tree.keys():
  1387.                 print '\t{key}:{value}'.format(key=key, value=tree[key])
  1388.             print '\n'
  1389.      
  1390.       if summary:
  1391.      
  1392.             print '\nOpened files\n'
  1393.             pretty_print(sorted(jdata['behavior']['summary']['files']), ['files'], [150])
  1394.            
  1395.             print '\nSet keys\n'
  1396.             pretty_print(sorted(jdata['behavior']['summary']['keys']), ['keys'], [150])
  1397.            
  1398.             print '\nCreated mutexes\n'
  1399.             pretty_print(sorted(jdata['behavior']['summary']['mutexes']), ['mutexes'], [100])
  1400.      
  1401.       if dump == True:
  1402.           md5 = hashlib.md5(name).hexdigest()
  1403.           jsondump(jdata, md5)
  1404.  
  1405.  
  1406. def main(apikey):
  1407.   opt=argparse.ArgumentParser('value',description='Scan/Search/ReScan/JSON parse')
  1408.  
  1409.   opt.add_argument('value', nargs='*', help='Enter the Hash, Path to File(s) or Url(s)')
  1410.   opt.add_argument('-c', '--config-file', action='store',  default='~/.vtapi', help='Path to configuration file')
  1411.  
  1412.   opt.add_argument('-fs', '--file-search',  action='store_true',               help='File(s) search, this option, don\'t upload file to VirusTotal, just search by hash, support linux name wildcard, example: /home/user/*malware*, if file was scanned, you will see scan info, for full scan report use verbose mode, and dump if you want save already scanned samples')
  1413.   opt.add_argument('-f',  '--file-scan',    action='store_true', dest='files', help='File(s) scan, support linux name wildcard, example: /home/user/*malware*, if file was scanned, you will see scan info, for full scan report use verbose mode, and dump if you want save already scanned samples')
  1414.   opt.add_argument('-u',  '--url-scan',     action='store_true',               help='Url scan, support space separated list, Max 4 urls (or 25 if you have private api), but you can provide more urls, for example with public api,  5 url - this will do 2 requests first with 4 url and other one with only 1, or you can specify file filename must be urls_for_scan.txt, and one url per line')
  1415.   opt.add_argument('-ur', '--url-report',   action='store_true',               help='Url(s) report, support space separated list, Max 4 (or 25 if you have private api) urls, you can use --url-report --url-scan options for analysing url(s) if they are not in VT data base, read previev description about more then max limits or file with urls')
  1416.  
  1417.   opt.add_argument('-d', '--domain-info',   action='store_true', dest='domain',  help='Retrieves a report on a given domain (PRIVATE API ONLY! including the information recorded by VirusTotal\'s Passive DNS infrastructure)')
  1418.   opt.add_argument('-i', '--ip-info',       action='store_true', dest='ip',      help='A valid IPv4 address in dotted quad notation, for the time being only IPv4 addresses are supported.')
  1419.   opt.add_argument('-s', '--search',        action='store_true',                 help='A md5/sha1/sha256 hash for which you want to retrieve the most recent report. You may also specify a scan_id (sha256-timestamp as returned by the scan API) to access a specific report. You can also specify a space separated list made up of a combination of hashes and scan_ids Public API up to 4 items/Private API up to 25 items, this allows you to perform a batch request with one single call.')
  1420.   opt.add_argument('--report-all-info',     action='store_true',                 help='PRIVATE API ONLY! If specified and set to one, the call will return additional info, other than the antivirus results, on the file being queried. This additional info includes the output of several tools acting on the file (PDFiD, ExifTool, sigcheck, TrID, etc.), metadata regarding VirusTotal submissions (number of unique sources that have sent the file in the past, first seen date, last seen date, etc.), and the output of in-house technologies such as a behavioural sandbox.')
  1421.   opt.add_argument('-ac', '--add-comment',  action='store_true',                 help='The actual review, you can tag it using the "#" twitter-like syntax (e.g. #disinfection #zbot) and reference users using the "@" syntax (e.g. @VirusTotalTeam). supported hashes MD5/SHA1/SHA256')
  1422.   opt.add_argument('-gc', '--get-comments', action='store_true',                 help='Either a md5/sha1/sha256 hash of the file or the URL itself you want to retrieve')
  1423.   opt.add_argument('--get-comments-before', action='store',      dest='date',default=False,  help='PRIVATE API ONLY! A datetime token that allows you to iterate over all comments on a specific item whenever it has been commented on more than 25 times. Token format 20120725170000 or 2012-07-25 17 00 00 or 2012-07-25 17:00:00')
  1424.  
  1425.   opt.add_argument('-v', '--verbose', action='store_true', dest='verbose', help='Turn on verbosity of VT reports')
  1426.   opt.add_argument('-j', '--dump',    action='store_true',                 help='Dumps the full VT report to file (VTDL{md5}.json), if you (re)scan many files/urls, their json data will be dumped to separetad files')
  1427.   opt.add_argument('--csv',           action='store_true',                 help='Dumps the AV\'s detections to file (VTDL{md5}.csv)')
  1428.  
  1429.   rescan = opt.add_argument_group('Rescan options')
  1430.   rescan.add_argument('-r', '--rescan', action='store_true',              help='Allows you to rescan files in VirusTotal\'s file store without having to resubmit them, thus saving bandwidth., support space separated list, MAX 25 hashes')
  1431.   rescan.add_argument('--delete',       action='store_true',              help='PRIVATE API ONLY! A md5/sha1/sha256 hash for which you want to delete the scheduled scan')
  1432.   rescan.add_argument('--date',         action='store',      dest='date', help='PRIVATE API ONLY! A Date in one of this formats (example: 20120725170000 or 2012-07-25 17 00 00 or 2012-07-25 17:00:00) in which the rescan should be performed. If not specified the rescan will be performed immediately.')
  1433.   rescan.add_argument('--period',       action='store',                   help='PRIVATE API ONLY! Period in days in which the file should be rescanned. If this argument is provided the file will be rescanned periodically every period days, if not, the rescan is performed once and not repated again.')
  1434.   rescan.add_argument('--repeat',       action='store',                   help='PRIVATE API ONLY! Used in conjunction with period to specify the number of times the file should be rescanned. If this argument is provided the file will be rescanned the given amount of times, if not, the file will be rescanned indefinitely.')
  1435.  
  1436.   scan_rescan = opt.add_argument_group('File scan/Rescan shared options')
  1437.   scan_rescan.add_argument('--notify-url',          action='store',      help='PRIVATE API ONLY! An URL where a POST notification should be sent when the scan finishes.')
  1438.   scan_rescan.add_argument('--notify-changes-only', action='store_true', help='PRIVATE API ONLY! Used in conjunction with --notify-url. Indicates if POST notifications should be sent only if the scan results differ from the previous one.')
  1439.  
  1440.   domain_opt = opt.add_argument_group('Domain/IP shared verbose mode options, by default just show resolved IPs/Passive DNS')
  1441.   domain_opt.add_argument('--alexa-domain-info',             action='store_true', default=False, help='Just Domain option: Show Alexa domain info')
  1442.   domain_opt.add_argument('--wot-domain-info',               action='store_true', default=False, help='Just Domain option: Show WOT domain info')
  1443.   domain_opt.add_argument('--trendmicro',                    action='store_true', default=False, help='Just Domain option: Show TrendMicro category info')
  1444.   domain_opt.add_argument('--websense-threatseeker',         action='store_true', default=False, help='Just Domain option: Show Websense ThreatSeeker category')
  1445.   domain_opt.add_argument('--bitdefender',                   action='store_true', default=False, help='Just Domain option: Show BitDefender category')
  1446.   domain_opt.add_argument('--webutation-domain',             action='store_true', default=False, help='Just Domain option: Show Webutation domain info')
  1447.   domain_opt.add_argument('--detected-urls',                 action='store_true', default=False, help='Just Domain option: Show latest detected URLs')
  1448.   domain_opt.add_argument('--pcaps',                         action='store_true', default=False, help='Just Domain option: Show all pcaps hashes')
  1449.   domain_opt.add_argument('--detected-downloaded-samples',   action='store_true', default=False, help='Domain/Ip options: Show latest detected files that were downloaded from this ip')
  1450.   domain_opt.add_argument('--undetected-downloaded-samples', action='store_true', default=False, help='Domain/Ip options: Show latest undetected files that were downloaded from this domain/ip')
  1451.   domain_opt.add_argument('--detected-communicated',         action='store_true', default=False, help='Domain/Ip Show latest detected files that communicate with this domain/ip')
  1452.   domain_opt.add_argument('--undetected-communicated',       action='store_true', default=False, help='Domain/Ip Show latest undetected files that communicate with this domain/ip')
  1453.  
  1454.   behaviour = opt.add_argument_group('Behaviour options - PRIVATE API ONLY!')
  1455.   behaviour.add_argument('--behaviour', action='store_true',  help='The md5/sha1/sha256 hash of the file whose dynamic behavioural report you want to retrieve.\
  1456.                       VirusTotal runs a distributed setup of Cuckoo sandbox machines that execute the files we receive. Execution is attempted only once, upon\
  1457.                       first submission to VirusTotal, and only Portable Executables under 10MB in size are ran. The execution of files is a best effort process,\
  1458.                       hence, there are no guarantees about a report being generated for a given file in our dataset. a file did indeed produce a behavioural report,\
  1459.                       a summary of it can be obtained by using the file scan lookup call providing the additional HTTP POST parameter allinfo=1. The summary will\
  1460.                       appear under the behaviour-v1 property of the additional_info field in the JSON report.This API allows you to retrieve the full JSON report\
  1461.                       of the file\'s execution as outputted by the Cuckoo JSON report encoder.')
  1462.  
  1463.   behaviour.add_argument('--behavior-network',     action='store_true', help='Show network activity')
  1464.   behaviour.add_argument('--behavior-process',     action='store_true', help='Show processes')
  1465.   behaviour.add_argument('--behavior-summary',     action='store_true', help='Show summary')
  1466.  
  1467.  
  1468.   private = opt.add_argument_group('Additional PRIVATE API options')
  1469.   private.add_argument('--pcap',                 action='store_true', help='The md5/sha1/sha256 hash of the file whose network traffic dump you want to retrieve. Will save as VTDL_{hash}.pcap')
  1470.   private.add_argument('--download',             action='store_true', help='The md5/sha1/sha256 hash of the file you want to download. Will save as VTDL_{hash}.dangerous')
  1471.   private.add_argument('--clusters',             action='store_true', help='A specific day for which we want to access the clustering details, example: 2013-09-10')
  1472.   #private.add_argument('--search-by-cluster-id', action='store_true', help=' the id property of each cluster allows users to list files contained in the given cluster, example: vhash 0740361d051)z1e3z 2013-09-10')
  1473.   private.add_argument('--distribution-files',   action='store_true', help='Timestamps are just integer numbers where higher values mean more recent files. Both before and after parameters are optional, if they are not provided the oldest files in the queue are returned in timestamp ascending order.')
  1474.   private.add_argument('--distribution-urls',    action='store_true', help='Timestamps are just integer numbers where higher values mean more recent urls. Both before and after parameters are optional, if they are not provided the oldest urls in the queue are returned in timestamp ascending order.')
  1475.  
  1476.   dist = opt.add_argument_group('Distribution options - PRIVATE API ONLY!')
  1477.   dist.add_argument('--before',       action='store',                     help='File/Url option. Retrieve files/urls received before the given timestamp, in timestamp descending order.')
  1478.   dist.add_argument('--after',        action='store',                     help='File/Url option. Retrieve files/urls received after the given timestamp, in timestamp ascending order.')
  1479.   dist.add_argument('--reports',      action='store_true', default=False, help='Include the files\' antivirus results in the response. Possible values are \'true\' or \'false\' (default value is \'false\').')
  1480.   dist.add_argument('--limit',        action='store',                     help='File/Url option. Retrieve limit file items at most (default: 1000).')
  1481.   dist.add_argument('--allinfo',      action='store_true',                help='will include the results for each particular URL scan (in exactly the same format as the URL scan retrieving API). If the parameter is not specified, each item returned will onlycontain the scanned URL and its detection ratio.')
  1482.   dist.add_argument('--massive-download', action='store_true', default=False, help='Show information how to get massive download work')
  1483.    
  1484.   options = opt.parse_args()
  1485.  
  1486.   #it's just a check, if you want set your apikey into value, go to the end of file
  1487.   if apikey == '<--------------apikey-here-------->':
  1488.  
  1489.       apikey = parse_conf(options.config_file)
  1490.      
  1491.       if apikey is None:
  1492.             sys.exit('No API key provided and cannot read ~/.vtapi. Specify an API key in vt.py or in ~/.vtapi or  in your file')
  1493.  
  1494.   vt=vtAPI(apikey)
  1495.  
  1496.   if options.date:
  1497.       options.date = options.date.replace('-','').replace(':','').replace(' ','')
  1498.    
  1499.   if options.verbose and (options.domain or options.ip or options.behaviour):
  1500.     options.detected_urls = options.undetected_downloaded_samples = options.wot_domain_info  = options.websense_threatseeker   = \
  1501.                             options.detected_communicated         = options.trendmicro       = options.undetected_communicated = \
  1502.                             options.alexa_domain_info             = options.bitdefender      = options.webutation_domain       = options.pcaps = \
  1503.                             options.detected_downloaded_samples   = options.behavior_network = options.behavior_process        = options.behavior_summary = True
  1504.  
  1505.   if options.files:
  1506.     vt.fileScan(options.value, options.verbose, options.notify_url, options.notify_changes_only, options.dump, options.csv, scan = True)
  1507.  
  1508.   elif options.file_search:
  1509.       vt.fileScan(options.value, options.verbose, options.notify_url, options.notify_changes_only, options.dump, options.csv)
  1510.  
  1511.   elif options.url_scan and not options.url_report:
  1512.     vt.url_scan_and_report(options.value, "scan", options.verbose, options.dump, options.csv)
  1513.  
  1514.   elif options.url_report:
  1515.       action = 0
  1516.      
  1517.       if options.url_scan:
  1518.             action = 1
  1519.      
  1520.       vt.url_scan_and_report(options.value, "report", options.verbose, options.dump, options.csv, action)
  1521.    
  1522.   elif options.rescan:
  1523.      
  1524.     if options.date:
  1525.      
  1526.       if len(options.date) < 14:
  1527.          print '\n[!] Date fotmar is: 20120725170000 or 2012-07-25 17 00 00 or 2012-07-25 17:00:00\n'
  1528.          sys.exit()
  1529.          
  1530.       now = time.strftime("%Y:%m:%d %H:%M:%S")
  1531.       if now >= relativedelta(options.date):
  1532.             print '\n[!] Date must be greater then today\n'
  1533.             sys.exit()
  1534.            
  1535.     vt.rescan(options.value, options.date, options.period, options.repeat, options.notify_url, options.notify_changes_only, options.delete)
  1536.  
  1537.   elif options.domain:
  1538.     vt.getDomain(options.value[0], options.dump, options.trendmicro, options.detected_urls, options.undetected_downloaded_samples, options.alexa_domain_info,\
  1539.                  options.wot_domain_info, options.websense_threatseeker, options.bitdefender, options.webutation_domain, options.detected_communicated,\
  1540.                  options.undetected_communicated, options.pcaps)
  1541.  
  1542.   elif options.ip:
  1543.     vt.getIP(options.value[0], options.dump, options.detected_urls, options.detected_downloaded_samples, options.undetected_downloaded_samples,\
  1544.              options.detected_communicated, options.undetected_communicated)
  1545.  
  1546.   elif options.report_all_info:
  1547.       vt.getReport(options.value, '1', options.verbose, options.dump, )
  1548.                    
  1549.   elif options.search and not options.domain and not options.ip and not options.url_scan and not options.url_report:
  1550.     vt.getReport(options.value, '0', options.verbose, options.dump, options.csv)
  1551.  
  1552.   elif options.download:
  1553.       vt.download(options.value[0], 'file')
  1554.      
  1555.   elif options.pcap:
  1556.       vt.download(options.value[0], 'pcap')
  1557.  
  1558.   elif options.behaviour:
  1559.       vt.behaviour(options.value[0], options.dump, options.behavior_network, options.behavior_process, options.behavior_summary)
  1560.        
  1561.   elif options.distribution_files:
  1562.       vt.distribution(options.value, 'file', options.before, options.after, options.reports, options.limit, False, options.dump)
  1563.  
  1564.   elif options.distribution_urls:
  1565.       vt.distribution(options.value, 'url', options.before, options.after, options.reports, options.limit, options.allinfo, options.dump)
  1566.  
  1567.   elif options.massive_download:
  1568.       print """
  1569.            [!] If you want massive download files check this script:\n\t https://www.virustotal.com/es/documentation/scripts/vtfiles.py
  1570.            """
  1571.       sys.exit()
  1572.      
  1573.   elif options.add_comment and len(options.value) == 2:
  1574.     vt.comment(options.value[0], 'add', options.dump, options.value[1])
  1575.    
  1576.   elif options.get_comments:
  1577.     vt.comment(options.value[0], 'get', options.dump, options.date)
  1578.  
  1579.   elif options.clusters:
  1580.       vt.clusters(options.value, options.dump)
  1581.    
  1582.   #elif options.search_by_cluster_id:
  1583.   #    vt.clusters(options.value, options.dump, True)
  1584.    
  1585.   else:
  1586.    
  1587.     sys.exit(opt.print_help())
  1588.  
  1589. if __name__ == '__main__':
  1590.     '''
  1591.    You can especificate apikey as value or put it to config file
  1592.    '''
  1593.    
  1594.     apikey = '<--------------apikey-here-------->'  
  1595.     main(apikey)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement