{
  "hunt": {
    "meta": {
      "tlp": "clear",
      "hunt": {
        "handoff": "promote-to-detection",
        "trigger": "intel-report",
        "methodology": "model-assisted",
        "applicability": "campaign-specific",
        "justification": "The AD RMS SLC private key is the master root for all protected documents in a deployment. Because it cannot be rotated and remains valid for 255 years, its compromise is a permanent failure of data confidentiality."
      },
      "name": "AD RMS Master Key Extraction and Offline Decryption",
      "type": "investigation",
      "labels": [
        "hunt",
        "attack.t1003.001",
        "attack.t1082",
        "attack.t1083",
        "attack.t1190",
        "attack.t1005"
      ],
      "related": [
        {
          "hunt": "ad-rms-client-side-bypass",
          "reason": "This hunt focuses on root key theft and global decryption, whereas client-side bypasses focus on individual document policy stripping by authorized users.",
          "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"
        },
        "endpoint": {
          "name": "Endpoint telemetry (hb_ surfaces)",
          "category": "endpoint",
          "telemetry": [
            "endpoint"
          ]
        }
      },
      "analysis": "Detecting the SOAP call alone is noisy. This hunt is required to correlate administrative server activity with rare process-level baseline execution to find the specific, unauthorized document access that follows key theft.",
      "coverage": [
        {
          "stage": "initial-access-exploitation",
          "steps": [
            "soap-export-activity"
          ],
          "status": "covered"
        },
        {
          "stage": "rms-configuration-discovery",
          "steps": [
            "discovery-activity"
          ],
          "status": "covered"
        },
        {
          "stage": "slc-private-key-extraction",
          "steps": [
            "assess-extraction"
          ],
          "status": "covered"
        },
        {
          "stage": "recon-rms-protected-content",
          "reason": "Identifying OLE magic bytes or internal stream names requires deep file inspection not present in hb_file_activity.",
          "status": "not_visible",
          "blind_spot": "file-magic-bytes-visibility"
        },
        {
          "stage": "offline-unauthorized-decryption",
          "steps": [
            "unauthorized-decryption-activity",
            "confirm-impact"
          ],
          "status": "covered"
        }
      ],
      "scenario": {
        "stages": [
          {
            "name": "Exploitation of AD RMS Service",
            "slug": "initial-access-exploitation",
            "tactic": "initial-access",
            "techniques": [
              "T1190"
            ],
            "observables": [
              "SOAP calls to VESUVIO admin endpoints",
              "Targeting AD RMS Service Group identities: tony.soprano"
            ]
          },
          {
            "name": "AD RMS Key and Database Discovery",
            "slug": "rms-configuration-discovery",
            "tactic": "discovery",
            "techniques": [
              "T1082"
            ],
            "observables": [
              "SharpRMS tool execution",
              "Querying keyprotection admin operation",
              "Response containing IsServicePrivateKeySoftwareBased: true",
              "DatabaseConnectionString targeting data source=BARONE"
            ]
          },
          {
            "name": "SLC Private Key Extraction via TPD Export",
            "slug": "slc-private-key-extraction",
            "tactic": "credential-access",
            "techniques": [
              "T1003.001"
            ],
            "observables": [
              "Authenticated SOAP call to Trusted Publishing Domain (TPD) export endpoint",
              "Extraction of 1172-byte SLC private key material",
              "Integrated Security=SSPI authentication to SQL server BARONE"
            ]
          },
          {
            "name": "Identification of RMS Protected Documents",
            "slug": "recon-rms-protected-content",
            "tactic": "discovery",
            "techniques": [
              "T1083"
            ],
            "observables": [
              "Searching for files starting with OLE magic bytes D0-CF-11-E0-A1-B1-1A-E1",
              "Identifying OLE streams named Primary and EncryptedPackage",
              "Targeting files like BOARD_MINUTES_2026.docx"
            ]
          },
          {
            "name": "Offline Document Decryption",
            "slug": "offline-unauthorized-decryption",
            "tactic": "collection",
            "techniques": [
              "T1005"
            ],
            "observables": [
              "Use of SharpRMS for offline decryption using extracted SLC key",
              "Accessing protected .docx files by non-authorized users like paulie.gualtieri"
            ]
          }
        ],
        "summary": "An attacker with AD RMS Service Group membership identifies protected assets and extracts the long-lived, unrotatable Server Licensor Certificate (SLC) private key via a Trusted Publishing Domain (TPD) export operation. This key acts as a master key for the entire deployment, allowing for permanent offline decryption of every document ever protected by the cluster, even after the infrastructure is rebuilt."
      },
      "severity": "high",
      "rationale": "Scope first to AD RMS servers using the software inventory. Use the resulting hostnames to populate the scope_hosts parameter, which narrows the HTTP and process searches to the most relevant infrastructure.",
      "guardrails": {
        "claims": "no_unsupported",
        "evidence": "citation_required",
        "telemetry": "untrusted",
        "missing_data": "not_benign"
      },
      "hypothesis": "An intruder has extracted the AD RMS Server Licensor Certificate (SLC) private key through a Trusted Publishing Domain export and is using it to decrypt protected documents offline.",
      "parameters": {
        "scope_hosts": {
          "type": "list[host]",
          "default": [],
          "description": "Specific hosts identified in the scoping step to narrow the hunt."
        },
        "lookback_days": {
          "type": "number",
          "default": "14",
          "description": "Days of history to examine."
        },
        "rms_admin_paths": {
          "type": "list[path]",
          "default": [
            "/wmcs/admin/server.asmx",
            "/wmcs/admin/trustpolicy.asmx"
          ],
          "description": "AD RMS admin SOAP endpoints used for TPD export."
        }
      },
      "provenance": {
        "authors": [
          {
            "org": "huntbase.io",
            "name": "Huntbase hunt generation"
          }
        ],
        "generated": {
          "by": "huntbase-hunt-generation",
          "from": "https://www.huntress.com/blog/ad-rms-slc-encryption-key",
          "gates": [
            "dry-run",
            "lint"
          ],
          "model": "hb_google/gemini-3-flash-preview"
        }
      },
      "references": [
        {
          "url": "https://www.huntress.com/blog/ad-rms-slc-encryption-key",
          "name": "Huntress \u2014 AD RMS SLC Encryption Key"
        }
      ],
      "blind_spots": [
        {
          "id": "no-endpoint-telemetry",
          "risk": "The SLC key allows for offline decryption. If the attacker moves the stolen documents and key to a personal or unmanaged machine, process telemetry will not see the decryption impact.",
          "stage": "offline-unauthorized-decryption",
          "question": "Was SharpRMS run on a non-enrolled device?",
          "requires": "universal endpoint coverage"
        },
        {
          "id": "file-magic-bytes-visibility",
          "risk": "We cannot see the attacker sweeping shares for the D0-CF-11-E0 magic bytes via standard file activity logs, making the recon stage a blind spot.",
          "stage": "recon-rms-protected-content",
          "question": "Which files were identified as RMS-protected through byte-level scanning?",
          "requires": "deep file inspection or EDR file-header logging"
        }
      ]
    },
    "name": "AD RMS Master Key Extraction and Offline Decryption",
    "description": "This hunt identifies the extraction of the AD RMS root key (SLC) and subsequent unauthorized document decryption. The Server Licensor Certificate is a long-lived root of trust that allows for the permanent, offline decryption of any document protected by that cluster. The flow identifies AD RMS servers, detects administrative discovery and SOAP-based TPD export calls, and then baselines rare decryption-related process activity to identify unauthorized data access across the fleet."
  },
  "nodes": [
    {
      "id": "hypothesis",
      "type": "hypothesis",
      "label": "Hypothesis",
      "config": {
        "tags": [],
        "coverage": [
          {
            "stage": "initial-access-exploitation",
            "steps": [
              "soap-export-activity"
            ],
            "status": "covered"
          },
          {
            "stage": "rms-configuration-discovery",
            "steps": [
              "discovery-activity"
            ],
            "status": "covered"
          },
          {
            "stage": "slc-private-key-extraction",
            "steps": [
              "assess-extraction"
            ],
            "status": "covered"
          },
          {
            "stage": "recon-rms-protected-content",
            "reason": "Identifying OLE magic bytes or internal stream names requires deep file inspection not present in hb_file_activity.",
            "status": "not_visible",
            "blind_spot": "file-magic-bytes-visibility"
          },
          {
            "stage": "offline-unauthorized-decryption",
            "steps": [
              "unauthorized-decryption-activity",
              "confirm-impact"
            ],
            "status": "covered"
          }
        ],
        "rationale": "An intruder has extracted the AD RMS Server Licensor Certificate (SLC) private key through a Trusted Publishing Domain export and is using it to decrypt protected documents offline.",
        "blind_spots": [
          {
            "id": "no-endpoint-telemetry",
            "risk": "The SLC key allows for offline decryption. If the attacker moves the stolen documents and key to a personal or unmanaged machine, process telemetry will not see the decryption impact.",
            "stage": "offline-unauthorized-decryption",
            "question": "Was SharpRMS run on a non-enrolled device?",
            "requires": "universal endpoint coverage"
          },
          {
            "id": "file-magic-bytes-visibility",
            "risk": "We cannot see the attacker sweeping shares for the D0-CF-11-E0 magic bytes via standard file activity logs, making the recon stage a blind spot.",
            "stage": "recon-rms-protected-content",
            "question": "Which files were identified as RMS-protected through byte-level scanning?",
            "requires": "deep file inspection or EDR file-header logging"
          }
        ],
        "scoping_notes": "Scope first to AD RMS servers using the software inventory. Use the resulting hostnames to populate the scope_hosts parameter, which narrows the HTTP and process searches to the most relevant infrastructure.",
        "beyond_detection": "Detecting the SOAP call alone is noisy. This hunt is required to correlate administrative server activity with rare process-level baseline execution to find the specific, unauthorized document access that follows key theft."
      }
    },
    {
      "id": "identify-rms-servers",
      "type": "query",
      "label": "Identify AD RMS Servers",
      "config": {
        "dsl": "sqlite",
        "role": "scoping",
        "source": "endpoint",
        "content": "SELECT DISTINCT device_hostname FROM hb_software_inventory WHERE (LOWER(package_name) LIKE '%rights management%' OR LOWER(vendor_name) LIKE '%microsoft%rms%')",
        "surface": "hb_software_inventory",
        "description": "Find hosts with AD RMS software installed to narrow the search for administrative activity.",
        "expected_signal": "A list of hostnames running AD RMS components. Silence means no AD RMS installations were found in the current inventory."
      },
      "parents": [
        {
          "id": "hypothesis"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "scoping",
        "label": "Identify AD RMS Servers",
        "reads": [
          "package_name",
          "vendor_name",
          "device_hostname"
        ],
        "source": "hb_software_inventory",
        "target": "endpoint",
        "content": "SELECT DISTINCT device_hostname FROM hb_software_inventory WHERE (LOWER(package_name) LIKE '%rights management%' OR LOWER(vendor_name) LIKE '%microsoft%rms%')",
        "silence": "not_evidence_of_absence",
        "expected": "A list of hostnames running AD RMS components. Silence means no AD RMS installations were found in the current inventory.",
        "verified": "dry-run",
        "verified_at": "2026-09-20"
      }
    },
    {
      "id": "soap-export-activity",
      "type": "query",
      "label": "TPD Export SOAP Activity",
      "config": {
        "dsl": "sqlite",
        "role": "triage",
        "source": "web",
        "content": "SELECT device_hostname, url_path, actor_user_name, src_endpoint_ip, time FROM hb_http_activity WHERE (('{{scope_hosts}}' = '') OR (instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0)) AND instr(',' || '{{rms_admin_paths}}' || ',', ',' || LOWER(url_path) || ',') > 0 AND (status_code = 200 OR status_code = '200') AND time >= datetime('now', '-{{lookback_days}} days')",
        "surface": "hb_http_activity",
        "description": "Detect successful HTTP requests to the AD RMS Trusted Publishing Domain export endpoints.",
        "expected_signal": "Successful 200 OK responses to AD RMS admin paths. Silence proves no successful TPD exports were observed in this window."
      },
      "parents": [
        {
          "id": "identify-rms-servers"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "triage",
        "label": "TPD Export SOAP Activity",
        "reads": [
          "url_path",
          "device_hostname",
          "actor_user_name",
          "status_code",
          "time"
        ],
        "source": "hb_http_activity",
        "target": "web",
        "content": "SELECT device_hostname, url_path, actor_user_name, src_endpoint_ip, time FROM hb_http_activity WHERE (('{{scope_hosts}}' = '') OR (instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0)) AND instr(',' || '{{rms_admin_paths}}' || ',', ',' || LOWER(url_path) || ',') > 0 AND (status_code = 200 OR status_code = '200') AND time >= datetime('now', '-{{lookback_days}} days')",
        "silence": "not_evidence_of_absence",
        "expected": "Successful 200 OK responses to AD RMS admin paths. Silence proves no successful TPD exports were observed in this window.",
        "verified": "dry-run",
        "verified_at": "2026-09-20"
      }
    },
    {
      "id": "discovery-activity",
      "type": "query",
      "label": "AD RMS Configuration Discovery",
      "config": {
        "dsl": "sqlite",
        "role": "detection-candidate",
        "source": "endpoint",
        "content": "SELECT device_hostname, process_cmd_line, user_name, time FROM hb_process_activity WHERE (('{{scope_hosts}}' = '') OR (instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0)) AND (LOWER(process_cmd_line) LIKE '%sharperms%' OR LOWER(process_cmd_line) LIKE '%keyprotection%') AND time >= datetime('now', '-{{lookback_days}} days')",
        "surface": "hb_process_activity",
        "description": "Identify process execution related to SharpRMS or the keyprotection command used to verify if the key is software-based.",
        "expected_signal": "Command lines explicitly referencing AD RMS discovery tools or operations. Silence suggests no such discovery tools were launched on the managed estate."
      },
      "parents": [
        {
          "id": "identify-rms-servers"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "detection-candidate",
        "label": "AD RMS Configuration Discovery",
        "reads": [
          "process_cmd_line",
          "user_name",
          "device_hostname",
          "time"
        ],
        "source": "hb_process_activity",
        "target": "endpoint",
        "content": "SELECT device_hostname, process_cmd_line, user_name, time FROM hb_process_activity WHERE (('{{scope_hosts}}' = '') OR (instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0)) AND (LOWER(process_cmd_line) LIKE '%sharperms%' OR LOWER(process_cmd_line) LIKE '%keyprotection%') AND time >= datetime('now', '-{{lookback_days}} days')",
        "silence": "not_evidence_of_absence",
        "expected": "Command lines explicitly referencing AD RMS discovery tools or operations. Silence suggests no such discovery tools were launched on the managed estate.",
        "verified": "dry-run",
        "verified_at": "2026-09-20"
      }
    },
    {
      "id": "assess-extraction",
      "type": "analytic",
      "label": "Assess Key Extraction Attempt",
      "config": {
        "cite": "required",
        "tools": [
          "endpoint",
          "web"
        ],
        "context": [
          "soap-export-activity",
          "discovery-activity"
        ],
        "objective": "Determine if the SOAP activity and discovery command lines together indicate a successful SLC key extraction by a Service Group member.",
        "description": "Correlate administrative SOAP activity with process-level discovery to determine if the SLC key was targeted.",
        "max_iterations": 4,
        "expected_signal": "A list of hosts where SLC key extraction is suspected based on discovery and SOAP export calls.",
        "success_criteria": "A per-host verdict of malicious, suspicious, or benign citing the relevant rows."
      },
      "parents": [
        {
          "id": "soap-export-activity",
          "kind": "merge"
        },
        {
          "id": "discovery-activity",
          "kind": "merge"
        }
      ]
    },
    {
      "id": "unauthorized-decryption-activity",
      "type": "query",
      "label": "Unauthorized Decryption Activity",
      "config": {
        "dsl": "sqlite",
        "role": "baseline",
        "source": "endpoint",
        "content": "SELECT process_cmd_line, device_hostname, user_name, MIN(time) AS first_seen, COUNT(*) AS execution_count FROM hb_process_activity WHERE (LOWER(process_cmd_line) LIKE '%--decrypt%' OR LOWER(process_cmd_line) LIKE '%--slc%') AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY process_cmd_line, device_hostname, user_name HAVING COUNT(DISTINCT device_hostname) <= 3",
        "surface": "hb_process_activity",
        "description": "Baseline rare decryption activity across the fleet to identify the impact of the stolen SLC key.",
        "expected_signal": "Process command lines indicating offline decryption on hosts where the user is not a service administrator. Silence confirms no unauthorized decryption tools were detected."
      },
      "parents": [
        {
          "id": "assess-extraction"
        }
      ],
      "primitive_config": {
        "dsl": "sqlite",
        "role": "baseline",
        "label": "Unauthorized Decryption Activity",
        "reads": [
          "process_cmd_line",
          "device_hostname",
          "user_name",
          "time"
        ],
        "source": "hb_process_activity",
        "target": "endpoint",
        "content": "SELECT process_cmd_line, device_hostname, user_name, MIN(time) AS first_seen, COUNT(*) AS execution_count FROM hb_process_activity WHERE (LOWER(process_cmd_line) LIKE '%--decrypt%' OR LOWER(process_cmd_line) LIKE '%--slc%') AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY process_cmd_line, device_hostname, user_name HAVING COUNT(DISTINCT device_hostname) <= 3",
        "silence": "not_evidence_of_absence",
        "baseline": {
          "window": "{{lookback_days}}d",
          "compare": "first_seen"
        },
        "expected": "Process command lines indicating offline decryption on hosts where the user is not a service administrator. Silence confirms no unauthorized decryption tools were detected.",
        "verified": "dry-run",
        "prevalence": {
          "by": "device_hostname",
          "key": [
            "process_cmd_line"
          ],
          "rare_below": 3
        },
        "verified_at": "2026-09-20"
      }
    },
    {
      "id": "confirm-impact",
      "type": "analytic",
      "label": "Confirm Unauthorized Impact",
      "config": {
        "cite": "required",
        "tools": [
          "endpoint",
          "web"
        ],
        "context": [
          "assess-extraction",
          "unauthorized-decryption-activity"
        ],
        "objective": "Verify if the rare decryption events correlate with the previously identified stolen key extraction to confirm a data breach.",
        "description": "Link the earlier extraction verdict to the observed decryption activity to confirm data compromise.",
        "max_iterations": 4,
        "expected_signal": "A confirmed link between a stolen key and unauthorized document access.",
        "success_criteria": "A final malicious verdict for any host where a stolen key was used for decryption."
      },
      "parents": [
        {
          "id": "unauthorized-decryption-activity"
        }
      ]
    },
    {
      "id": "route-on-impact",
      "type": "checkpoint",
      "label": "Route on Impact",
      "config": {
        "fuzzy": true,
        "judge": "hunter",
        "question": "the confirm-impact verdict is malicious for at least one host involving stolen SLC keys",
        "condition": "the confirm-impact verdict is malicious for at least one host involving stolen SLC keys",
        "blind_spot": "no-endpoint-telemetry",
        "confidence": "high",
        "description": "Direct the response based on the agent's impact confirmation.",
        "checkpoint_type": "mandatory"
      },
      "parents": [
        {
          "id": "confirm-impact"
        }
      ]
    },
    {
      "id": "isolate-beachhead",
      "type": "action",
      "label": "Isolate Beachhead",
      "config": {
        "target": "endpoint",
        "description": "Prevent further document decryption by isolating the compromised host.",
        "instructions": "Isolate the host where decryption was observed and disable the AD RMS Service Group account. Since the SLC key is unrotatable, notify the data protection team that all previously protected content must be considered exposed.",
        "action_approval": "required"
      },
      "parents": [
        {
          "id": "route-on-impact",
          "branch": "on_supports"
        }
      ]
    },
    {
      "id": "document-exposure",
      "type": "task",
      "label": "Analyze Document Exposure",
      "config": {
        "assignee": "analyst",
        "description": "Review file activity to determine which sensitive documents were targeted by the intruder.",
        "instructions": "Review hb_file_activity for the host and time window identified. Look for access to .docx or .xlsx files by the process identified in unauthorized-decryption-activity. Identify which sensitive shares were swept for OLE magic bytes."
      },
      "parents": [
        {
          "id": "route-on-impact",
          "branch": "default"
        },
        {
          "id": "route-on-impact",
          "branch": "on_unavailable"
        },
        {
          "id": "isolate-beachhead"
        }
      ]
    },
    {
      "id": "close-out",
      "type": "task",
      "label": "Close Out",
      "config": {
        "assignee": "analyst",
        "description": "Finalize the hunt and record telemetry gaps.",
        "instructions": "Record the results of the hunt. If no activity was found, document that the HTTP and process telemetry confirmed the integrity of the AD RMS root key for this window."
      },
      "parents": [
        {
          "id": "route-on-impact",
          "branch": "on_refutes"
        },
        {
          "id": "document-exposure"
        }
      ]
    }
  ]
}