{
  "hunt": {
    "meta": {
      "tlp": "clear",
      "hunt": {
        "handoff": "promote-to-detection",
        "trigger": "intel-report",
        "methodology": "model-assisted",
        "applicability": "campaign-specific",
        "justification": "Vulnerability researchers are high-value targets whose compromise exposes proprietary research and customer vulnerability data. A negative result confirms that active trojanised PoC campaigns have not reached the internal research estate."
      },
      "name": "ChocoPoC: Mapbox Dead-Drop C2 and Exfiltration",
      "type": "investigation",
      "labels": [
        "hunt",
        "attack.t1041",
        "attack.t1102",
        "attack.t1555",
        "attack.t1572"
      ],
      "series": {
        "slug": "don-t-eat-the-chocopocs-trojanised-pocs-hit-researchers",
        "index": 2,
        "title": "Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers",
        "total": 2
      },
      "related": [
        {
          "hunt": "python-malicious-pypi-droppers",
          "reason": "This hunt handles the C2 and exfiltration; initial access through native extension loading is handled by its sibling.",
          "relation": "out-of-scope-alternative"
        }
      ],
      "targets": {
        "web": {
          "name": "Web server / proxy logs",
          "category": "siem",
          "telemetry": [
            "network"
          ]
        },
        "hunter": {
          "name": "Hunt agent",
          "agent": true
        },
        "analyst": {
          "name": "Tier-2 analyst",
          "role": "analyst"
        },
        "network": {
          "name": "Network telemetry",
          "category": "network",
          "telemetry": [
            "network"
          ]
        },
        "endpoint": {
          "name": "Endpoint telemetry (hb_ surfaces)",
          "category": "endpoint",
          "telemetry": [
            "endpoint"
          ]
        }
      },
      "analysis": "A standard detection rule would likely false-positive on legitimate Python usage of Mapbox APIs; this hunt adds the context of DoH resolution and rare credential store access to confirm the RAT's impact.",
      "coverage": [
        {
          "stage": "c2-doh-mapbox-dead-drop",
          "steps": [
            "python-networking-lead",
            "mapbox-payload-retrieval"
          ],
          "status": "covered"
        },
        {
          "stage": "collection-exfiltration-rat",
          "steps": [
            "credential-harvesting"
          ],
          "status": "covered"
        },
        {
          "stage": "initial-access-malicious-pypi-poc",
          "reason": "Belongs to another part of the \"Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers\" series.",
          "status": "out_of_scope"
        },
        {
          "stage": "execution-native-extension-loading",
          "reason": "Belongs to another part of the \"Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers\" series.",
          "status": "out_of_scope"
        },
        {
          "stage": "defense-evasion-environmental-gating",
          "reason": "Belongs to another part of the \"Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers\" series.",
          "status": "out_of_scope"
        },
        {
          "stage": "persistence-site-packages-shim",
          "reason": "Belongs to another part of the \"Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers\" series.",
          "status": "out_of_scope"
        }
      ],
      "scenario": {
        "stages": [
          {
            "name": "Trojanised Python packages via lure PoC",
            "slug": "initial-access-malicious-pypi-poc",
            "tactic": "initial-access",
            "techniques": [
              "T1195",
              "T1190"
            ],
            "observables": [
              "frint",
              "skytext",
              "CVE-2026-48908",
              "CVE-2025-55182",
              "CVE-2025-64446",
              "CVE-2026-10520",
              "github.com/ogenich/CVE-2026-48908"
            ]
          },
          {
            "name": "Malicious Python native extension execution",
            "slug": "execution-native-extension-loading",
            "tactic": "execution",
            "techniques": [
              "T1129"
            ],
            "observables": [
              "gradient.pyd",
              "gradient.so",
              "PyInit_gradient"
            ]
          },
          {
            "name": "Anti-analysis and environment-aware execution",
            "slug": "defense-evasion-environmental-gating",
            "tactic": "defense-evasion",
            "techniques": [
              "T1497",
              "T1027"
            ],
            "observables": [
              "EXPLOIT_POC.py",
              "exploit.py",
              "CheckRemoteDebuggerPresent"
            ]
          },
          {
            "name": "Persistence via Python site-packages shims",
            "slug": "persistence-site-packages-shim",
            "tactic": "persistence",
            "techniques": [
              "T1546",
              "T1070.006"
            ],
            "observables": [
              "_disutils_hack",
              ".pth files",
              "choco.py"
            ]
          },
          {
            "name": "Multi-stage C2 via DoH and Mapbox datasets",
            "slug": "c2-doh-mapbox-dead-drop",
            "tactic": "command-and-control",
            "techniques": [
              "T1572",
              "T1102"
            ],
            "observables": [
              "dns.alidns.com",
              "cloudflare-dns.com",
              "api.mapbox.com",
              "api.mapbox.com/datasets/v1/frankley/cmor0tcxf008i1mmpd7apt903/features/dm370543acmdopk296nahbtua"
            ]
          },
          {
            "name": "Credential harvesting and data exfiltration",
            "slug": "collection-exfiltration-rat",
            "tactic": "collection",
            "techniques": [
              "T1555",
              "T1041"
            ],
            "observables": [
              "ChocoPoC RAT"
            ]
          }
        ],
        "summary": "A supply chain campaign targeting vulnerability researchers distributes trojanised Python PoC repositories on GitHub. These PoCs include malicious PyPI dependencies that load obfuscated native extensions to establish persistence and deploy ChocoPoC, a RAT that uses DNS-over-HTTPS and Mapbox datasets for command and control."
      },
      "severity": "high",
      "rationale": "Focus on developer workstations and vulnerability research environments. If no signals are found on those hosts, widen the hunt to any system running Python with outbound HTTPS access.",
      "guardrails": {
        "claims": "no_unsupported",
        "evidence": "citation_required",
        "telemetry": "untrusted",
        "missing_data": "not_benign"
      },
      "hypothesis": "An adversary is using trojanised Python packages to establish C2 via DoH and Mapbox datasets on researcher workstations, subsequently exfiltrating credentials from local password stores.",
      "parameters": {
        "mapbox_api": {
          "from": {
            "ref": "sekoia-chocopoc",
            "kind": "article",
            "observed": "2026-06-30"
          },
          "type": "domain",
          "default": "api.mapbox.com",
          "description": "The primary Mapbox API domain used for dead-drops."
        },
        "scope_hosts": {
          "type": "list[host]",
          "default": [],
          "description": "Optional list of hostnames to narrow the hunt scope."
        },
        "doh_resolvers": {
          "from": {
            "ref": "sekoia-chocopoc",
            "kind": "article",
            "observed": "2026-06-30"
          },
          "type": "list[domain]",
          "default": [
            "dns.alidns.com",
            "cloudflare-dns.com"
          ],
          "description": "DoH resolver hostnames observed in the campaign."
        },
        "lookback_days": {
          "type": "number",
          "default": "14",
          "description": "Days of history to examine."
        },
        "sensitive_files": {
          "type": "list[string]",
          "default": [
            "login data",
            "cookies",
            "key4.db",
            "credentials",
            "id_rsa"
          ],
          "description": "Filenames of credential and secret stores targeted by the RAT."
        }
      },
      "provenance": {
        "authors": [
          {
            "org": "huntbase.io",
            "name": "Huntbase hunt generation"
          }
        ],
        "generated": {
          "by": "huntbase-hunt-generation",
          "from": "https://www.sekoia.com/blog/dont-eat-the-chocopocs-how-vulnerability-researchers-were-repeatedly-targeted-by-trojanised-exploits",
          "gates": [
            "dry-run",
            "lint",
            "critic"
          ],
          "model": "hb_google/gemini-3-flash-preview"
        }
      },
      "references": [
        {
          "url": "https://www.sekoia.com/blog/dont-eat-the-chocopocs-how-vulnerability-researchers-were-repeatedly-targeted-by-trojanised-exploits",
          "name": "Sekoia \u2014 Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers"
        }
      ],
      "blind_spots": [
        {
          "id": "missing-http-process-context",
          "risk": "hb_http_activity does not record the process_name, so we must rely on timing and host-level correlation to link the HTTP request to the Python RAT.",
          "stage": "c2-doh-mapbox-dead-drop",
          "question": "Which specific Python process initiated the Mapbox dataset retrieval?",
          "requires": "hb_http_activity with process context"
        },
        {
          "id": "domain-fronting-obscurity",
          "risk": "If the malware connects directly to a malicious IP while using 'Host: api.mapbox.com', standard network logs might only see the IP connection, potentially missing the C2 signal.",
          "stage": "c2-doh-mapbox-dead-drop",
          "question": "Is the malware using IP-pinning with a spoofed Host header to hide its true destination?",
          "requires": "TLS inspection or detailed Host header logging"
        }
      ]
    },
    "name": "ChocoPoC: Mapbox Dead-Drop C2 and Exfiltration",
    "description": "This hunt targets the command-and-control and exfiltration phases of the ChocoPoC RAT campaign. It identifies Python processes that bypass local DNS controls by using public DNS-over-HTTPS (DoH) resolvers to resolve Mapbox infrastructure, which is then used as a dead-drop for payload delivery. The hunt corroborates this activity by looking for specific Mapbox dataset API access patterns and identifying Python processes that access sensitive credential stores like browser profile data or SSH keys. The combination of DoH usage, Mapbox dataset retrieval, and rare access to secret files from a Python interpreter provides high-fidelity evidence of this compromise."
  },
  "nodes": [
    {
      "id": "hypothesis",
      "type": "hypothesis",
      "label": "Hypothesis",
      "config": {
        "tags": [],
        "series": {
          "slug": "don-t-eat-the-chocopocs-trojanised-pocs-hit-researchers",
          "index": 2,
          "title": "Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers",
          "total": 2
        },
        "coverage": [
          {
            "stage": "c2-doh-mapbox-dead-drop",
            "steps": [
              "python-networking-lead",
              "mapbox-payload-retrieval"
            ],
            "status": "covered"
          },
          {
            "stage": "collection-exfiltration-rat",
            "steps": [
              "credential-harvesting"
            ],
            "status": "covered"
          },
          {
            "stage": "initial-access-malicious-pypi-poc",
            "reason": "Belongs to another part of the \"Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers\" series.",
            "status": "out_of_scope"
          },
          {
            "stage": "execution-native-extension-loading",
            "reason": "Belongs to another part of the \"Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers\" series.",
            "status": "out_of_scope"
          },
          {
            "stage": "defense-evasion-environmental-gating",
            "reason": "Belongs to another part of the \"Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers\" series.",
            "status": "out_of_scope"
          },
          {
            "stage": "persistence-site-packages-shim",
            "reason": "Belongs to another part of the \"Don't Eat the ChocoPoCs: Trojanised PoCs Hit Researchers\" series.",
            "status": "out_of_scope"
          }
        ],
        "rationale": "An adversary is using trojanised Python packages to establish C2 via DoH and Mapbox datasets on researcher workstations, subsequently exfiltrating credentials from local password stores.",
        "blind_spots": [
          {
            "id": "missing-http-process-context",
            "risk": "hb_http_activity does not record the process_name, so we must rely on timing and host-level correlation to link the HTTP request to the Python RAT.",
            "stage": "c2-doh-mapbox-dead-drop",
            "question": "Which specific Python process initiated the Mapbox dataset retrieval?",
            "requires": "hb_http_activity with process context"
          },
          {
            "id": "domain-fronting-obscurity",
            "risk": "If the malware connects directly to a malicious IP while using 'Host: api.mapbox.com', standard network logs might only see the IP connection, potentially missing the C2 signal.",
            "stage": "c2-doh-mapbox-dead-drop",
            "question": "Is the malware using IP-pinning with a spoofed Host header to hide its true destination?",
            "requires": "TLS inspection or detailed Host header logging"
          }
        ],
        "scoping_notes": "Focus on developer workstations and vulnerability research environments. If no signals are found on those hosts, widen the hunt to any system running Python with outbound HTTPS access.",
        "beyond_detection": "A standard detection rule would likely false-positive on legitimate Python usage of Mapbox APIs; this hunt adds the context of DoH resolution and rare credential store access to confirm the RAT's impact."
      }
    },
    {
      "id": "python-networking-lead",
      "type": "query",
      "label": "Python networking to DoH or Mapbox",
      "config": {
        "dsl": "sqlite",
        "role": "scoping",
        "source": "network",
        "content": "SELECT device_hostname, process_name, dst_endpoint_hostname, dst_endpoint_port, time FROM hb_network_connection WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND LOWER(process_name) LIKE '%python%' AND (instr(',' || '{{doh_resolvers}}' || ',', ',' || LOWER(dst_endpoint_hostname) || ',') > 0 OR LOWER(dst_endpoint_hostname) = '{{mapbox_api}}') AND time >= datetime('now', '-{{lookback_days}} days')",
        "surface": "hb_network_connection",
        "description": "Identify Python processes communicating with known DoH resolvers or Mapbox infrastructure as a lead for C2 activity.",
        "expected_signal": "Python processes making connections to DoH resolvers or Mapbox. Legitimate developer tools rarely use DoH; most rely on the system resolver."
      },
      "parents": [
        {
          "id": "hypothesis"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "scoping",
        "label": "Python networking to DoH or Mapbox",
        "reads": [
          "device_hostname",
          "process_name",
          "dst_endpoint_hostname",
          "dst_endpoint_port",
          "time"
        ],
        "source": "hb_network_connection",
        "target": "network",
        "content": "SELECT device_hostname, process_name, dst_endpoint_hostname, dst_endpoint_port, time FROM hb_network_connection WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND LOWER(process_name) LIKE '%python%' AND (instr(',' || '{{doh_resolvers}}' || ',', ',' || LOWER(dst_endpoint_hostname) || ',') > 0 OR LOWER(dst_endpoint_hostname) = '{{mapbox_api}}') AND time >= datetime('now', '-{{lookback_days}} days')",
        "silence": "not_evidence_of_absence",
        "expected": "Python processes making connections to DoH resolvers or Mapbox. Legitimate developer tools rarely use DoH; most rely on the system resolver.",
        "verified": "dry-run",
        "verified_at": "2026-09-28"
      }
    },
    {
      "id": "mapbox-payload-retrieval",
      "type": "query",
      "label": "Mapbox dataset access patterns",
      "config": {
        "dsl": "sqlite",
        "role": "detection-candidate",
        "source": "web",
        "content": "SELECT device_hostname, url_hostname, url_path, time FROM hb_http_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND LOWER(url_hostname) = '{{mapbox_api}}' AND LOWER(url_path) LIKE '%/datasets/v1/%' AND time >= datetime('now', '-{{lookback_days}} days')",
        "surface": "hb_http_activity",
        "description": "Identify the specific HTTP request pattern used to retrieve the ChocoPoC RAT payload from Mapbox.",
        "expected_signal": "Requests to Mapbox dataset features, which act as a dead-drop for the final stage script. Silence here is not proof of absence if the attacker rotates the dead-drop provider."
      },
      "parents": [
        {
          "id": "python-networking-lead"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "detection-candidate",
        "label": "Mapbox dataset access patterns",
        "reads": [
          "device_hostname",
          "url_hostname",
          "url_path",
          "time"
        ],
        "source": "hb_http_activity",
        "target": "web",
        "content": "SELECT device_hostname, url_hostname, url_path, time FROM hb_http_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND LOWER(url_hostname) = '{{mapbox_api}}' AND LOWER(url_path) LIKE '%/datasets/v1/%' AND time >= datetime('now', '-{{lookback_days}} days')",
        "silence": "not_evidence_of_absence",
        "expected": "Requests to Mapbox dataset features, which act as a dead-drop for the final stage script. Silence here is not proof of absence if the attacker rotates the dead-drop provider.",
        "verified": "dry-run",
        "verified_at": "2026-09-28"
      }
    },
    {
      "id": "credential-harvesting",
      "type": "query",
      "label": "Rare Python access to credentials",
      "config": {
        "dsl": "sqlite",
        "role": "baseline",
        "source": "endpoint",
        "content": "SELECT device_hostname, process_name, file_path, file_name, COUNT(*) as access_count, MIN(time) as first_seen FROM hb_file_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND LOWER(process_name) LIKE '%python%' AND instr(',' || '{{sensitive_files}}' || ',', ',' || LOWER(file_name) || ',') > 0 AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, process_name, file_path, file_name HAVING COUNT(DISTINCT device_hostname) <= 3",
        "surface": "hb_file_activity",
        "description": "Find Python processes reading sensitive credential files, stack-counted to highlight anomalies.",
        "expected_signal": "A Python process accessing files like 'Login Data' or 'credentials' on a very small number of hosts. This identifies the impact of the RAT's info-stealing capabilities."
      },
      "parents": [
        {
          "id": "python-networking-lead"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "baseline",
        "label": "Rare Python access to credentials",
        "reads": [
          "device_hostname",
          "process_name",
          "file_path",
          "file_name",
          "time"
        ],
        "source": "hb_file_activity",
        "target": "endpoint",
        "content": "SELECT device_hostname, process_name, file_path, file_name, COUNT(*) as access_count, MIN(time) as first_seen FROM hb_file_activity WHERE ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND LOWER(process_name) LIKE '%python%' AND instr(',' || '{{sensitive_files}}' || ',', ',' || LOWER(file_name) || ',') > 0 AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, process_name, file_path, file_name HAVING COUNT(DISTINCT device_hostname) <= 3",
        "silence": "not_evidence_of_absence",
        "baseline": {
          "window": "{{lookback_days}}d",
          "compare": "first_seen"
        },
        "expected": "A Python process accessing files like 'Login Data' or 'credentials' on a very small number of hosts. This identifies the impact of the RAT's info-stealing capabilities.",
        "verified": "dry-run",
        "prevalence": {
          "by": "device_hostname",
          "key": [
            "process_name",
            "file_name"
          ],
          "rare_below": 3
        },
        "verified_at": "2026-09-28"
      }
    },
    {
      "id": "triage-findings",
      "type": "analytic",
      "label": "Triage ChocoPoC activity",
      "config": {
        "cite": "required",
        "tools": [
          "endpoint",
          "network",
          "web"
        ],
        "context": [
          "python-networking-lead",
          "mapbox-payload-retrieval",
          "credential-harvesting"
        ],
        "objective": "Decide if any host shows the ChocoPoC signature: a Python process using DoH or Mapbox to retrieve a payload, followed by access to local secrets.",
        "description": "Synthesize the networking, HTTP, and file access results to confirm a RAT infection.",
        "max_iterations": 6,
        "expected_signal": "A per-host verdict citing the specific Python process that resolves DoH, fetches from Mapbox, and touches credentials.",
        "success_criteria": "A verdict of malicious | suspicious | benign per host, citing the rows."
      },
      "parents": [
        {
          "id": "mapbox-payload-retrieval",
          "kind": "merge"
        },
        {
          "id": "credential-harvesting",
          "kind": "merge"
        }
      ]
    },
    {
      "id": "evaluate-threat",
      "type": "checkpoint",
      "label": "Evaluate threat verdict",
      "config": {
        "fuzzy": true,
        "judge": "hunter",
        "question": "the triage-findings verdict is malicious for at least one host",
        "condition": "the triage-findings verdict is malicious for at least one host",
        "blind_spot": "missing-http-process-context",
        "confidence": "high",
        "description": "Route the hunt based on the agent's findings.",
        "checkpoint_type": "mandatory"
      },
      "parents": [
        {
          "id": "triage-findings"
        }
      ]
    },
    {
      "id": "isolate-workstation",
      "type": "action",
      "label": "Isolate workstation",
      "config": {
        "target": "endpoint",
        "description": "Halt data exfiltration and prevent further command execution.",
        "instructions": "Isolate the host and collect any local Python script files (e.g., choco.py) or modified site-packages for forensics.",
        "action_approval": "required"
      },
      "parents": [
        {
          "id": "evaluate-threat",
          "branch": "on_supports"
        }
      ]
    },
    {
      "id": "remediation-tasks",
      "type": "task",
      "label": "Remediation and review",
      "config": {
        "assignee": "analyst",
        "description": "Manually verify findings and trigger credential rotation.",
        "instructions": "Review the Python file access rows; rotate any AWS credentials, SSH keys, or browser-stored passwords that the RAT touched."
      },
      "parents": [
        {
          "id": "evaluate-threat",
          "branch": "default"
        },
        {
          "id": "evaluate-threat",
          "branch": "on_unavailable"
        },
        {
          "id": "isolate-workstation"
        }
      ]
    },
    {
      "id": "close-out-hunt",
      "type": "task",
      "label": "Close out hunt",
      "config": {
        "assignee": "analyst",
        "description": "Document findings and update protection profile.",
        "instructions": "Record the hunt results. If malicious activity was confirmed, provide the Mapbox feature IDs to the detection engineering team for permanent blocking."
      },
      "parents": [
        {
          "id": "evaluate-threat",
          "branch": "on_refutes"
        },
        {
          "id": "remediation-tasks"
        }
      ]
    }
  ]
}