[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M71F5BXMRH0T89MBNJKDX83P":3,"skill-same:01M71F5BXMRH0T89MBNJKDX83P":102},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":28,"publishedAt":49,"linkOnly":50,"markdownContent":51,"markdownBody":52,"frontMatter":53,"refName":75,"commitSha":76,"skillDirectory":77,"forksCount":14,"repositoryHtmlUrl":78,"repositoryHomepageUrl":6,"ownerHtmlUrl":79,"ownerBlogUrl":6,"ownerDescription":80,"updatedAt":81,"install":82,"resources":95},"01M71F5BXMRH0T89MBNJKDX83P","ioc-virustotal-detect",null,"Enrich malware file hashes using the VirusTotal API to retrieve detection rates, behavioral analysis, YARA matches, and contextual threat intelligence for incident triage and IOC validation.","DCx7C5\u002Fai-marketplace","DCx7C5","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F42419559?v=4","01M71C01G2AZV3NTNGWAWSHJPP","DC","01M71C01GQW6G50S2BYMS7PP3E",0,"MIT","https:\u002F\u002Fgithub.com\u002FDCx7C5\u002Fai-marketplace\u002Fblob\u002Fmain\u002Fskills\u002Fmalware\u002Fioc\u002Fvirustotal\u002Fdetect\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":26,"taxonomyTypeDesc":27},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],"ioc","VirusTotal","detect","ioc virustotal detect","sonnet","behavioral","threat","malware","intelligence","read","de","threat-intelligence","threat intelligence","api","analysis","Bash","cybersecurity","incident","cm","enrich","2026-11-10 10:12:30",false,"---\nname: ioc-virustotal-detect\ndescription: Enrich malware file hashes using the VirusTotal API to retrieve detection rates, behavioral analysis, YARA matches, and contextual threat intelligence for incident triage and IOC validation.\ndomain: cybersecurity\nsubdomain: threat-intelligence\ntags:\n- virustotal\n- malware-analysis\n- hash-enrichment\n- ioc\n- threat-intelligence\n- triage\n- api\n- detection\nnist_csf:\n- ID.RA-01\n- ID.RA-05\n- DE.CM-01\n- DE.AE-02\nmodel: sonnet\nmaxTurns: 20\ntools: [Read, Bash, Glob, Grep]\nmitre_attack:\n- T1027\n- T1046\n- T1059\ncapec: []\n---\n\n# Performing Malware Hash Enrichment with VirusTotal\n\n## Overview\n\nVirusTotal is the world's largest crowdsourced malware corpus, scanning files with 70+ antivirus engines and providing behavioral analysis, YARA rule matches, network indicators, and community intelligence. This skill covers using the VirusTotal API v3 to enrich file hashes (MD5, SHA-1, SHA-256) with detection verdicts, sandbox reports, related indicators, and contextual intelligence for SOC triage, incident response, and threat intelligence enrichment workflows.\n\n\n## When to Use\n\n- When conducting security assessments that involve performing malware hash enrichment with virustotal\n- When following incident response procedures for related security events\n- When performing scheduled security testing or auditing activities\n- When validating security controls through hands-on testing\n\n## Prerequisites\n\n- Python 3.9+ with `vt-py` (official VirusTotal Python client) or `requests`\n- VirusTotal API key (free tier: 4 requests\u002Fminute, 500\u002Fday; premium for higher limits)\n- Understanding of file hash types: MD5, SHA-1, SHA-256\n- Familiarity with AV detection naming conventions\n- STIX 2.1 knowledge for IOC representation\n\n## Key Concepts\n\n### VirusTotal API v3\n\nThe API provides RESTful endpoints for file reports (`\u002Ffiles\u002F{hash}`), URL scanning, domain reports, IP address intelligence, and advanced hunting with VirusTotal Intelligence (VTI). Each file report includes detection results from 70+ AV engines, behavioral analysis from sandboxes, YARA rule matches, sigma rule matches, file metadata (PE headers, imports, sections), network indicators (contacted IPs, domains, URLs), and community votes and comments.\n\n### Hash Enrichment Workflow\n\nThe typical enrichment flow is: receive hash from alert\u002FEDR -> query VT API -> parse detection ratio -> extract behavioral indicators -> correlate with existing intelligence -> make triage decision. The API returns a `last_analysis_stats` object with `malicious`, `suspicious`, `undetected`, and `harmless` counts.\n\n### Pivoting from Hashes\n\nVirusTotal enables pivoting from a single hash to related intelligence: similar files (ITW\u002Fin-the-wild samples), contacted domains and IPs (C2 infrastructure), dropped files, embedded URLs, YARA rule matches, and threat actor attribution through crowdsourced intelligence.\n\n## Workflow\n\n### Step 1: Query VirusTotal for Hash Report\n\n```python\nimport vt\nimport json\nimport hashlib\nfrom datetime import datetime\n\nclass VTEnricher:\n    def __init__(self, api_key):\n        self.client = vt.Client(api_key)\n\n    def enrich_hash(self, file_hash):\n        \"\"\"Enrich a file hash with VirusTotal intelligence.\"\"\"\n        try:\n            file_obj = self.client.get_object(f\"\u002Ffiles\u002F{file_hash}\")\n            stats = file_obj.last_analysis_stats\n            report = {\n                \"hash\": file_hash,\n                \"sha256\": file_obj.sha256,\n                \"sha1\": file_obj.sha1,\n                \"md5\": file_obj.md5,\n                \"file_type\": getattr(file_obj, \"type_description\", \"Unknown\"),\n                \"file_size\": getattr(file_obj, \"size\", 0),\n                \"first_submission\": str(getattr(file_obj, \"first_submission_date\", \"\")),\n                \"last_analysis_date\": str(getattr(file_obj, \"last_analysis_date\", \"\")),\n                \"detection_stats\": {\n                    \"malicious\": stats.get(\"malicious\", 0),\n                    \"suspicious\": stats.get(\"suspicious\", 0),\n                    \"undetected\": stats.get(\"undetected\", 0),\n                    \"harmless\": stats.get(\"harmless\", 0),\n                },\n                \"detection_ratio\": f\"{stats.get('malicious', 0)}\u002F{sum(stats.values())}\",\n                \"popular_threat_names\": getattr(file_obj, \"popular_threat_classification\", {}),\n                \"tags\": getattr(file_obj, \"tags\", []),\n                \"names\": getattr(file_obj, \"names\", []),\n            }\n            total_engines = sum(stats.values())\n            mal_count = stats.get(\"malicious\", 0)\n            report[\"threat_level\"] = (\n                \"critical\" if mal_count > total_engines * 0.7\n                else \"high\" if mal_count > total_engines * 0.4\n                else \"medium\" if mal_count > total_engines * 0.1\n                else \"low\" if mal_count > 0\n                else \"clean\"\n            )\n            print(f\"[+] {file_hash[:16]}... -> {report['detection_ratio']} \"\n                  f\"({report['threat_level'].upper()})\")\n            return report\n        except vt.error.APIError as e:\n            print(f\"[-] VT API error for {file_hash}: {e}\")\n            return None\n\n    def get_behavior_report(self, file_hash):\n        \"\"\"Get sandbox behavioral analysis for a file.\"\"\"\n        try:\n            behaviors = self.client.get_object(f\"\u002Ffiles\u002F{file_hash}\u002Fbehaviours\")\n            behavior_data = {\n                \"processes_created\": [],\n                \"files_written\": [],\n                \"registry_keys_set\": [],\n                \"dns_lookups\": [],\n                \"http_conversations\": [],\n                \"mutexes_created\": [],\n                \"commands_executed\": [],\n            }\n            for sandbox in getattr(behaviors, \"data\", []):\n                attrs = sandbox.get(\"attributes\", {})\n                behavior_data[\"processes_created\"].extend(\n                    attrs.get(\"processes_created\", []))\n                behavior_data[\"files_written\"].extend(\n                    [f.get(\"path\", \"\") for f in attrs.get(\"files_written\", [])])\n                behavior_data[\"registry_keys_set\"].extend(\n                    [r.get(\"key\", \"\") for r in attrs.get(\"registry_keys_set\", [])])\n                behavior_data[\"dns_lookups\"].extend(\n                    [d.get(\"hostname\", \"\") for d in attrs.get(\"dns_lookups\", [])])\n                behavior_data[\"commands_executed\"].extend(\n                    attrs.get(\"command_executions\", []))\n            return behavior_data\n        except Exception as e:\n            print(f\"[-] Behavior report error: {e}\")\n            return {}\n\n    def close(self):\n        self.client.close()\n\n# Usage\nenricher = VTEnricher(\"YOUR_VT_API_KEY\")\nreport = enricher.enrich_hash(\"275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f\")\nprint(json.dumps(report, indent=2, default=str))\nenricher.close()\n```\n\n### Step 2: Batch Hash Enrichment with Rate Limiting\n\n```python\nimport time\nimport csv\n\ndef batch_enrich(api_key, hash_file, output_file, rate_limit=4):\n    \"\"\"Enrich a list of hashes from a file with rate limiting.\"\"\"\n    enricher = VTEnricher(api_key)\n    results = []\n\n    with open(hash_file, \"r\") as f:\n        hashes = [line.strip() for line in f if line.strip()]\n\n    print(f\"[*] Enriching {len(hashes)} hashes (rate: {rate_limit}\u002Fmin)\")\n    for i, file_hash in enumerate(hashes):\n        report = enricher.enrich_hash(file_hash)\n        if report:\n            results.append(report)\n        if (i + 1) % rate_limit == 0:\n            print(f\"  [{i+1}\u002F{len(hashes)}] Rate limit pause (60s)...\")\n            time.sleep(60)\n\n    # Export to CSV\n    with open(output_file, \"w\", newline=\"\") as f:\n        if results:\n            writer = csv.DictWriter(f, fieldnames=results[0].keys())\n            writer.writeheader()\n            for r in results:\n                flat = {k: str(v) for k, v in r.items()}\n                writer.writerow(flat)\n\n    print(f\"[+] Enrichment complete: {len(results)}\u002F{len(hashes)} hashes\")\n    print(f\"[+] Results saved to {output_file}\")\n    enricher.close()\n    return results\n\nbatch_enrich(\"YOUR_API_KEY\", \"hashes.txt\", \"enrichment_results.csv\")\n```\n\n### Step 3: Extract Network Indicators for Pivoting\n\n```python\ndef extract_network_iocs(api_key, file_hash):\n    \"\"\"Extract network-based IOCs from VT for C2 identification.\"\"\"\n    client = vt.Client(api_key)\n    network_iocs = {\n        \"contacted_ips\": [],\n        \"contacted_domains\": [],\n        \"contacted_urls\": [],\n        \"embedded_urls\": [],\n    }\n\n    try:\n        # Get contacted IPs\n        it = client.iterator(f\"\u002Ffiles\u002F{file_hash}\u002Fcontacted_ips\")\n        for ip_obj in it:\n            network_iocs[\"contacted_ips\"].append({\n                \"ip\": ip_obj.id,\n                \"country\": getattr(ip_obj, \"country\", \"\"),\n                \"asn\": getattr(ip_obj, \"asn\", 0),\n                \"as_owner\": getattr(ip_obj, \"as_owner\", \"\"),\n            })\n\n        # Get contacted domains\n        it = client.iterator(f\"\u002Ffiles\u002F{file_hash}\u002Fcontacted_domains\")\n        for domain_obj in it:\n            network_iocs[\"contacted_domains\"].append({\n                \"domain\": domain_obj.id,\n                \"registrar\": getattr(domain_obj, \"registrar\", \"\"),\n                \"creation_date\": str(getattr(domain_obj, \"creation_date\", \"\")),\n            })\n\n        # Get contacted URLs\n        it = client.iterator(f\"\u002Ffiles\u002F{file_hash}\u002Fcontacted_urls\")\n        for url_obj in it:\n            network_iocs[\"contacted_urls\"].append({\n                \"url\": url_obj.url,\n                \"last_http_response_code\": getattr(url_obj, \"last_http_response_content_length\", 0),\n            })\n\n    except Exception as e:\n        print(f\"[-] Error extracting network IOCs: {e}\")\n    finally:\n        client.close()\n\n    print(f\"[+] Network IOCs: {len(network_iocs['contacted_ips'])} IPs, \"\n          f\"{len(network_iocs['contacted_domains'])} domains, \"\n          f\"{len(network_iocs['contacted_urls'])} URLs\")\n    return network_iocs\n```\n\n### Step 4: YARA Rule Matching and Threat Classification\n\n```python\ndef get_yara_matches(api_key, file_hash):\n    \"\"\"Retrieve YARA rule matches for threat classification.\"\"\"\n    client = vt.Client(api_key)\n    try:\n        file_obj = client.get_object(f\"\u002Ffiles\u002F{file_hash}\")\n        crowdsourced_yara = getattr(file_obj, \"crowdsourced_yara_results\", [])\n\n        matches = []\n        for rule in crowdsourced_yara:\n            matches.append({\n                \"rule_name\": rule.get(\"rule_name\", \"\"),\n                \"ruleset_name\": rule.get(\"ruleset_name\", \"\"),\n                \"author\": rule.get(\"author\", \"\"),\n                \"description\": rule.get(\"description\", \"\"),\n                \"source\": rule.get(\"source\", \"\"),\n            })\n\n        # Classify based on YARA matches\n        classifications = set()\n        for m in matches:\n            rule_lower = m[\"rule_name\"].lower()\n            if any(k in rule_lower for k in [\"apt\", \"nation\", \"state\"]):\n                classifications.add(\"apt\")\n            if any(k in rule_lower for k in [\"ransom\", \"crypto\"]):\n                classifications.add(\"ransomware\")\n            if any(k in rule_lower for k in [\"trojan\", \"rat\", \"backdoor\"]):\n                classifications.add(\"trojan\")\n            if any(k in rule_lower for k in [\"loader\", \"dropper\"]):\n                classifications.add(\"loader\")\n\n        print(f\"[+] YARA: {len(matches)} rules matched\")\n        print(f\"[+] Classifications: {classifications or {'unclassified'}}\")\n        return {\"matches\": matches, \"classifications\": list(classifications)}\n    finally:\n        client.close()\n```\n\n### Step 5: Generate Enrichment Report\n\n```python\ndef generate_enrichment_report(hash_report, behavior, network, yara_data):\n    \"\"\"Generate comprehensive enrichment report.\"\"\"\n    report = {\n        \"metadata\": {\n            \"generated\": datetime.now().isoformat(),\n            \"hash\": hash_report.get(\"sha256\", \"\"),\n        },\n        \"verdict\": {\n            \"threat_level\": hash_report.get(\"threat_level\", \"unknown\"),\n            \"detection_ratio\": hash_report.get(\"detection_ratio\", \"0\u002F0\"),\n            \"classifications\": yara_data.get(\"classifications\", []),\n            \"threat_names\": hash_report.get(\"popular_threat_names\", {}),\n        },\n        \"behavioral_indicators\": {\n            \"processes\": behavior.get(\"processes_created\", [])[:10],\n            \"dns_queries\": behavior.get(\"dns_lookups\", [])[:10],\n            \"commands\": behavior.get(\"commands_executed\", [])[:10],\n        },\n        \"network_indicators\": {\n            \"c2_candidates\": network.get(\"contacted_ips\", [])[:10],\n            \"domains\": network.get(\"contacted_domains\", [])[:10],\n        },\n        \"yara_matches\": yara_data.get(\"matches\", [])[:10],\n        \"recommendation\": (\n            \"BLOCK and investigate\" if hash_report.get(\"threat_level\") in (\"critical\", \"high\")\n            else \"Monitor and analyze\" if hash_report.get(\"threat_level\") == \"medium\"\n            else \"Low risk - continue monitoring\"\n        ),\n    }\n\n    with open(f\"enrichment_{hash_report.get('sha256', 'unknown')[:16]}.json\", \"w\") as f:\n        json.dump(report, f, indent=2, default=str)\n    return report\n```\n\n## Validation Criteria\n\n- VT API v3 queried successfully with proper authentication\n- File hash enriched with detection stats, behavioral data, and network indicators\n- Batch enrichment handles rate limiting correctly\n- Network IOCs extracted for C2 identification\n- YARA matches retrieved and used for classification\n- Enrichment report generated with actionable verdict\n\n## References\n\n- [VirusTotal API v3 Documentation](https:\u002F\u002Fdocs.virustotal.com\u002Freference\u002Foverview)\n- [vt-py Official Python Client](https:\u002F\u002Fgithub.com\u002FVirusTotal\u002Fvt-py)\n- [VirusTotal Intelligence](https:\u002F\u002Fwww.virustotal.com\u002Fgui\u002Fintelligence-overview)\n- [Torq: VT Hash Enrichment Workflow](https:\u002F\u002Fkb.torq.io\u002Fen\u002Farticles\u002F9350251-virustotal-file-hash-enrichment-with-cache-workflow-template)\n- [Dynatrace: Enrich Observables with VT](https:\u002F\u002Fwww.dynatrace.com\u002Fnews\u002Fblog\u002Fenrich-observables-with-virustotal-threat-intelligence\u002F)\n- [Penligent: VT in Incident Response](https:\u002F\u002Fwww.penligent.ai\u002Fhackinglabs\u002Fvirustotal-in-incident-response-how-to-identify-malware-fast-and-pivot-without-leaking-data\u002F)\n","# Performing Malware Hash Enrichment with VirusTotal\n\n## Overview\n\nVirusTotal is the world's largest crowdsourced malware corpus, scanning files with 70+ antivirus engines and providing behavioral analysis, YARA rule matches, network indicators, and community intelligence. This skill covers using the VirusTotal API v3 to enrich file hashes (MD5, SHA-1, SHA-256) with detection verdicts, sandbox reports, related indicators, and contextual intelligence for SOC triage, incident response, and threat intelligence enrichment workflows.\n\n\n## When to Use\n\n- When conducting security assessments that involve performing malware hash enrichment with virustotal\n- When following incident response procedures for related security events\n- When performing scheduled security testing or auditing activities\n- When validating security controls through hands-on testing\n\n## Prerequisites\n\n- Python 3.9+ with `vt-py` (official VirusTotal Python client) or `requests`\n- VirusTotal API key (free tier: 4 requests\u002Fminute, 500\u002Fday; premium for higher limits)\n- Understanding of file hash types: MD5, SHA-1, SHA-256\n- Familiarity with AV detection naming conventions\n- STIX 2.1 knowledge for IOC representation\n\n## Key Concepts\n\n### VirusTotal API v3\n\nThe API provides RESTful endpoints for file reports (`\u002Ffiles\u002F{hash}`), URL scanning, domain reports, IP address intelligence, and advanced hunting with VirusTotal Intelligence (VTI). Each file report includes detection results from 70+ AV engines, behavioral analysis from sandboxes, YARA rule matches, sigma rule matches, file metadata (PE headers, imports, sections), network indicators (contacted IPs, domains, URLs), and community votes and comments.\n\n### Hash Enrichment Workflow\n\nThe typical enrichment flow is: receive hash from alert\u002FEDR -> query VT API -> parse detection ratio -> extract behavioral indicators -> correlate with existing intelligence -> make triage decision. The API returns a `last_analysis_stats` object with `malicious`, `suspicious`, `undetected`, and `harmless` counts.\n\n### Pivoting from Hashes\n\nVirusTotal enables pivoting from a single hash to related intelligence: similar files (ITW\u002Fin-the-wild samples), contacted domains and IPs (C2 infrastructure), dropped files, embedded URLs, YARA rule matches, and threat actor attribution through crowdsourced intelligence.\n\n## Workflow\n\n### Step 1: Query VirusTotal for Hash Report\n\n```python\nimport vt\nimport json\nimport hashlib\nfrom datetime import datetime\n\nclass VTEnricher:\n    def __init__(self, api_key):\n        self.client = vt.Client(api_key)\n\n    def enrich_hash(self, file_hash):\n        \"\"\"Enrich a file hash with VirusTotal intelligence.\"\"\"\n        try:\n            file_obj = self.client.get_object(f\"\u002Ffiles\u002F{file_hash}\")\n            stats = file_obj.last_analysis_stats\n            report = {\n                \"hash\": file_hash,\n                \"sha256\": file_obj.sha256,\n                \"sha1\": file_obj.sha1,\n                \"md5\": file_obj.md5,\n                \"file_type\": getattr(file_obj, \"type_description\", \"Unknown\"),\n                \"file_size\": getattr(file_obj, \"size\", 0),\n                \"first_submission\": str(getattr(file_obj, \"first_submission_date\", \"\")),\n                \"last_analysis_date\": str(getattr(file_obj, \"last_analysis_date\", \"\")),\n                \"detection_stats\": {\n                    \"malicious\": stats.get(\"malicious\", 0),\n                    \"suspicious\": stats.get(\"suspicious\", 0),\n                    \"undetected\": stats.get(\"undetected\", 0),\n                    \"harmless\": stats.get(\"harmless\", 0),\n                },\n                \"detection_ratio\": f\"{stats.get('malicious', 0)}\u002F{sum(stats.values())}\",\n                \"popular_threat_names\": getattr(file_obj, \"popular_threat_classification\", {}),\n                \"tags\": getattr(file_obj, \"tags\", []),\n                \"names\": getattr(file_obj, \"names\", []),\n            }\n            total_engines = sum(stats.values())\n            mal_count = stats.get(\"malicious\", 0)\n            report[\"threat_level\"] = (\n                \"critical\" if mal_count > total_engines * 0.7\n                else \"high\" if mal_count > total_engines * 0.4\n                else \"medium\" if mal_count > total_engines * 0.1\n                else \"low\" if mal_count > 0\n                else \"clean\"\n            )\n            print(f\"[+] {file_hash[:16]}... -> {report['detection_ratio']} \"\n                  f\"({report['threat_level'].upper()})\")\n            return report\n        except vt.error.APIError as e:\n            print(f\"[-] VT API error for {file_hash}: {e}\")\n            return None\n\n    def get_behavior_report(self, file_hash):\n        \"\"\"Get sandbox behavioral analysis for a file.\"\"\"\n        try:\n            behaviors = self.client.get_object(f\"\u002Ffiles\u002F{file_hash}\u002Fbehaviours\")\n            behavior_data = {\n                \"processes_created\": [],\n                \"files_written\": [],\n                \"registry_keys_set\": [],\n                \"dns_lookups\": [],\n                \"http_conversations\": [],\n                \"mutexes_created\": [],\n                \"commands_executed\": [],\n            }\n            for sandbox in getattr(behaviors, \"data\", []):\n                attrs = sandbox.get(\"attributes\", {})\n                behavior_data[\"processes_created\"].extend(\n                    attrs.get(\"processes_created\", []))\n                behavior_data[\"files_written\"].extend(\n                    [f.get(\"path\", \"\") for f in attrs.get(\"files_written\", [])])\n                behavior_data[\"registry_keys_set\"].extend(\n                    [r.get(\"key\", \"\") for r in attrs.get(\"registry_keys_set\", [])])\n                behavior_data[\"dns_lookups\"].extend(\n                    [d.get(\"hostname\", \"\") for d in attrs.get(\"dns_lookups\", [])])\n                behavior_data[\"commands_executed\"].extend(\n                    attrs.get(\"command_executions\", []))\n            return behavior_data\n        except Exception as e:\n            print(f\"[-] Behavior report error: {e}\")\n            return {}\n\n    def close(self):\n        self.client.close()\n\n# Usage\nenricher = VTEnricher(\"YOUR_VT_API_KEY\")\nreport = enricher.enrich_hash(\"275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f\")\nprint(json.dumps(report, indent=2, default=str))\nenricher.close()\n```\n\n### Step 2: Batch Hash Enrichment with Rate Limiting\n\n```python\nimport time\nimport csv\n\ndef batch_enrich(api_key, hash_file, output_file, rate_limit=4):\n    \"\"\"Enrich a list of hashes from a file with rate limiting.\"\"\"\n    enricher = VTEnricher(api_key)\n    results = []\n\n    with open(hash_file, \"r\") as f:\n        hashes = [line.strip() for line in f if line.strip()]\n\n    print(f\"[*] Enriching {len(hashes)} hashes (rate: {rate_limit}\u002Fmin)\")\n    for i, file_hash in enumerate(hashes):\n        report = enricher.enrich_hash(file_hash)\n        if report:\n            results.append(report)\n        if (i + 1) % rate_limit == 0:\n            print(f\"  [{i+1}\u002F{len(hashes)}] Rate limit pause (60s)...\")\n            time.sleep(60)\n\n    # Export to CSV\n    with open(output_file, \"w\", newline=\"\") as f:\n        if results:\n            writer = csv.DictWriter(f, fieldnames=results[0].keys())\n            writer.writeheader()\n            for r in results:\n                flat = {k: str(v) for k, v in r.items()}\n                writer.writerow(flat)\n\n    print(f\"[+] Enrichment complete: {len(results)}\u002F{len(hashes)} hashes\")\n    print(f\"[+] Results saved to {output_file}\")\n    enricher.close()\n    return results\n\nbatch_enrich(\"YOUR_API_KEY\", \"hashes.txt\", \"enrichment_results.csv\")\n```\n\n### Step 3: Extract Network Indicators for Pivoting\n\n```python\ndef extract_network_iocs(api_key, file_hash):\n    \"\"\"Extract network-based IOCs from VT for C2 identification.\"\"\"\n    client = vt.Client(api_key)\n    network_iocs = {\n        \"contacted_ips\": [],\n        \"contacted_domains\": [],\n        \"contacted_urls\": [],\n        \"embedded_urls\": [],\n    }\n\n    try:\n        # Get contacted IPs\n        it = client.iterator(f\"\u002Ffiles\u002F{file_hash}\u002Fcontacted_ips\")\n        for ip_obj in it:\n            network_iocs[\"contacted_ips\"].append({\n                \"ip\": ip_obj.id,\n                \"country\": getattr(ip_obj, \"country\", \"\"),\n                \"asn\": getattr(ip_obj, \"asn\", 0),\n                \"as_owner\": getattr(ip_obj, \"as_owner\", \"\"),\n            })\n\n        # Get contacted domains\n        it = client.iterator(f\"\u002Ffiles\u002F{file_hash}\u002Fcontacted_domains\")\n        for domain_obj in it:\n            network_iocs[\"contacted_domains\"].append({\n                \"domain\": domain_obj.id,\n                \"registrar\": getattr(domain_obj, \"registrar\", \"\"),\n                \"creation_date\": str(getattr(domain_obj, \"creation_date\", \"\")),\n            })\n\n        # Get contacted URLs\n        it = client.iterator(f\"\u002Ffiles\u002F{file_hash}\u002Fcontacted_urls\")\n        for url_obj in it:\n            network_iocs[\"contacted_urls\"].append({\n                \"url\": url_obj.url,\n                \"last_http_response_code\": getattr(url_obj, \"last_http_response_content_length\", 0),\n            })\n\n    except Exception as e:\n        print(f\"[-] Error extracting network IOCs: {e}\")\n    finally:\n        client.close()\n\n    print(f\"[+] Network IOCs: {len(network_iocs['contacted_ips'])} IPs, \"\n          f\"{len(network_iocs['contacted_domains'])} domains, \"\n          f\"{len(network_iocs['contacted_urls'])} URLs\")\n    return network_iocs\n```\n\n### Step 4: YARA Rule Matching and Threat Classification\n\n```python\ndef get_yara_matches(api_key, file_hash):\n    \"\"\"Retrieve YARA rule matches for threat classification.\"\"\"\n    client = vt.Client(api_key)\n    try:\n        file_obj = client.get_object(f\"\u002Ffiles\u002F{file_hash}\")\n        crowdsourced_yara = getattr(file_obj, \"crowdsourced_yara_results\", [])\n\n        matches = []\n        for rule in crowdsourced_yara:\n            matches.append({\n                \"rule_name\": rule.get(\"rule_name\", \"\"),\n                \"ruleset_name\": rule.get(\"ruleset_name\", \"\"),\n                \"author\": rule.get(\"author\", \"\"),\n                \"description\": rule.get(\"description\", \"\"),\n                \"source\": rule.get(\"source\", \"\"),\n            })\n\n        # Classify based on YARA matches\n        classifications = set()\n        for m in matches:\n            rule_lower = m[\"rule_name\"].lower()\n            if any(k in rule_lower for k in [\"apt\", \"nation\", \"state\"]):\n                classifications.add(\"apt\")\n            if any(k in rule_lower for k in [\"ransom\", \"crypto\"]):\n                classifications.add(\"ransomware\")\n            if any(k in rule_lower for k in [\"trojan\", \"rat\", \"backdoor\"]):\n                classifications.add(\"trojan\")\n            if any(k in rule_lower for k in [\"loader\", \"dropper\"]):\n                classifications.add(\"loader\")\n\n        print(f\"[+] YARA: {len(matches)} rules matched\")\n        print(f\"[+] Classifications: {classifications or {'unclassified'}}\")\n        return {\"matches\": matches, \"classifications\": list(classifications)}\n    finally:\n        client.close()\n```\n\n### Step 5: Generate Enrichment Report\n\n```python\ndef generate_enrichment_report(hash_report, behavior, network, yara_data):\n    \"\"\"Generate comprehensive enrichment report.\"\"\"\n    report = {\n        \"metadata\": {\n            \"generated\": datetime.now().isoformat(),\n            \"hash\": hash_report.get(\"sha256\", \"\"),\n        },\n        \"verdict\": {\n            \"threat_level\": hash_report.get(\"threat_level\", \"unknown\"),\n            \"detection_ratio\": hash_report.get(\"detection_ratio\", \"0\u002F0\"),\n            \"classifications\": yara_data.get(\"classifications\", []),\n            \"threat_names\": hash_report.get(\"popular_threat_names\", {}),\n        },\n        \"behavioral_indicators\": {\n            \"processes\": behavior.get(\"processes_created\", [])[:10],\n            \"dns_queries\": behavior.get(\"dns_lookups\", [])[:10],\n            \"commands\": behavior.get(\"commands_executed\", [])[:10],\n        },\n        \"network_indicators\": {\n            \"c2_candidates\": network.get(\"contacted_ips\", [])[:10],\n            \"domains\": network.get(\"contacted_domains\", [])[:10],\n        },\n        \"yara_matches\": yara_data.get(\"matches\", [])[:10],\n        \"recommendation\": (\n            \"BLOCK and investigate\" if hash_report.get(\"threat_level\") in (\"critical\", \"high\")\n            else \"Monitor and analyze\" if hash_report.get(\"threat_level\") == \"medium\"\n            else \"Low risk - continue monitoring\"\n        ),\n    }\n\n    with open(f\"enrichment_{hash_report.get('sha256', 'unknown')[:16]}.json\", \"w\") as f:\n        json.dump(report, f, indent=2, default=str)\n    return report\n```\n\n## Validation Criteria\n\n- VT API v3 queried successfully with proper authentication\n- File hash enriched with detection stats, behavioral data, and network indicators\n- Batch enrichment handles rate limiting correctly\n- Network IOCs extracted for C2 identification\n- YARA matches retrieved and used for classification\n- Enrichment report generated with actionable verdict\n\n## References\n\n- [VirusTotal API v3 Documentation](https:\u002F\u002Fdocs.virustotal.com\u002Freference\u002Foverview)\n- [vt-py Official Python Client](https:\u002F\u002Fgithub.com\u002FVirusTotal\u002Fvt-py)\n- [VirusTotal Intelligence](https:\u002F\u002Fwww.virustotal.com\u002Fgui\u002Fintelligence-overview)\n- [Torq: VT Hash Enrichment Workflow](https:\u002F\u002Fkb.torq.io\u002Fen\u002Farticles\u002F9350251-virustotal-file-hash-enrichment-with-cache-workflow-template)\n- [Dynatrace: Enrich Observables with VT](https:\u002F\u002Fwww.dynatrace.com\u002Fnews\u002Fblog\u002Fenrich-observables-with-virustotal-threat-intelligence\u002F)\n- [Penligent: VT in Incident Response](https:\u002F\u002Fwww.penligent.ai\u002Fhackinglabs\u002Fvirustotal-in-incident-response-how-to-identify-malware-fast-and-pivot-without-leaking-data\u002F)\n",{"name":5,"tags":54,"capec":60,"model":33,"tools":61,"domain":45,"maxTurns":65,"nist_csf":66,"subdomain":40,"description":7,"mitre_attack":71},[55,56,57,29,40,58,42,59],"virustotal","malware-analysis","hash-enrichment","triage","detection",[],[62,44,63,64],"Read","Glob","Grep",20,[67,68,69,70],"ID.RA-01","ID.RA-05","DE.CM-01","DE.AE-02",[72,73,74],"T1027","T1046","T1059","main","a91f1293287ffa9f4f1b8f486cd6e835a1568c84","skills\u002Fmalware\u002Fioc\u002Fvirustotal\u002Fdetect","https:\u002F\u002Fgithub.com\u002FDCx7C5\u002Fai-marketplace","https:\u002F\u002Fgithub.com\u002FDCx7C5","#Python","2026-09-01 11:21:00",{"source":8,"skillName":5,"commands":83,"prompt":93,"zipAvailable":94},[84,87,90],{"tool":85,"command":86},"npx","npx skills add DCx7C5\u002Fai-marketplace --skill ioc-virustotal-detect",{"tool":88,"command":89},"bunx","bunx skills add DCx7C5\u002Fai-marketplace --skill ioc-virustotal-detect",{"tool":91,"command":92},"pnpm","pnpm dlx skills add DCx7C5\u002Fai-marketplace --skill ioc-virustotal-detect","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FDCx7C5\u002Fai-marketplace\u002Fblob\u002Fmain\u002Fskills\u002Fmalware\u002Fioc\u002Fvirustotal\u002Fdetect\u002FSKILL.md",true,[96],{"path":97,"resourceType":98,"resourceTypeDesc":99,"sizeBytes":100,"sourceHtmlUrl":101},"index.json","REFERENCE","参考文档",668,"https:\u002F\u002Fgithub.com\u002FDCx7C5\u002Fai-marketplace\u002Fblob\u002Fmain\u002Fskills\u002Fmalware\u002Fioc\u002Fvirustotal\u002Fdetect\u002Findex.json",[103,125,145,166,188,203],{"skillNo":104,"name":105,"nameZh":6,"description":106,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":107,"categories":108,"keywords":109,"publishedAt":49},"01M71HAPZ01KQ30RKTB0FFSQ05","services-wmi-persistence-detect","Detect WMI event subscription persistence by enumerating ActiveScriptEventConsumer, CommandLineEventConsumer, and permanent subscriptions in the WMI repository.","https:\u002F\u002Fgithub.com\u002FDCx7C5\u002Fai-marketplace\u002Fblob\u002Fmain\u002Fskills\u002Fwindows\u002Fservices\u002Fwmi\u002Fpersistence\u002Fdetect\u002FSKILL.md",[],[110,31,111,112,113,39,47,114,115,116,117,118,119,120,121,122,123,45,124],"services","services wmi persistence detect","wmi","persistence","process","activescript","event","subscriptions","commandline-consumer","repository","subscription","event-subscription","t1546.003","forensics","process-forensics",{"skillNo":126,"name":127,"nameZh":6,"description":128,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":129,"categories":130,"keywords":131,"publishedAt":49},"01M71HAK6JTTTS229T17WJMMCG","services-wmi-exec-exploit","Perform lateral movement across Windows networks using WMI-based remote execution techniques including Impacket wmiexec.py, CrackMapExec, and native WMI commands for stealthy post-exploitation during red team engagements.","https:\u002F\u002Fgithub.com\u002FDCx7C5\u002Fai-marketplace\u002Fblob\u002Fmain\u002Fskills\u002Fwindows\u002Fservices\u002Fwmi\u002Fexec\u002Fexploit\u002FSKILL.md",[],[132,110,133,112,134,135,136,45,44,43,137,138,139,140,39,141,142,38,143,144],"exploit","services wmi exec exploit","exec","remote","traffic","team","across","crackmapexec","native","command","lateral movement","lateral-movement","Impacket",{"skillNo":146,"name":147,"nameZh":6,"description":148,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":149,"categories":150,"keywords":151,"publishedAt":49},"01M71HAG6MHKNQV8KDZKMT4886","registry-artifact-extract","Extract and analyze Windows Registry hives to uncover user activity, installed software, autostart entries, and evidence of system compromise.","https:\u002F\u002Fgithub.com\u002FDCx7C5\u002Fai-marketplace\u002Fblob\u002Fmain\u002Fskills\u002Fwindows\u002Fregistry\u002Fartifact\u002Fextract\u002FSKILL.md",[],[152,153,154,155,156,157,45,44,158,43,159,160,39,38,161,162,163,164,165,33],"artifact","registry","registry artifact extract","extract","evidence-collection","artifact-analysis","collection","analyze","uncover","software","activity","digital-forensics","windows-registry","regripper",{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":170,"categories":171,"keywords":172,"publishedAt":49},"01M71HACR4A8XTWTTSXK4124AA","processes-token-impersonate-detect","Detect Windows token impersonation and privilege abuse including SeImpersonatePrivilege exploitation via Potato attacks and token stealing techniques.","https:\u002F\u002Fgithub.com\u002FDCx7C5\u002Fai-marketplace\u002Fblob\u002Fmain\u002Fskills\u002Fwindows\u002Fprocesses\u002Ftoken\u002Fimpersonate\u002Fdetect\u002FSKILL.md",[],[31,173,174,175,176,177,178,47,179,45,124,180,181,182,183,184,185,186,187,39],"processes token impersonate detect","token","processes","attacks","windows","escalation","techniques","privilege-escalation","seimpersonate","token-impersonation","printspoofer","exploitation","potato","impersonation","via",{"skillNo":189,"name":190,"nameZh":6,"description":191,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":192,"categories":193,"keywords":194,"publishedAt":49},"01M71HAABSB4Z6QFSXEG00R4RK","processes-thread-injection-detect","Detect Windows thread injection techniques including CreateRemoteThread, QueueUserAPC, NtCreateThreadEx, and thread hijacking via process memory analysis.","https:\u002F\u002Fgithub.com\u002FDCx7C5\u002Fai-marketplace\u002Fblob\u002Fmain\u002Fskills\u002Fwindows\u002Fprocesses\u002Fthread\u002Finjection\u002Fdetect\u002FSKILL.md",[],[195,196,31,197,175,177,198,47,199,179,45,124,43,42,200,201,202,187,39,114],"thread","processes thread injection detect","injection","memory","process-injection","apc-injection","thread-injection","nt-api",{"skillNo":204,"name":205,"nameZh":6,"description":206,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":207,"categories":208,"keywords":209,"publishedAt":49},"01M71HA7H311V5G14WMX58HQSS","processes-hollow-technique-detect","Detect process hollowing (RunPE) by identifying processes with mismatched image paths between PEB and VAD tree, or unmapped PE headers in memory.","https:\u002F\u002Fgithub.com\u002FDCx7C5\u002Fai-marketplace\u002Fblob\u002Fmain\u002Fskills\u002Fwindows\u002Fprocesses\u002Fhollow\u002Ftechnique\u002Fdetect\u002FSKILL.md",[],[210,31,175,211,198,47,212,213,45,124,214,215,216,217,218,219,39,114,220,221],"processes hollow technique detect","tree","memory-forensics","process-hollow","peb","runpe","image","pe-header","in memory","with","mismatched","headers"]