Skip to content

Implement shadow copy dumping for SAM and LSA#1064

Open
azoxlpf wants to merge 3 commits intoPennyw0rth:mainfrom
azoxlpf:feat/add-vss-sam/lsa
Open

Implement shadow copy dumping for SAM and LSA#1064
azoxlpf wants to merge 3 commits intoPennyw0rth:mainfrom
azoxlpf:feat/add-vss-sam/lsa

Conversation

@azoxlpf
Copy link
Contributor

@azoxlpf azoxlpf commented Jan 6, 2026

Description

This PR extends the shadow copy implementation. Previously, this method was only available for NTDS dumping. I have added support for dumping SAM and LSA secrets using shadow copies as well

Type of change

Insert an "x" inside the brackets for relevant items (do not delete options)

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Deprecation of feature or functionality
  • This change requires a documentation update
  • This requires a third party update (such as Impacket, Dploot, lsassy, etc)

Screenshots (if appropriate):

SAM :

1

LSA :

lsa

Checklist:

Insert an "x" inside the brackets for completed and relevant items (do not delete options)

  • I have ran Ruff against my changes (via poetry: poetry run python -m ruff check . --preview, use --fix to automatically fix what it can)
  • I have added or updated the tests/e2e_commands.txt file if necessary (new modules or features are required to be added to the e2e tests)
  • New and existing e2e tests pass locally with my changes
  • If reliant on changes of third party dependencies, such as Impacket, dploot, lsassy, etc, I have linked the relevant PRs in those projects
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (PR here: https://github.com/Pennyw0rth/NetExec-Wiki)

@NeffIsBack
Copy link
Member

Thanks for the PR, but isn't that something that should be implemented on the impacket side? That's how ntds vss is implemented as well

@azoxlpf
Copy link
Contributor Author

azoxlpf commented Jan 6, 2026

Thanks for the PR, but isn't that something that should be implemented on the impacket side? That's how ntds vss is implemented as well

This is already implemented on the impacket side. We're using RemoteOperations.createSSandDownloadWMI() which is an existing impacket method. This is the same approach as NTDS VSS which uses RemoteOperations.saveNTDS(). Both methods are from impacket's RemoteOperations class, we're just exposing them through the --sam vss and --lsa vss arguments

@NeffIsBack
Copy link
Member

Thanks for the PR, but isn't that something that should be implemented on the impacket side? That's how ntds vss is implemented as well

This is already implemented on the impacket side. We're using RemoteOperations.createSSandDownloadWMI() which is an existing impacket method. This is the same approach as NTDS VSS which uses RemoteOperations.saveNTDS(). Both methods are from impacket's RemoteOperations class, we're just exposing them through the --sam vss and --lsa vss arguments

Got it okay! The code can probably be a bit more deduplicated tho.

@NeffIsBack NeffIsBack added the enhancement New feature or request label Jan 9, 2026
Comment on lines 1981 to 1986
SAM = SAMHashes(sam_path, bootkey, isRemote=False, perSecretCallback=lambda secret: add_sam_hash(secret, host_id))
self.output_filename = self.output_file_template.format(output_folder="sam")
SAM.dump()
SAM.export(self.output_filename)
self.logger.success(f"Added {highlight(add_sam_hash.sam_hashes)} SAM hashes to the database")
SAM.finish()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks redundant to the code of the other methods. Without having access to a proper IDE I can't verify it, but could we move that out of the condition and group it with the others?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve applied the refactor: the shared logic (dump, export, success message, finish) is no longer inside each branch. Instead, it's now consolidated into a single if SAM: / if LSA: block after the vss vs regdump/secdump branches. I don’t see a cleaner way to do it. Does that sound good to you ?

Comment on lines 2304 to 2311
LSA = LSASecrets(security_path, bootkey, None, isRemote=False, perSecretCallback=lambda secret_type, secret: add_lsa_secret(secret))
self.output_filename = self.output_file_template.format(output_folder="lsa")
LSA.dumpCachedHashes()
LSA.exportCached(self.output_filename)
LSA.dumpSecrets()
LSA.exportSecrets(self.output_filename)
self.logger.success(f"Dumped {highlight(add_lsa_secret.secrets)} LSA secrets to {self.output_filename + '.secrets'} and {self.output_filename + '.cached'}")
LSA.finish()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants