Add credential manager dump feature to winrm protocol
Description
This is a winrm module designed to find and unlock Credential Manager masterkeys and credentials owned by the connecting user. In a situation where smb's --dpapi cannot work due to the lack of access to the C$ share, and where a user has remote management privileges, the module automates the discovery and offline decryption of these files.
The flow is inspired by and a simplified version of dploot's triage methods for user masterkeys and credentials. Actual decryption of keys and credentials is taken and adapted from impacket-dpapi.
This is my first contribution to the project (aside from a small bugfix earlier, found in the process of writing this!), and I would appreciate any feedback :)
I'll work on the corresponding documentation on the wiki in the meantime.
Type of change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [x] This change requires a documentation update
- [ ] This requires a third party update (such as Impacket, Dploot, lsassy, etc)
Setup guide for the review
The target must have a user who is allowed to connect via WinRM, and this user should have saved credentials in Credential Manager.
There is an active HTB machine where this is easily demonstrable. There might be retired machines that allow the same, I'll research this and add as a comment below.
Screenshots:
Here's the module working on said active HTB machine:
Checklist:
- [x] I have ran Ruff against my changes (via poetry:
poetry run python -m ruff check . --preview, use--fixto automatically fix what it can) - [x] I have added or updated the tests/e2e_commands.txt file if necessary
- [ ] 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
- [x] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation (PR here: https://github.com/Pennyw0rth/NetExec-Wiki/pull/60)
Interesting one, thanks for the PR! I'll take a look at this as soon as i worked on the pile of PRs that has been stacking up the past months
New modules need to be added to the e2e tests
New modules need to be added to the e2e tests
Thanks, I've now added this and took the liberty to add a line for aws-credentials, the only other winrm module currently.
It is unclear to me however what the expectation regarding running the e2e tests is. Is there an image to spin up and test against that we can use?
Thanks, I've now added this and took the liberty to add a line for aws-credentials, the only other winrm module currently.
Nice, thanks!
It is unclear to me however what the expectation regarding running the e2e tests is. Is there an image to spin up and test against that we can use?
The expectation from the check is that you run the e2e tests against your target machine so you can check if you broke something with your changes, but I think @Marshall-Hallenbeck opinion and mine are split on this one.
For me it is fine if you just test your own module and make sure it works, especially as a new module won't have any impact on the rest of the code base in 99% of the time. Testing the rest of the code base is something i usually only do if there are major changes in the core of the project
New modules need to be added to the e2e tests
Thanks, I've now added this and took the liberty to add a line for aws-credentials, the only other winrm module currently.
It is unclear to me however what the expectation regarding running the e2e tests is. Is there an image to spin up and test against that we can use?
Thanks!
If you are just adding a single module then you don't have to worry about e2e tests - they're there for changes that affect large portions of the code base.
why not as a core feature of winrm ? like nxc winrm ip -u user -p pass --dpapi ?
why not as a core feature of winrm ? like n
xc winrm ip -u user -p pass --dpapi?
If you guys think that'd be best I'll make the appropriate changes. It was in fact the first question I had :) The idea that I got from Discord was essentially that "if we use it all the time, it's a core feature; if more niche, it's a module", and I thought this was more niche than all-the-time.
why not as a core feature of winrm ? like n
xc winrm ip -u user -p pass --dpapi?If you guys think that'd be best I'll make the appropriate changes. It was in fact the first question I had :) The idea that I got from Discord was essentially that "if we use it all the time, it's a core feature; if more niche, it's a module", and I thought this was more niche than all-the-time.
dpapi is by default on every user directory so core feature sounds like a good place to me and it will be consistent with dpapi from smb
dpapi is by default on every user directory so core feature sounds like a good place to me and it will be consistent with dpapi from smb
Alright, done!
@NeffIsBack I'm not sure how important it is but the label no longer applies, after turning this into a core feature
Currently having an issue with dploot https://github.com/zblurx/dploot/issues/37
Currently having an issue with dploot zblurx/dploot#37
Interesting, I'm not sure what it could be. Is Credential Guard enabled perhaps? I'll be watching the ticket.
Any update here ? This feature is very cool and need to be added ! 😄
Any update here ? This feature is very cool and need to be added ! 😄
Time is pretty short on my side at the moment, but i will give it a shot now.
Not sure atm what is happening here but i get a Padding error for what it looks like is the masterkey?
Perhaps indeed related to https://github.com/zblurx/dploot/issues/37, @zblurx do you know or have you seen that error?
Any update here ? This feature is very cool and need to be added ! 😄
Time is pretty short on my side at the moment, but i will give it a shot now.
Man, you are doing an amazing job, no pressure or panic aha
Hi! Great timing to bring this PR back up, thank you @qu35t-code! The HTB machine that "inspired" me (Puppy) was retired yesterday and is currently free to try.
I've just retried and it still works there, so I'm curious about the issue you've found @NeffIsBack, I'll have a look today.
For the record:
Took a short look at it, looks to me like something is going wrong with the decryption of the first credential file which then leads to a padding error when it tries to unpad random garbage.
@zblurx will take a look at it next week, as he has much more knowledge about dpapi than i do.
Took a short look at it, looks to me like something is going wrong with the decryption of the first credential file which then leads to a padding error when it tries to unpad random garbage.
@zblurx will take a look at it next week, as he has much more knowledge about dpapi than i do.
So I think the behaviour is normal, but maybe I'm missing more credential files. I got the files from Alex on discord, two masterkeys and one credential file:
I modified the code to ignore the files on the HTB machine and just pick them from their location. The diff:
The output shows the "Padding is incorrect" error when trying to decrypt the credential file with the first masterkey, but succeeding with the second:
This is an unfortunate error message from Impacket dpapi, but it seems to be the normal result when a file cannot be decrypted with a non-matching masterkey. See this write-up from 0xdf for an example (search for "Padding is incorrect"): https://0xdf.gitlab.io/2025/04/26/htb-vintage.html .
What do you think? @zblurx do you confirm that this is normal behaviour in this case?
Hey guys, sorry for the delay. So the "Padding is incorrect" error happens every time you try to decrypt a DPAPI blob (for example, Credential file) with the wrong masterkey. It's completely normal behavior, so no issue from impacket nor dploot.
In DPAPI_BLOB structure, you can find the encrypted data and some metadata regarding decryption, but also the GUID of the masterkey that you need :
The process of selecting the correct masterkey based on the GUID written in the DPAPI BLOB is automated in dploot.
For the record, after implementing the fix pointed out by @zblurx and still testing with the hard-coded files provided by @NeffIsBack , we now pick the right masterkey to open the credentials file (and avoid the padding error message as a side-effect):
In case we don't have the necessary masterkey for a given credentials file, we now get a better message: