[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6ADXC5ZH5FRGY6ARAYR0SH4":3,"skill-same:01M6ADXC5ZH5FRGY6ARAYR0SH4":100},{"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":23,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":59,"commitSha":60,"skillDirectory":61,"forksCount":62,"repositoryHtmlUrl":63,"repositoryHomepageUrl":64,"ownerHtmlUrl":65,"ownerBlogUrl":66,"ownerDescription":67,"updatedAt":68,"install":69,"resources":82},"01M6ADXC5ZH5FRGY6ARAYR0SH4","building-adversary-infrastructure-tracking-system",null,"Build an automated adversary infrastructure tracking system in Python (dnspython, python-whois, shodan, networkx) that pivots across passive DNS, certificate transparency logs, WHOIS records, and IP enrichment to map threat-actor C2 networks and flag newly registered domains matching known patterns. Use when pivoting from known indicators to discover related C2 infrastructure or maintaining a continuously updated map of a threat actor's network.","mukul975\u002FAnthropic-Cybersecurity-Skills","mukul975","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F42860185?v=4","01M6ADEQR8T5M4EEG6C67BQCWF","Mahipal","01M6ADJPMYWG1E5GM1FWBE3128",36078,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fbuilding-adversary-infrastructure-tracking-system\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"infrastructure","building adversary infrastructure tracking system","python","cybersecurity","logs","threat-actor","threat-intelligence","c2","dns","network","enrichment","infrastructure-tracking","passive-dns","whois","pivoting","domain-analysis","2026-11-10 10:12:30",false,"---\nname: building-adversary-infrastructure-tracking-system\ndescription: Build an automated adversary infrastructure tracking system in Python (dnspython, python-whois, shodan, networkx) that pivots across passive DNS, certificate transparency logs, WHOIS records, and IP enrichment to map threat-actor C2 networks and flag newly registered domains matching known patterns. Use when pivoting from known indicators to discover related C2 infrastructure or maintaining a continuously updated map of a threat actor's network.\ndomain: cybersecurity\nsubdomain: threat-intelligence\ntags:\n- infrastructure-tracking\n- passive-dns\n- c2\n- whois\n- threat-actor\n- pivoting\n- threat-intelligence\n- domain-analysis\nversion: '1.0'\nauthor: mahipal\nlicense: Apache-2.0\nnist_csf:\n- ID.RA-01\n- ID.RA-05\n- DE.CM-01\n- DE.AE-02\nmitre_attack:\n- T1583.001\n- T1583.004\n- T1596.001\n- T1590.002\n- T1071.001\n---\n# Building Adversary Infrastructure Tracking System\n\n## Overview\n\nAdversary infrastructure tracking uses passive DNS records, certificate transparency logs, WHOIS registration data, and IP enrichment to discover, map, and monitor threat actor command-and-control (C2) networks. Attackers frequently reuse hosting providers, registrars, SSL certificates, and naming patterns across campaigns, enabling analysts to pivot from known indicators to discover new infrastructure. This skill covers building an automated tracking system that identifies infrastructure relationships, detects newly registered domains matching adversary patterns, and maintains a continuously updated map of threat actor networks.\n\n\n## When to Use\n\n- When deploying or configuring building adversary infrastructure tracking system capabilities in your environment\n- When establishing security controls aligned to compliance requirements\n- When building or improving security architecture for this domain\n- When conducting security assessments that require this implementation\n\n## Prerequisites\n\n- Python 3.9+ with `requests`, `dnspython`, `python-whois`, `shodan`, `networkx` libraries\n- API keys: SecurityTrails, PassiveTotal\u002FRiskIQ, Shodan, VirusTotal\n- Access to passive DNS data sources\n- Understanding of DNS infrastructure, hosting, and domain registration\n- Graph database (Neo4j) or NetworkX for relationship visualization\n\n## Key Concepts\n\n### Passive DNS\n\nPassive DNS captures historical DNS resolution data, recording which domains resolved to which IPs and when. Unlike active DNS queries, passive DNS preserves historical relationships even after records change, enabling analysts to track infrastructure changes, identify shared hosting patterns, and discover related domains that resolved to the same IP addresses over time.\n\n### Infrastructure Pivoting\n\nPivoting identifies related infrastructure by following connections: IP pivot (find all domains on an IP), domain pivot (find all IPs a domain resolved to), WHOIS pivot (find domains with same registrant), certificate pivot (find hosts sharing SSL certificates), and NS\u002FMX pivot (find domains using same name servers or mail servers).\n\n### Adversary Infrastructure Patterns\n\nThreat actors exhibit patterns: preferred registrars (Namecheap, REG.RU, Tucows), preferred hosting (bulletproof hosting providers, cloud services), domain generation algorithms (DGA), consistent naming patterns, and certificate reuse across campaigns.\n\n## Workflow\n\n### Step 1: Passive DNS Infrastructure Discovery\n\n```python\nimport requests\nimport json\nfrom collections import defaultdict\nfrom datetime import datetime\n\nclass InfrastructureTracker:\n    def __init__(self, securitytrails_key=None, vt_key=None, shodan_key=None):\n        self.st_key = securitytrails_key\n        self.vt_key = vt_key\n        self.shodan_key = shodan_key\n        self.infrastructure_graph = defaultdict(lambda: {\"nodes\": set(), \"edges\": []})\n\n    def passive_dns_lookup(self, domain):\n        \"\"\"Query passive DNS for domain resolution history.\"\"\"\n        headers = {\"apikey\": self.st_key}\n        url = f\"https:\u002F\u002Fapi.securitytrails.com\u002Fv1\u002Fhistory\u002F{domain}\u002Fdns\u002Fa\"\n        resp = requests.get(url, headers=headers, timeout=30)\n        if resp.status_code == 200:\n            records = resp.json().get(\"records\", [])\n            history = []\n            for record in records:\n                for value in record.get(\"values\", []):\n                    history.append({\n                        \"domain\": domain,\n                        \"ip\": value.get(\"ip\", \"\"),\n                        \"first_seen\": record.get(\"first_seen\", \"\"),\n                        \"last_seen\": record.get(\"last_seen\", \"\"),\n                        \"type\": record.get(\"type\", \"a\"),\n                    })\n            print(f\"[+] Passive DNS for {domain}: {len(history)} records\")\n            return history\n        return []\n\n    def reverse_ip_lookup(self, ip_address):\n        \"\"\"Find all domains hosted on an IP address.\"\"\"\n        headers = {\"apikey\": self.st_key}\n        url = f\"https:\u002F\u002Fapi.securitytrails.com\u002Fv1\u002Fips\u002Fnearby\u002F{ip_address}\"\n        resp = requests.get(url, headers=headers, timeout=30)\n        if resp.status_code == 200:\n            blocks = resp.json().get(\"blocks\", [])\n            domains = []\n            for block in blocks:\n                for site in block.get(\"sites\", []):\n                    domains.append(site)\n            print(f\"[+] Reverse IP for {ip_address}: {len(domains)} domains\")\n            return domains\n        return []\n\n    def whois_lookup(self, domain):\n        \"\"\"Get WHOIS registration data for pivoting.\"\"\"\n        headers = {\"apikey\": self.st_key}\n        url = f\"https:\u002F\u002Fapi.securitytrails.com\u002Fv1\u002Fdomain\u002F{domain}\u002Fwhois\"\n        resp = requests.get(url, headers=headers, timeout=30)\n        if resp.status_code == 200:\n            data = resp.json()\n            whois_data = {\n                \"domain\": domain,\n                \"registrar\": data.get(\"registrar\", \"\"),\n                \"registrant_org\": data.get(\"registrant_org\", \"\"),\n                \"registrant_email\": data.get(\"registrant_email\", \"\"),\n                \"name_servers\": data.get(\"nameServers\", []),\n                \"created_date\": data.get(\"createdDate\", \"\"),\n                \"updated_date\": data.get(\"updatedDate\", \"\"),\n                \"expires_date\": data.get(\"expiresDate\", \"\"),\n            }\n            return whois_data\n        return {}\n\n    def pivot_from_seed(self, seed_indicator, indicator_type=\"domain\", depth=2):\n        \"\"\"Recursively pivot from a seed indicator to discover infrastructure.\"\"\"\n        discovered = {\"domains\": set(), \"ips\": set(), \"relationships\": []}\n\n        if indicator_type == \"domain\":\n            discovered[\"domains\"].add(seed_indicator)\n            # Get IPs for domain\n            pdns = self.passive_dns_lookup(seed_indicator)\n            for record in pdns:\n                ip = record[\"ip\"]\n                discovered[\"ips\"].add(ip)\n                discovered[\"relationships\"].append({\n                    \"source\": seed_indicator, \"target\": ip,\n                    \"type\": \"resolves_to\",\n                    \"first_seen\": record[\"first_seen\"],\n                    \"last_seen\": record[\"last_seen\"],\n                })\n\n                if depth > 1:\n                    # Reverse lookup on discovered IPs\n                    reverse_domains = self.reverse_ip_lookup(ip)\n                    for rd in reverse_domains[:20]:\n                        discovered[\"domains\"].add(rd)\n                        discovered[\"relationships\"].append({\n                            \"source\": rd, \"target\": ip,\n                            \"type\": \"hosted_on\",\n                        })\n\n        elif indicator_type == \"ip\":\n            discovered[\"ips\"].add(seed_indicator)\n            domains = self.reverse_ip_lookup(seed_indicator)\n            for domain in domains[:20]:\n                discovered[\"domains\"].add(domain)\n                discovered[\"relationships\"].append({\n                    \"source\": domain, \"target\": seed_indicator,\n                    \"type\": \"hosted_on\",\n                })\n\n        print(f\"[+] Pivot from {seed_indicator}: \"\n              f\"{len(discovered['domains'])} domains, \"\n              f\"{len(discovered['ips'])} IPs, \"\n              f\"{len(discovered['relationships'])} relationships\")\n        return discovered\n\ntracker = InfrastructureTracker(\n    securitytrails_key=\"YOUR_ST_KEY\",\n    vt_key=\"YOUR_VT_KEY\",\n)\n```\n\n### Step 2: Build Infrastructure Graph\n\n```python\nimport networkx as nx\n\nclass InfrastructureGraph:\n    def __init__(self):\n        self.graph = nx.Graph()\n\n    def add_discovery(self, discovery_data):\n        \"\"\"Add discovered infrastructure to graph.\"\"\"\n        for domain in discovery_data[\"domains\"]:\n            self.graph.add_node(domain, type=\"domain\")\n        for ip in discovery_data[\"ips\"]:\n            self.graph.add_node(ip, type=\"ip\")\n        for rel in discovery_data[\"relationships\"]:\n            self.graph.add_edge(\n                rel[\"source\"], rel[\"target\"],\n                relationship=rel[\"type\"],\n                first_seen=rel.get(\"first_seen\", \"\"),\n                last_seen=rel.get(\"last_seen\", \"\"),\n            )\n\n    def find_clusters(self):\n        \"\"\"Identify infrastructure clusters.\"\"\"\n        components = list(nx.connected_components(self.graph))\n        clusters = []\n        for component in components:\n            domains = [n for n in component if self.graph.nodes[n].get(\"type\") == \"domain\"]\n            ips = [n for n in component if self.graph.nodes[n].get(\"type\") == \"ip\"]\n            clusters.append({\n                \"size\": len(component),\n                \"domains\": sorted(domains),\n                \"ips\": sorted(ips),\n                \"domain_count\": len(domains),\n                \"ip_count\": len(ips),\n            })\n        clusters.sort(key=lambda x: x[\"size\"], reverse=True)\n        print(f\"[+] Infrastructure clusters: {len(clusters)}\")\n        return clusters\n\n    def find_hub_nodes(self, top_n=10):\n        \"\"\"Find high-centrality nodes (shared infrastructure).\"\"\"\n        centrality = nx.degree_centrality(self.graph)\n        top_nodes = sorted(centrality.items(), key=lambda x: x[1], reverse=True)[:top_n]\n        hubs = []\n        for node, score in top_nodes:\n            hubs.append({\n                \"node\": node,\n                \"type\": self.graph.nodes[node].get(\"type\", \"unknown\"),\n                \"centrality\": round(score, 4),\n                \"connections\": self.graph.degree(node),\n            })\n        return hubs\n\n    def export_graph(self, output_file=\"infrastructure_graph.json\"):\n        data = nx.node_link_data(self.graph)\n        with open(output_file, \"w\") as f:\n            json.dump(data, f, indent=2)\n        print(f\"[+] Graph exported: {self.graph.number_of_nodes()} nodes, \"\n              f\"{self.graph.number_of_edges()} edges\")\n\ninfra_graph = InfrastructureGraph()\ndiscovery = tracker.pivot_from_seed(\"evil-domain.com\", depth=2)\ninfra_graph.add_discovery(discovery)\nclusters = infra_graph.find_clusters()\nhubs = infra_graph.find_hub_nodes()\ninfra_graph.export_graph()\n```\n\n### Step 3: Monitor for New Infrastructure\n\n```python\nimport time\n\nclass InfrastructureMonitor:\n    def __init__(self, tracker, known_indicators):\n        self.tracker = tracker\n        self.known = set(known_indicators)\n        self.alerts = []\n\n    def check_new_registrations(self, patterns):\n        \"\"\"Check for newly registered domains matching adversary patterns.\"\"\"\n        import re\n        new_domains = []\n        for pattern in patterns:\n            # Query SecurityTrails for new domains matching pattern\n            headers = {\"apikey\": self.tracker.st_key}\n            url = \"https:\u002F\u002Fapi.securitytrails.com\u002Fv1\u002Fdomains\u002Flist\"\n            params = {\"include_ips\": \"true\", \"page\": 1}\n            body = {\"filter\": {\"keyword\": pattern}}\n            resp = requests.post(url, headers=headers, json=body, timeout=30)\n            if resp.status_code == 200:\n                records = resp.json().get(\"records\", [])\n                for record in records:\n                    domain = record.get(\"hostname\", \"\")\n                    if domain not in self.known:\n                        new_domains.append({\n                            \"domain\": domain,\n                            \"pattern_matched\": pattern,\n                            \"first_seen\": datetime.now().isoformat(),\n                        })\n                        self.known.add(domain)\n\n        if new_domains:\n            print(f\"[ALERT] {len(new_domains)} new domains matching patterns\")\n            self.alerts.extend(new_domains)\n        return new_domains\n\n    def generate_infrastructure_report(self, clusters, hubs):\n        report = f\"\"\"# Adversary Infrastructure Tracking Report\nGenerated: {datetime.now().isoformat()}\n\n## Summary\n- Infrastructure clusters identified: {len(clusters)}\n- Total domains tracked: {sum(c['domain_count'] for c in clusters)}\n- Total IPs tracked: {sum(c['ip_count'] for c in clusters)}\n- New domains detected: {len(self.alerts)}\n\n## Top Infrastructure Hubs\n| Node | Type | Connections | Centrality |\n|------|------|-------------|------------|\n\"\"\"\n        for hub in hubs[:10]:\n            report += (f\"| {hub['node']} | {hub['type']} \"\n                       f\"| {hub['connections']} | {hub['centrality']} |\\n\")\n\n        report += \"\\n## Infrastructure Clusters\\n\"\n        for i, cluster in enumerate(clusters[:5], 1):\n            report += f\"\\n### Cluster {i} ({cluster['size']} nodes)\\n\"\n            report += f\"- Domains: {', '.join(cluster['domains'][:5])}\\n\"\n            report += f\"- IPs: {', '.join(cluster['ips'][:5])}\\n\"\n\n        with open(\"infrastructure_report.md\", \"w\") as f:\n            f.write(report)\n        print(\"[+] Infrastructure report saved\")\n\nmonitor = InfrastructureMonitor(tracker, known_indicators=set())\n```\n\n## Validation Criteria\n\n- Passive DNS queries return historical resolution data\n- Reverse IP lookups discover co-hosted domains\n- Infrastructure pivoting expands from seed indicators\n- Graph analysis identifies clusters and hub nodes\n- New infrastructure detected through pattern monitoring\n- Reports generated with actionable recommendations\n\n## References\n\n- [Juniper: Threat Hunting with Passive DNS](https:\u002F\u002Fblogs.juniper.net\u002Fen-us\u002Fthreat-research\u002Fthreat-hunting-with-passive-dns-discovering-the-attacker-infrastructure)\n- [Censys: Advanced Persistent Infrastructure Tracking](https:\u002F\u002Fcensys.com\u002Fblog\u002Fadvanced-persistent-infrastructure-tracking)\n- [Embee Research: Malware Infrastructure with DNS Pivoting](https:\u002F\u002Fwww.embeeresearch.io\u002Finfrastructure-analysis-with-dns-pivoting\u002F)\n- [Validin: Passive DNS Threat Hunting](https:\u002F\u002Fwww.validin.com\u002Fblog\u002Fannouncing_validin_threat_hunting_platform\u002F)\n- [SecurityTrails API](https:\u002F\u002Fsecuritytrails.com\u002Fcorp\u002Fapi)\n- [Hunt.io: Uncovering Malicious Infrastructure](https:\u002F\u002Fhunt.io\u002Fblog\u002Fpractical-guide-unconvering-malicious-infrastructure)\n","# Building Adversary Infrastructure Tracking System\n\n## Overview\n\nAdversary infrastructure tracking uses passive DNS records, certificate transparency logs, WHOIS registration data, and IP enrichment to discover, map, and monitor threat actor command-and-control (C2) networks. Attackers frequently reuse hosting providers, registrars, SSL certificates, and naming patterns across campaigns, enabling analysts to pivot from known indicators to discover new infrastructure. This skill covers building an automated tracking system that identifies infrastructure relationships, detects newly registered domains matching adversary patterns, and maintains a continuously updated map of threat actor networks.\n\n\n## When to Use\n\n- When deploying or configuring building adversary infrastructure tracking system capabilities in your environment\n- When establishing security controls aligned to compliance requirements\n- When building or improving security architecture for this domain\n- When conducting security assessments that require this implementation\n\n## Prerequisites\n\n- Python 3.9+ with `requests`, `dnspython`, `python-whois`, `shodan`, `networkx` libraries\n- API keys: SecurityTrails, PassiveTotal\u002FRiskIQ, Shodan, VirusTotal\n- Access to passive DNS data sources\n- Understanding of DNS infrastructure, hosting, and domain registration\n- Graph database (Neo4j) or NetworkX for relationship visualization\n\n## Key Concepts\n\n### Passive DNS\n\nPassive DNS captures historical DNS resolution data, recording which domains resolved to which IPs and when. Unlike active DNS queries, passive DNS preserves historical relationships even after records change, enabling analysts to track infrastructure changes, identify shared hosting patterns, and discover related domains that resolved to the same IP addresses over time.\n\n### Infrastructure Pivoting\n\nPivoting identifies related infrastructure by following connections: IP pivot (find all domains on an IP), domain pivot (find all IPs a domain resolved to), WHOIS pivot (find domains with same registrant), certificate pivot (find hosts sharing SSL certificates), and NS\u002FMX pivot (find domains using same name servers or mail servers).\n\n### Adversary Infrastructure Patterns\n\nThreat actors exhibit patterns: preferred registrars (Namecheap, REG.RU, Tucows), preferred hosting (bulletproof hosting providers, cloud services), domain generation algorithms (DGA), consistent naming patterns, and certificate reuse across campaigns.\n\n## Workflow\n\n### Step 1: Passive DNS Infrastructure Discovery\n\n```python\nimport requests\nimport json\nfrom collections import defaultdict\nfrom datetime import datetime\n\nclass InfrastructureTracker:\n    def __init__(self, securitytrails_key=None, vt_key=None, shodan_key=None):\n        self.st_key = securitytrails_key\n        self.vt_key = vt_key\n        self.shodan_key = shodan_key\n        self.infrastructure_graph = defaultdict(lambda: {\"nodes\": set(), \"edges\": []})\n\n    def passive_dns_lookup(self, domain):\n        \"\"\"Query passive DNS for domain resolution history.\"\"\"\n        headers = {\"apikey\": self.st_key}\n        url = f\"https:\u002F\u002Fapi.securitytrails.com\u002Fv1\u002Fhistory\u002F{domain}\u002Fdns\u002Fa\"\n        resp = requests.get(url, headers=headers, timeout=30)\n        if resp.status_code == 200:\n            records = resp.json().get(\"records\", [])\n            history = []\n            for record in records:\n                for value in record.get(\"values\", []):\n                    history.append({\n                        \"domain\": domain,\n                        \"ip\": value.get(\"ip\", \"\"),\n                        \"first_seen\": record.get(\"first_seen\", \"\"),\n                        \"last_seen\": record.get(\"last_seen\", \"\"),\n                        \"type\": record.get(\"type\", \"a\"),\n                    })\n            print(f\"[+] Passive DNS for {domain}: {len(history)} records\")\n            return history\n        return []\n\n    def reverse_ip_lookup(self, ip_address):\n        \"\"\"Find all domains hosted on an IP address.\"\"\"\n        headers = {\"apikey\": self.st_key}\n        url = f\"https:\u002F\u002Fapi.securitytrails.com\u002Fv1\u002Fips\u002Fnearby\u002F{ip_address}\"\n        resp = requests.get(url, headers=headers, timeout=30)\n        if resp.status_code == 200:\n            blocks = resp.json().get(\"blocks\", [])\n            domains = []\n            for block in blocks:\n                for site in block.get(\"sites\", []):\n                    domains.append(site)\n            print(f\"[+] Reverse IP for {ip_address}: {len(domains)} domains\")\n            return domains\n        return []\n\n    def whois_lookup(self, domain):\n        \"\"\"Get WHOIS registration data for pivoting.\"\"\"\n        headers = {\"apikey\": self.st_key}\n        url = f\"https:\u002F\u002Fapi.securitytrails.com\u002Fv1\u002Fdomain\u002F{domain}\u002Fwhois\"\n        resp = requests.get(url, headers=headers, timeout=30)\n        if resp.status_code == 200:\n            data = resp.json()\n            whois_data = {\n                \"domain\": domain,\n                \"registrar\": data.get(\"registrar\", \"\"),\n                \"registrant_org\": data.get(\"registrant_org\", \"\"),\n                \"registrant_email\": data.get(\"registrant_email\", \"\"),\n                \"name_servers\": data.get(\"nameServers\", []),\n                \"created_date\": data.get(\"createdDate\", \"\"),\n                \"updated_date\": data.get(\"updatedDate\", \"\"),\n                \"expires_date\": data.get(\"expiresDate\", \"\"),\n            }\n            return whois_data\n        return {}\n\n    def pivot_from_seed(self, seed_indicator, indicator_type=\"domain\", depth=2):\n        \"\"\"Recursively pivot from a seed indicator to discover infrastructure.\"\"\"\n        discovered = {\"domains\": set(), \"ips\": set(), \"relationships\": []}\n\n        if indicator_type == \"domain\":\n            discovered[\"domains\"].add(seed_indicator)\n            # Get IPs for domain\n            pdns = self.passive_dns_lookup(seed_indicator)\n            for record in pdns:\n                ip = record[\"ip\"]\n                discovered[\"ips\"].add(ip)\n                discovered[\"relationships\"].append({\n                    \"source\": seed_indicator, \"target\": ip,\n                    \"type\": \"resolves_to\",\n                    \"first_seen\": record[\"first_seen\"],\n                    \"last_seen\": record[\"last_seen\"],\n                })\n\n                if depth > 1:\n                    # Reverse lookup on discovered IPs\n                    reverse_domains = self.reverse_ip_lookup(ip)\n                    for rd in reverse_domains[:20]:\n                        discovered[\"domains\"].add(rd)\n                        discovered[\"relationships\"].append({\n                            \"source\": rd, \"target\": ip,\n                            \"type\": \"hosted_on\",\n                        })\n\n        elif indicator_type == \"ip\":\n            discovered[\"ips\"].add(seed_indicator)\n            domains = self.reverse_ip_lookup(seed_indicator)\n            for domain in domains[:20]:\n                discovered[\"domains\"].add(domain)\n                discovered[\"relationships\"].append({\n                    \"source\": domain, \"target\": seed_indicator,\n                    \"type\": \"hosted_on\",\n                })\n\n        print(f\"[+] Pivot from {seed_indicator}: \"\n              f\"{len(discovered['domains'])} domains, \"\n              f\"{len(discovered['ips'])} IPs, \"\n              f\"{len(discovered['relationships'])} relationships\")\n        return discovered\n\ntracker = InfrastructureTracker(\n    securitytrails_key=\"YOUR_ST_KEY\",\n    vt_key=\"YOUR_VT_KEY\",\n)\n```\n\n### Step 2: Build Infrastructure Graph\n\n```python\nimport networkx as nx\n\nclass InfrastructureGraph:\n    def __init__(self):\n        self.graph = nx.Graph()\n\n    def add_discovery(self, discovery_data):\n        \"\"\"Add discovered infrastructure to graph.\"\"\"\n        for domain in discovery_data[\"domains\"]:\n            self.graph.add_node(domain, type=\"domain\")\n        for ip in discovery_data[\"ips\"]:\n            self.graph.add_node(ip, type=\"ip\")\n        for rel in discovery_data[\"relationships\"]:\n            self.graph.add_edge(\n                rel[\"source\"], rel[\"target\"],\n                relationship=rel[\"type\"],\n                first_seen=rel.get(\"first_seen\", \"\"),\n                last_seen=rel.get(\"last_seen\", \"\"),\n            )\n\n    def find_clusters(self):\n        \"\"\"Identify infrastructure clusters.\"\"\"\n        components = list(nx.connected_components(self.graph))\n        clusters = []\n        for component in components:\n            domains = [n for n in component if self.graph.nodes[n].get(\"type\") == \"domain\"]\n            ips = [n for n in component if self.graph.nodes[n].get(\"type\") == \"ip\"]\n            clusters.append({\n                \"size\": len(component),\n                \"domains\": sorted(domains),\n                \"ips\": sorted(ips),\n                \"domain_count\": len(domains),\n                \"ip_count\": len(ips),\n            })\n        clusters.sort(key=lambda x: x[\"size\"], reverse=True)\n        print(f\"[+] Infrastructure clusters: {len(clusters)}\")\n        return clusters\n\n    def find_hub_nodes(self, top_n=10):\n        \"\"\"Find high-centrality nodes (shared infrastructure).\"\"\"\n        centrality = nx.degree_centrality(self.graph)\n        top_nodes = sorted(centrality.items(), key=lambda x: x[1], reverse=True)[:top_n]\n        hubs = []\n        for node, score in top_nodes:\n            hubs.append({\n                \"node\": node,\n                \"type\": self.graph.nodes[node].get(\"type\", \"unknown\"),\n                \"centrality\": round(score, 4),\n                \"connections\": self.graph.degree(node),\n            })\n        return hubs\n\n    def export_graph(self, output_file=\"infrastructure_graph.json\"):\n        data = nx.node_link_data(self.graph)\n        with open(output_file, \"w\") as f:\n            json.dump(data, f, indent=2)\n        print(f\"[+] Graph exported: {self.graph.number_of_nodes()} nodes, \"\n              f\"{self.graph.number_of_edges()} edges\")\n\ninfra_graph = InfrastructureGraph()\ndiscovery = tracker.pivot_from_seed(\"evil-domain.com\", depth=2)\ninfra_graph.add_discovery(discovery)\nclusters = infra_graph.find_clusters()\nhubs = infra_graph.find_hub_nodes()\ninfra_graph.export_graph()\n```\n\n### Step 3: Monitor for New Infrastructure\n\n```python\nimport time\n\nclass InfrastructureMonitor:\n    def __init__(self, tracker, known_indicators):\n        self.tracker = tracker\n        self.known = set(known_indicators)\n        self.alerts = []\n\n    def check_new_registrations(self, patterns):\n        \"\"\"Check for newly registered domains matching adversary patterns.\"\"\"\n        import re\n        new_domains = []\n        for pattern in patterns:\n            # Query SecurityTrails for new domains matching pattern\n            headers = {\"apikey\": self.tracker.st_key}\n            url = \"https:\u002F\u002Fapi.securitytrails.com\u002Fv1\u002Fdomains\u002Flist\"\n            params = {\"include_ips\": \"true\", \"page\": 1}\n            body = {\"filter\": {\"keyword\": pattern}}\n            resp = requests.post(url, headers=headers, json=body, timeout=30)\n            if resp.status_code == 200:\n                records = resp.json().get(\"records\", [])\n                for record in records:\n                    domain = record.get(\"hostname\", \"\")\n                    if domain not in self.known:\n                        new_domains.append({\n                            \"domain\": domain,\n                            \"pattern_matched\": pattern,\n                            \"first_seen\": datetime.now().isoformat(),\n                        })\n                        self.known.add(domain)\n\n        if new_domains:\n            print(f\"[ALERT] {len(new_domains)} new domains matching patterns\")\n            self.alerts.extend(new_domains)\n        return new_domains\n\n    def generate_infrastructure_report(self, clusters, hubs):\n        report = f\"\"\"# Adversary Infrastructure Tracking Report\nGenerated: {datetime.now().isoformat()}\n\n## Summary\n- Infrastructure clusters identified: {len(clusters)}\n- Total domains tracked: {sum(c['domain_count'] for c in clusters)}\n- Total IPs tracked: {sum(c['ip_count'] for c in clusters)}\n- New domains detected: {len(self.alerts)}\n\n## Top Infrastructure Hubs\n| Node | Type | Connections | Centrality |\n|------|------|-------------|------------|\n\"\"\"\n        for hub in hubs[:10]:\n            report += (f\"| {hub['node']} | {hub['type']} \"\n                       f\"| {hub['connections']} | {hub['centrality']} |\\n\")\n\n        report += \"\\n## Infrastructure Clusters\\n\"\n        for i, cluster in enumerate(clusters[:5], 1):\n            report += f\"\\n### Cluster {i} ({cluster['size']} nodes)\\n\"\n            report += f\"- Domains: {', '.join(cluster['domains'][:5])}\\n\"\n            report += f\"- IPs: {', '.join(cluster['ips'][:5])}\\n\"\n\n        with open(\"infrastructure_report.md\", \"w\") as f:\n            f.write(report)\n        print(\"[+] Infrastructure report saved\")\n\nmonitor = InfrastructureMonitor(tracker, known_indicators=set())\n```\n\n## Validation Criteria\n\n- Passive DNS queries return historical resolution data\n- Reverse IP lookups discover co-hosted domains\n- Infrastructure pivoting expands from seed indicators\n- Graph analysis identifies clusters and hub nodes\n- New infrastructure detected through pattern monitoring\n- Reports generated with actionable recommendations\n\n## References\n\n- [Juniper: Threat Hunting with Passive DNS](https:\u002F\u002Fblogs.juniper.net\u002Fen-us\u002Fthreat-research\u002Fthreat-hunting-with-passive-dns-discovering-the-attacker-infrastructure)\n- [Censys: Advanced Persistent Infrastructure Tracking](https:\u002F\u002Fcensys.com\u002Fblog\u002Fadvanced-persistent-infrastructure-tracking)\n- [Embee Research: Malware Infrastructure with DNS Pivoting](https:\u002F\u002Fwww.embeeresearch.io\u002Finfrastructure-analysis-with-dns-pivoting\u002F)\n- [Validin: Passive DNS Threat Hunting](https:\u002F\u002Fwww.validin.com\u002Fblog\u002Fannouncing_validin_threat_hunting_platform\u002F)\n- [SecurityTrails API](https:\u002F\u002Fsecuritytrails.com\u002Fcorp\u002Fapi)\n- [Hunt.io: Uncovering Malicious Infrastructure](https:\u002F\u002Fhunt.io\u002Fblog\u002Fpractical-guide-unconvering-malicious-infrastructure)\n",{"name":5,"tags":45,"author":46,"domain":27,"license":15,"version":47,"nist_csf":48,"subdomain":30,"description":7,"mitre_attack":53},[35,36,31,37,29,38,30,39],"mahipal","1.0",[49,50,51,52],"ID.RA-01","ID.RA-05","DE.CM-01","DE.AE-02",[54,55,56,57,58],"T1583.001","T1583.004","T1596.001","T1590.002","T1071.001","main","54a798831d2266a3ca61ce68a7acb80b81160d57","skills\u002Fbuilding-adversary-infrastructure-tracking-system",4414,"https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills","https:\u002F\u002Fmahipal.engineer\u002FAnthropic-Cybersecurity-Skills\u002F","https:\u002F\u002Fgithub.com\u002Fmukul975","Mahipal.engineer","🔐 Cybersecurity | 💻 Dev | 📷 Street Photographer\r\n🎓 MSc | 📚 Research & AI Security","2026-08-31 12:32:44",{"source":8,"skillName":5,"commands":70,"prompt":80,"zipAvailable":81},[71,74,77],{"tool":72,"command":73},"npx","npx skills add mukul975\u002FAnthropic-Cybersecurity-Skills --skill building-adversary-infrastructure-tracking-system",{"tool":75,"command":76},"bunx","bunx skills add mukul975\u002FAnthropic-Cybersecurity-Skills --skill building-adversary-infrastructure-tracking-system",{"tool":78,"command":79},"pnpm","pnpm dlx skills add mukul975\u002FAnthropic-Cybersecurity-Skills --skill building-adversary-infrastructure-tracking-system","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fbuilding-adversary-infrastructure-tracking-system\u002FSKILL.md",true,[83,88,94],{"path":84,"resourceType":84,"resourceTypeDesc":85,"sizeBytes":86,"sourceHtmlUrl":87},"LICENSE","许可证",11255,"https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fbuilding-adversary-infrastructure-tracking-system\u002FLICENSE",{"path":89,"resourceType":90,"resourceTypeDesc":91,"sizeBytes":92,"sourceHtmlUrl":93},"references\u002Fapi-reference.md","REFERENCE","参考文档",1504,"https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fbuilding-adversary-infrastructure-tracking-system\u002Freferences\u002Fapi-reference.md",{"path":95,"resourceType":96,"resourceTypeDesc":97,"sizeBytes":98,"sourceHtmlUrl":99},"scripts\u002Fagent.py","SCRIPT","脚本",4517,"https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fbuilding-adversary-infrastructure-tracking-system\u002Fscripts\u002Fagent.py",[101,128,152,179,204,231],{"skillNo":102,"name":103,"nameZh":6,"description":104,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":105,"categories":106,"keywords":108,"publishedAt":40},"01M6AGDM3HJXTKXX15ZZ0ZVCJ3","verifying-build-provenance-with-slsa-sigstore","Verifies artifact signatures and SLSA provenance using Sigstore's cosign (verify, verify-attestation, verify-blob-attestation) and slsa-verifier (verify-artifact), enforcing keyless OIDC builder identity and source repo against SLSA Build levels. Use in CI\u002FCD before deploying artifacts, when consuming third-party attestations, establishing a SLSA Build L3 pipeline, or confirming provenance during incident response or admission control.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fverifying-build-provenance-with-slsa-sigstore\u002FSKILL.md",[107],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[109,110,111,112,113,27,114,115,116,117,118,119,120,121,122,123,124,125,126,127],"sigstore","provenance","slsa","verifying build provenance with slsa sigstore","security","incident response","identity","pr","code","artifacts","ci","supply-chain","pipeline","supply-chain-security","t1195","attestation","code-signing","cosign","keyless",{"skillNo":129,"name":130,"nameZh":6,"description":131,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":132,"categories":133,"keywords":135,"publishedAt":40},"01M6AGDGBPWYVZ2F11GFKJ4HZ9","validating-tpm-measured-boot-attestation","Verifies TPM 2.0 measured-boot integrity and remote attestation with tpm2-tools -- reading PCRs (tpm2_pcrread), replaying the boot event log, generating and checking signed quotes (tpm2_quote\u002Ftpm2_checkquote), and sealing secrets to a PCR policy. Use to confirm a system booted trusted firmware\u002Fkernel for Zero Trust device posture, detect boot-chain tampering via PCR drift, or build a golden-value baseline for fleet attestation.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fvalidating-tpm-measured-boot-attestation\u002FSKILL.md",[134],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[136,124,137,138,113,139,27,116,140,141,142,143,144,145,146,147,148,149,150,151],"boot","TPM","validating tpm measured boot attestation","policy","verification","ZeRO","firmware","Tools","measured-boot","PCR","integrity","secrets","remote-attestation","tpm2-tools","integrity-verification","trusted-computing",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":156,"categories":157,"keywords":162,"publishedAt":40},"01M6AGDCW0Y4FXZ3362GT1941M","validating-backup-integrity-for-recovery","Validates backup integrity through cryptographic hash verification, automated restore testing, corruption detection, and recoverability checks to confirm backups are reliable for disaster recovery and ransomware response. Use before relying on backups for recovery, when building post-backup validation pipelines, auditing backup infrastructure for compliance, or checking immutable\u002Fair-gapped backups for silent corruption or tampering.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Fvalidating-backup-integrity-for-recovery\u002FSKILL.md",[158,161],{"categoryNo":159,"categoryName":160,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[146,163,164,165,166,27,24,167,140,168,169,170,171,172,173,174,175,176,177,178],"backup","recovery","validating backup integrity for recovery","testing","validation","compliance","hash-verification","incident-response","ransomware","cryptocurrency","detection","t1078","t1490","immutable","disaster-recovery","restore-testing",{"skillNo":180,"name":181,"nameZh":6,"description":182,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":183,"categories":184,"keywords":186,"publishedAt":40},"01M6AGD9GBG2KZ336AE763J3WH","triaging-windows-with-kape","Runs KAPE (Kroll Artifact Parser and Extractor) to collect targeted forensic artifacts (registry hives, $MFT, event logs, prefetch, browser data) via Targets and parse them with Modules wrapping Eric Zimmerman's EZ Tools (PECmd, MFTECmd, RECmd). Use during early incident containment\u002Ftriage when full disk imaging is impractical but a defensible, parseable Windows artifact set is needed quickly, including at-scale remote collection.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Ftriaging-windows-with-kape\u002FSKILL.md",[185],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[187,188,189,27,190,191,28,192,193,194,195,196,197,198,199,200,143,201,202,203],"windows","kape","triaging windows with kape","registry","browser","windows-forensics","dfir","mft","mftecmd","data","prefetch","eric-zimmerman","digital-forensics","SET","collection","pecmd","artifact-collection",{"skillNo":205,"name":206,"nameZh":6,"description":207,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":208,"categories":209,"keywords":211,"publishedAt":40},"01M6AGD5PW5J4EVZM958WD74ZQ","triaging-vulnerabilities-with-ssvc-framework","Triages and prioritizes vulnerabilities with CISA's Stakeholder-Specific Vulnerability Categorization (SSVC) decision tree, weighing exploitation status (via the CISA KEV catalog and FIRST EPSS API), technical impact, automatability, and mission prevalence to output Track\u002FTrack*\u002FAttend\u002FAct decisions. Use when prioritizing vulnerability scan results (OpenVAS, Nessus, Qualys) for remediation planning beyond raw CVSS scores.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Ftriaging-vulnerabilities-with-ssvc-framework\u002FSKILL.md",[210],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[212,213,214,27,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230],"vulnerabilities","framework","triaging vulnerabilities with ssvc framework","status","planning","CISA","vulnerability-management","risk-management","nessus","qualys","openvas","cvss","remediation","risk","vulnerability","api","prioritization","ssvc","decision-tree",{"skillNo":232,"name":233,"nameZh":6,"description":234,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":235,"categories":236,"keywords":238,"publishedAt":40},"01M6AGD24TTQQM4CXG69E3B9TJ","triaging-security-incident","Performs initial triage of security incidents using the NIST SP 800-61r3 and SANS PICERL frameworks, classifying incident type, assigning priority by business impact, and routing to the appropriate response team. Use when a SIEM\u002FEDR alert needs human classification, concurrent alerts must be prioritized, or a user report or threat-intel IOC match requires initial incident categorization.","https:\u002F\u002Fgithub.com\u002Fmukul975\u002FAnthropic-Cybersecurity-Skills\u002Fblob\u002Fmain\u002Fskills\u002Ftriaging-security-incident\u002FSKILL.md",[237],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[113,239,27,240,241,242,243,244,245,246,247,174,248,175,249,250,251,252,253,254],"triaging security incident","siem","file","ioc","soc","NIST-800-61","NIST","severity","edr","execution","analysis","classification","severity-classification","incident-triage","SANS-PICERL","SOC-operations"]