Created
October 27, 2025 12:22
-
-
Save manchicken/b6a6c214814875bb856789bf9b9c9397 to your computer and use it in GitHub Desktop.
Uploading to VirusTotal
This file contains hidden or 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
| #!/usr/bin/env python3 | |
| import csv | |
| import requests | |
| import time | |
| import sys | |
| # Replace with your VirusTotal API key | |
| VT_API_KEY = "YOUR_API_KEY_HERE" | |
| def check_hash(file_hash): | |
| """Check a single hash against VirusTotal""" | |
| url = f"https://www.virustotal.com/api/v3/files/{file_hash}" | |
| headers = {"x-apikey": VT_API_KEY} | |
| try: | |
| response = requests.get(url, headers=headers) | |
| if response.status_code == 200: | |
| data = response.json() | |
| stats = data['data']['attributes']['last_analysis_stats'] | |
| return { | |
| 'malicious': stats.get('malicious', 0), | |
| 'suspicious': stats.get('suspicious', 0), | |
| 'undetected': stats.get('undetected', 0), | |
| 'harmless': stats.get('harmless', 0), | |
| 'found': True | |
| } | |
| elif response.status_code == 404: | |
| return {'found': False} | |
| else: | |
| print(f"[!] Error {response.status_code} for hash {file_hash}") | |
| return {'found': False, 'error': response.status_code} | |
| except Exception as e: | |
| print(f"[!] Exception: {e}") | |
| return {'found': False, 'error': str(e)} | |
| def main(input_csv, output_csv): | |
| """Read hashes from CSV and check them against VT""" | |
| results = [] | |
| with open(input_csv, 'r') as f: | |
| reader = csv.DictReader(f) | |
| rows = list(reader) | |
| print(f"[*] Checking {len(rows)} hashes...") | |
| for i, row in enumerate(rows, 1): | |
| file_hash = row['SHA256'] | |
| filename = row['FileName'] | |
| print(f"[{i}/{len(rows)}] Checking {filename}...") | |
| result = check_hash(file_hash) | |
| # Add original data plus VT results | |
| output_row = row.copy() | |
| if result['found']: | |
| output_row['VT_Malicious'] = result['malicious'] | |
| output_row['VT_Suspicious'] = result['suspicious'] | |
| output_row['VT_Undetected'] = result['undetected'] | |
| output_row['VT_Harmless'] = result['harmless'] | |
| output_row['VT_Found'] = 'Yes' | |
| if result['malicious'] > 0: | |
| print(f" [!!!] MALICIOUS: {result['malicious']} detections") | |
| else: | |
| output_row['VT_Found'] = 'No' | |
| print(f" [i] Not found in VT") | |
| results.append(output_row) | |
| # Rate limiting: 4 requests/minute for free tier | |
| time.sleep(15) # Wait 15 seconds between requests | |
| # Write results | |
| with open(output_csv, 'w', newline='') as f: | |
| fieldnames = list(results[0].keys()) | |
| writer = csv.DictWriter(f, fieldnames=fieldnames) | |
| writer.writeheader() | |
| writer.writerows(results) | |
| print(f"\n[+] Results saved to {output_csv}") | |
| # Summary | |
| malicious_count = sum(1 for r in results if int(r.get('VT_Malicious', 0)) > 0) | |
| print(f"[+] Found {malicious_count} malicious files") | |
| if __name__ == "__main__": | |
| if len(sys.argv) != 3: | |
| print("Usage: python3 vt_check_hashes.py input.csv output.csv") | |
| sys.exit(1) | |
| main(sys.argv[1], sys.argv[2]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment