-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for decrypting System DPAPI secrets #305
Conversation
Added DPAPI support to Wireguard
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apologies for taking so long. I have some other thoughts for improvements as well, but if you could address some of these comments first, I'd like to make some commits directly to your branch afterwards if you don't mind!
tests/data/dpapi/master_keys/d8ef5e00-328a-4919-9ab6-c058f493a6e3
Outdated
Show resolved
Hide resolved
Going over the review now, I'm having serious thought about removing pre-vista support, mostly because I can't test it (AFAIK there is no harness for that so I would have to replicate the registry from an old version of windows). |
…riable naming convention, and other review changes
Okay, I'm done with the requested changes. |
I've pushed some suggested changes. I haven't fully read into the details of DPAPI, so let me know what you think.
Ideally we also support <Vista down the line, but I'm fine with adding that at a later stage. In some brief Googling I also saw that Win2000 requires some different structures for the master key file, so there's also that. Regarding the big changes to how you used dissect.cstruct, that mostly comes down to a bit of optimisation + magic reduction. I liked the approach though, and I've long been considering adding a native UUID type to cstruct, as well as a |
Codecov Report
@@ Coverage Diff @@
## main #305 +/- ##
==========================================
+ Coverage 73.28% 73.47% +0.18%
==========================================
Files 245 249 +4
Lines 19544 19925 +381
==========================================
+ Hits 14322 14639 +317
- Misses 5222 5286 +64
Flags with carried forward coverage won't be shown. Click here to find out more.
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've pushed a couple of lines of fixes, and added some questions as comments.
I'm going to push another commit which removes "support" for pre-vista logic
config_globs = self.os_config_globs.get(target.os, []) | ||
for path in config_globs: | ||
self.configs: list[Path] = [] | ||
for path in self.CONFIG_GLOBS: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a specific reason to attempt to read all files, instead of just the relevant ones?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly readability and ease of expansion. Especially the Unix-y based paths would quickly get hairy and easy to forget when adding new operating system support to Dissect (e.g. BSD). It's a small amount of paths so I feel it's okay to "bruteforce" it.
|
||
self.blob = self._blob.blob | ||
# All the blob data between the version, provider and sign fields | ||
self.blob = data[20 : -(self._blob.signLength + 4)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm slightly worried about this . It's basically hardcoded magic values which (theoretically but super unlikely) could change.
I don't think that it will ever change, so if you prefer this as opposed to another solution, that's fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made it more dynamic, does that satisfy? I intend to add a offsetof
function to cstruct to make this easier/more concise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cobyge once again thank you very much for this contribution, and my sincere apologies for the time it has taken. This is one of the best contributions we've gotten so far, and I'm excited to see what you'll bring next 😄 |
Co-authored-by: Schamper <1254028+Schamper@users.noreply.github.com>
Co-authored-by: Schamper <1254028+Schamper@users.noreply.github.com>
Closes #274 .
This PR adds support for decrypting system DPAPI secrets.
I have also added support for decrypting Wireguard configuration from DPAPI (As an example).
Questions I have:
System
user. Any other user would require either a password, or a Domain Backup Key. I'm not sure what the right way to accept those would be (Especially since I assume most of the time we don't have the plaintext password, and accepting a different target to extract the Backup Key from (the DC) would be odd). I would like to hear any thoughts about this.decrypt_dpapi_system_blob(blob: bytes)
good enough? Should there be a different API? See the Wireguard code for an example usageI'd love to get some feedback on the code, as most of the work I did was the research into DPAPI itself, and I'm not 100% sure that the way I implemented the module inside of Dissect was the correct way.