LSA Secrets: revisiting secretsdump
When doing Windows or Active Directory security assessments, retrieving secrets stored on a compromised host constitutes a key step to move laterally within the network or increase one's privileges. The infamous secretsdump.py
script from the impacket suite is a well-known tool to extract various sensitive secrets from a machine, including user hashes, the base secret for the DPAPI encryption mechanism, service accounts cleartext credentials, and more.
As years passed, security products began to effectively detect and block the execution of this script, which led us to have a closer look at the inner workings of secretsdump and devise a new version that is currently less prone to detection.
Revisiting secretsdump
As stated in the introduction, secretsdump.py
allows retrieving specific secrets in the registry from a targeted computer, but it also allows performing DCSync operations when targeting a domain controller. This blogpost will focus only on the remote registry part, without using the recently added vssadmin approach.
Currently, the following secrets are retrieved by secretsdump.py
:
- SAM hive content: contains local user NT hashes.
- MsCache: contains domain user hashes if the registry key CachedLogonsCount is higher than zero.
- LSA secrets:
- Computer password if enrolled in an Active Directory domain.
- DPAPI local keys (dpapi_userkey and dpapi_machinekey).
- Passwords of accounts used for non-interactive services.
Let us dive into secretsdump.py
's current technical implementation:
- The
RemoteRegistry
service is checked. If its not enabled or not started, it is enabled and started. - The
bootkey
is computed by performing registry queries on theSYSTEM\CurrentControlSet\Control\Lsa\[JD|Skew1|GBG|Data]
keys. - The
SAM
andSECURITY
hives are saved insideC:\Windows\Temp
with a randomly generated name of 8 characters with the.tmp
extension. - Hives content is read using SMB and the
ADMIN$
administrative share. All keys and secrets are decrypted and displayed. - Temporary hives are deleted and the
RemoteRegistry
is reset to its initial state.
While its execution may leave forensic traces (partially described in this article), the following heuristics are easily picked up by security products, and will raise alerts:
- Interactions with the
svcctl
named pipe to perform action on services, especially theRemoteRegistry
service required by secretsdump. - Connecting to the
ADMIN$
share. - Saving base registry hives like
SAM
orSECURITY
. - Writing files to a temporary folder with a fixed size and a specific extension.
More importantly, current EDR-like products recognize and often block saving base hives.
What if only interacting with the RemoteRegistry
was enough to perform secrets extraction? This would also avoid writing anything on the disk, leaving fewer forensics traces.
There is one problem to circumvent, the SAM
and SECURITY
hives are not accessible with a Local Administrator account, SYSTEM
identity is required:
$ reg.py Administrator:Password123@172.16.203.128 query -keyName HKLM\\SAM\\SAM
Impacket v0.13.0.dev0+20250206.100953.075f2b10 - Copyright Fortra, LLC and its affiliated companies
[*] Service RemoteRegistry is in stopped state
[*] Service RemoteRegistry is disabled, enabling it
[*] Starting service RemoteRegistry
[-] DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[*] Stopping service RemoteRegistry
[*] Restoring the disabled state for service RemoteRegistry
However, as such a restriction is not applied when saving hives, there might be a way to query arbitrary keys in the same manner.
Fortunately, the Microsoft documentation is well written and the BaseRegOpenKey
method contains a dwOptions
argument that accepts a REG_OPTIONS_BACKUP_RESTORE
value. Opening a key with this intent will bypass any ACL check, therefore, allowing to dump secrets while only interacting with the svcctl
named pipe and the RemoteRegistry
service.
A pull request has been opened on the original impacket repository with a script named regsecrets.py
which implements the aforementioned method. When retrieving secrets, the following steps are performed:
- The
RemoteRegistry
service is checked. If its not enabled or not started, it is enabled and started. - The
bootkey
is computed by performing registry queries on theSYSTEM\CurrentControlSet\Control\Lsa\[JD|Skew1|GBG|Data]
keys. - Secrets are computed using registry queries only.
- The
RemoteRegistry
is reset to its initial state.
This script was executed in multiple recent engagements and successfully circumvented the detection and / or blocking actions performed by security products.
Bonus: dpapidump.py
Moreover, a script from a pull request from 2021 that was never merged was modified and added into our pull request. The original script performs the following steps:
- Connect to the WMI interface over DCOM to perform queries and retrieve encrypted secrets related to SCCM. It first connects to the RPC port mapper before connecting to another port and then connects to a high dynamic port. However, depending on the firewall configuration, the second port might not be reachable.
- Connect to the
C$
share, retrieve machine DPAPI masterkeys inWindows\System32\Microsoft\Protect\S-1-5-18\User
and credentials secrets inWindows\System32\config\systemprofile\AppData\Local\Microsoft\Credentials
. Credentials include scheduled task user and password for non-interactive tasks. - Retrieve the necessary
dpapi_userkey
if it was not provided using secretsdump. - Decrypt the retrieved secrets and print them.
- Close all connections.
If the dpapi_userkey
is provided, this script does not perform actions that have a high risk of raising security alerts. When performing post-compromise secrets collections, running in succession regsecrets.py
then dpapidump.py
while providing the dpapi_userkey
minimizes the risk of raising security alerts while enhancing the scope of recovered secrets. Amongst them, SCCM information are retrieved, including the popular Network Access Accounts credentials (NAA) if SCCM is deployed with this account.
A modified version of this script, called dpapidump.py
is included in the PR with multiple changes:
- It uses the technique described in the first part of this article to retrieve local machine DPAPI keys if not provided in the CLI.
- The collections of information related to SCCM in the WMI database has been enhanced to match those retrieved by sccmhunter.
- Various small bug fixes and code improvements.
- Disable the retrieval of the credentials file related to
virtualapp/didlogical
, this credential has always the same file name and does not contain useful information security wise.
Conclusion
In conclusion, security products should rely on generic heuristics rather than specific ones tied to public tooling. Moreover, reading the documentation and being curious often lead to interesting discoveries.
If you are curious and liked this article, you might be interested in reading more about Windows secrets extraction.