Credential Hunting
When the privilege/token/group/ACL checks don’t produce a primitive, hunt for credentials someone left on disk. A password for a local admin, a domain account, or a service sitting in a config file, a script, a history file, or a note turns “I can read files” into a higher-privileged context - or a domain foothold. This is the lowest-value, highest-effort lookup, so it comes last; but re-run it after every escalation, because SYSTEM can read files your foothold user couldn’t.
# Config files - recursive string huntfindstr /SIM /C:"password" *.txt *.ini *.cfg *.config *.xmlGet-ChildItem C:\ -Recurse -Include *.config,*.xml,*.ini,*.rdp,*.vnc,*.cred -EA Ignore
# High-value fixed locationsgc (Get-PSReadLineOption).HistorySavePath # PowerShell historytype C:\Windows\Panther\unattend.xml # install answer filegc 'C:\Users\*\AppData\Local\Google\Chrome\User Data\Default\Custom Dictionary.txt'
# DPAPI-protected PowerShell credential (if running AS that user)$c = Import-Clixml C:\scripts\pass.xml; $c.GetNetworkCredential().Password
# Network shares, at scale.\Snaffler.exe -s -o snaffler.log # crawls shares for *.kdbx, *.ppk, passwords.*Success indicator: a recovered cleartext password (or crackable hash / private key) you can reuse for a higher-privileged local or domain account - confirm with runas, WinRM, or an authenticated service logon.
When this applies
Section titled “When this applies”Credential hunting is the fallback, not the opener - a full file-system sweep is hours of work and the lowest hit-rate step in the loop (see the overview’s operational sequence). Reach for it when:
- Token privileges, group memberships, missing patches, and service/ACL audits have all come up empty.
- You’ve just escalated and should re-sweep: SYSTEM or a new admin context can read profile paths, registry hives, and share folders your previous user couldn’t. Always recheck PowerShell history and user profiles after gaining local admin.
- You have a domain foothold and want to pivot: a password on a share or in a script is frequently the path from local access to a domain account.
Config files
Section titled “Config files”Against best practice, applications routinely store passwords in cleartext config files. findstr is the workhorse for searching file contents recursively:
findstr /SIM /C:"password" *.txt *.ini *.cfg *.config *.xml/Srecurse subdirectories ·/Icase-insensitive ·/Mprint only the filename ·/C:"..."literal search string.- Drop
/Mto see the matching line (findstr /SI "password" *.config), add/Nfor line numbers,/Pto skip binary files.
IIS stores credentials (connection strings, app-pool identities) in web.config. The default site’s is at C:\inetpub\wwwroot\web.config, but there are often several across sites and application directories:
Get-ChildItem C:\ -Recurse -Filter web.config -EA Ignore | Select FullNamewhere.exe /R C:\ web.config # where.exe, not `where` - that's the Where-Object alias in PSTo search for a file by name regardless of contents:
dir /s /b confidential.txtGet-ChildItem -Path C:\ -Recurse -Filter "confidential.txt" -ErrorAction SilentlyContinueFile-system and extension sweeps
Section titled “File-system and extension sweeps”The two orthogonal sweeps - by content and by extension - between them catch most at-rest secrets. By content:
:: match + show the linefindstr /si password *.xml *.ini *.txt *.config:: every file, with line numbers (/p skips binaries)findstr /spin "password" *.*Select-String -Path C:\Users\*\Documents\*.txt -Pattern passwordBy extension - the names that tend to hold secrets:
dir /S /B *pass*.txt == *pass*.xml == *pass*.ini == *cred* == *vnc* == *.configGet-ChildItem C:\ -Recurse -Include *.rdp,*.config,*.vnc,*.cred,*.kdbx,*.ppk -ErrorAction IgnoreHigh-value fixed locations
Section titled “High-value fixed locations”Some stashes are predictable enough to check directly rather than sweep for.
PowerShell history
Section titled “PowerShell history”Since PowerShell 5.0 (Windows 10+), PSReadLine logs command history to a per-user file. Commands that pass credentials on the command line (net use, wevtutil ... /u: /p:, scripted logons) end up recorded in cleartext:
(Get-PSReadLineOption).HistorySavePath# C:\Users\<user>\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txtgc (Get-PSReadLineOption).HistorySavePathOnce you’re local admin, sweep every user’s history at once (assumes the default path):
foreach($u in (ls C:\users).fullname){ cat "$u\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt" -EA SilentlyContinue}Unattended-install answer files
Section titled “Unattended-install answer files”unattend.xml / sysprep.xml / autounattend.xml can carry an AutoLogon password or extra-account credentials, stored plaintext or base64. They should be deleted after imaging, but copies linger in C:\Windows\Panther\, C:\Windows\System32\Sysprep\, and ad-hoc image-build folders:
<AutoLogon> <Password><Value>local_4dmin_p@ss</Value><PlainText>true</PlainText></Password> <Enabled>true</Enabled><Username>Administrator</Username></AutoLogon>A <PlainText>false</PlainText> value is only base64, not encryption - decode it.
DPAPI-protected PowerShell credentials
Section titled “DPAPI-protected PowerShell credentials”Admins store “encrypted” credentials for scripts with Get-Credential | Export-Clixml. The protection is DPAPI - the blob decrypts only as the same user on the same machine. So if you already have code execution as that user, reversing it is trivial:
$c = Import-Clixml -Path 'C:\scripts\pass.xml'$c.GetNetworkCredential().UserName$c.GetNetworkCredential().Password # Str0ng3ncryptedP@ss!If you find the .xml but aren’t that user, you can’t just import it - you’d need the user’s DPAPI masterkey (recoverable as SYSTEM, or with the domain DPAPI backup key) via mimikatz dpapi:: or SharpDPAPI. Treat the file as a lead even when the direct import fails.
Browser dictionary files
Section titled “Browser dictionary files”Users add words their spell-checker flags to a custom dictionary - and people type passwords into fields that get spell-checked. Chrome’s is plaintext:
gc 'C:\Users\<user>\AppData\Local\Google\Chrome\User Data\Default\Custom Dictionary.txt' | Select-String -Pattern '!|@|[0-9]'Sticky Notes
Section titled “Sticky Notes”The Windows Sticky Notes app is a SQLite database, not a text file, so people treat it as a scratchpad for passwords without realizing it persists. It lives at:
C:\Users\<user>\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\plum.sqliteCopy the three plum.sqlite* files (.sqlite, -shm, -wal) off and read the Text column of the Note table - the -wal write-ahead log often holds notes not yet merged into the main DB:
Import-Module .\PSSQLite.psd1Invoke-SqliteQuery -Database .\plum.sqlite -Query "SELECT Text FROM Note" | ft -wrap# or, quick and dirty, off the box:strings plum.sqlite-wal | findstr /i "pass root admin"Other files of interest
Section titled “Other files of interest”A grab-bag worth checking by hand - registry-hive copies yield local hashes (see Backup Operators for extracting them), logs and config dumps hold connection strings:
%WINDIR%\repair\sam %WINDIR%\repair\system %WINDIR%\System32\config\*.sav%WINDIR%\Panther\unattend.xml %WINDIR%\debug\NetSetup.log%WINDIR%\system32\CCM\logs\*.log %USERPROFILE%\ntuser.dat%SYSTEMDRIVE%\pagefile.sys C:\ProgramData\Configs\*Network shares
Section titled “Network shares”In a domain, the richest hunting ground is file shares - user home folders with loose ACLs (every Domain User can read everyone’s folder), departmental shares, backup locations. Snaffler crawls accessible shares and flags interesting files by extension and content:
.\Snaffler.exe -s -o snaffler.log # -s console output, -o log fileIt surfaces .kdbx (KeePass), .ppk (PuTTY key), .vmdk/.vhdx (virtual disks you can mount for the local SAM), .config, SSH private keys, and files whose names or contents look credential-bearing. A single password on a forgotten share is a common initial-access-or-escalation win.
Defense
Section titled “Defense”- Never store credentials in config files, scripts, or answer files; use a secrets manager or managed identities (gMSA) and reference secrets at runtime.
- Delete
unattend.xml/sysprepanswer files after imaging, and scrub image-build shares. AuditC:\Windows\Panther\. - Tighten share ACLs - home folders should be readable only by their owner and admins, not all Domain Users. Run Snaffler yourself to find what an attacker would.
- Disable PowerShell plaintext history for privileged automation, or keep secrets out of command lines (prompt, or read from a vault) so they never reach
ConsoleHost_history.txt. - Monitor for mass file reads of profile/AppData paths and for
findstr/Select-Stringsweeps across the file system.
Related
Section titled “Related”- Initial enumeration - flags installed password managers and profile paths that feed this hunt
- Stored credentials - extracting secrets held by apps and the OS (browsers, cmdkey, registry, wifi, KeePass cracking)
- Backup Operators - turning a recovered SAM/SYSTEM hive copy into local hashes
- SeTakeOwnership - reading a credential file whose ACL denies your user