<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: performing-campaign-tracking
description: >-
  Track adversary campaigns across time using the Diamond Model, cluster
  infrastructure and TTPs, maintain campaign timelines, and produce finished
  intelligence linking intrusion sets to threat actors.
domain: cybersecurity
subdomain: threat-intelligence
tags:
  - campaign-tracking
  - diamond-model
  - intrusion-sets
  - infrastructure-clustering
  - timeline-analysis
  - attribution
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: []
---
# Performing Campaign Tracking

## Overview

Campaign tracking maps adversary operations across time, linking disparate
intrusions through shared infrastructure, TTPs, and tooling. This skill covers
applying the Diamond Model for event analysis, clustering infrastructure via
passive DNS and WHOIS patterns, building campaign timelines, and producing
finished intelligence products with confidence-rated attribution.

## Prerequisites

| Requirement | Details |
|---|---|
| Python 3.10+ with `stix2`, `requests`, `pymisp`, `pycti` libraries | Required |
| OpenCTI or MISP for campaign entity management | Required |
| Passive DNS access (SecurityTrails, DNSDB) | Required |
| MITRE ATT&CK data for TTP correlation | Required |
| Timeline visualization tool (Timesketch or custom) | Required |

## Key Concepts

### Diamond Model of Intrusion Analysis

```
          Adversary
           /    \
    Capability    Infrastructure
           \    /
           Victim
```

**Meta-features**: timestamp, phase, result, direction, methodology, resources

Each intrusion event maps to all four vertices. Campaign boundaries emerge
from clustering events that share adversary, infrastructure, or capability
features across multiple victims.

### Campaign Boundary Detection

Indicators of campaign boundary:
- Shift in tooling or TTP methodology
- Infrastructure rotation to new registrar/ASN
- Change in victimology (sector, geography)
- Temporal gap exceeding actor's operational tempo
- New C2 protocol or encryption scheme

### Attribution Confidence Ladder

```
1. Shared IOCs         → LOW (IOCs can be false-flagged)
2. Shared TTPs         → LOW-MODERATE (TTPs overlap across actors)
3. Shared tooling      → MODERATE (custom tools more attributive)
4. Shared infra + ops  → MODERATE-HIGH (operational patterns)
5. Convergent evidence → HIGH (multiple independent lines of evidence)
```

## Workflow

### Step 1: Cluster Intrusion Events

```python
import stix2

def create_campaign(name: str, description: str, events: list[dict]) -> dict:
    """Create STIX Campaign object linking intrusion events."""
    campaign = stix2.Campaign(
        name=name,
        description=description,
        first_seen=min(e["timestamp"] for e in events),
        last_seen=max(e["timestamp"] for e in events),
    )
    relationships = []
    for event in events:
        if event.get("indicator_id"):
            rel = stix2.Relationship(
                relationship_type="indicates",
                source_ref=event["indicator_id"],
                target_ref=campaign.id,
            )
            relationships.append(rel)
    bundle = stix2.Bundle(objects=[campaign, *relationships])
    return json.loads(bundle.serialize())
```

### Step 2: Infrastructure Clustering

```python
def cluster_infrastructure(domains: list[dict]) -> list[list[str]]:
    """Cluster domains by registrant and hosting patterns."""
    clusters: dict[str, list[str]] = {}
    for d in domains:
        key = f"{d.get('registrant', 'unknown')}|{d.get('asn', 'unknown')}"
        clusters.setdefault(key, []).append(d["domain"])
    return [domains for domains in clusters.values() if len(domains) > 1]
```

### Step 3: Timeline Construction

```python
from datetime import datetime

def build_campaign_timeline(events: list[dict]) -> list[dict]:
    """Build chronological campaign timeline."""
    sorted_events = sorted(events, key=lambda e: e.get("timestamp", ""))
    timeline = []
    for i, event in enumerate(sorted_events):
        timeline.append({
            "sequence": i + 1,
            "timestamp": event["timestamp"],
            "tactic": event.get("tactic", ""),
            "technique": event.get("technique_id", ""),
            "description": event.get("description", ""),
            "iocs": event.get("iocs", []),
            "diamond_vertex": event.get("vertex", ""),
        })
    return timeline
```

## Verification

- [ ] Intrusion events clustered by shared infrastructure and TTPs
- [ ] Diamond Model applied with all four vertices populated per event
- [ ] Campaign timeline constructed with chronological event ordering
- [ ] Infrastructure clustering reveals related domains and hosting
- [ ] Attribution assessed with confidence ladder methodology
- [ ] Campaign report produced with STIX entities in OpenCTI/MISP

## References

- [Diamond Model Paper](https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf)
- [MITRE ATT&CK Campaigns](https://attack.mitre.org/campaigns/)
- [STIX 2.1 Campaign SDO](https://docs.oasis-open.org/cti/stix/v2.1/os/stix-v2.1-os.html#_pcpvfz4ik6d6)
- [OpenCTI Campaign Management](https://docs.opencti.io/)
- [Timesketch](https://timesketch.org/)
