Skip to content
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

Support DPAPI masterkeys from Windows 10 1607+ #3419

Merged
merged 5 commits into from
Oct 10, 2018

Conversation

jagotu
Copy link
Contributor

@jagotu jagotu commented Oct 5, 2018

Since Windows 10 version 1607 (build 14393), DPAPI masterkeys in a domain context use a key derived from the NTLM hash instead of directly using the NTLM hash. That resulted in John being unable to crack these newer masterkeys.

Unfortunately, it's impossible to tell whether the masterkey is in the newer or older format just by having the file. This pull request adds context number 3 to DPAPImk, which prompts John to perform the key derivation step. Also, a modified DPAPImk2john.py script is provided, which defaults to outputting both variants unless the user specifies a context of "domain1607+" or "domain1607-". It's obviously two times slower to attempt to crack with both variants, but remember that until now, John wouldn't crack these newer masterkeys at all.

@magnumripper
Copy link
Member

Cool, thanks! I'll let Dhiru review this.

@kholia
Copy link
Member

kholia commented Oct 7, 2018

I will be back on the 19th October to review this. Thanks!

CC @Fist0urs. Hey, does this look OK to you?

}

for (i = 0; i < sha256loops; i++)
{
Copy link
Member

Choose a reason for hiding this comment

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

Put the brace on the previous line itself. Applies to other places as well.

@Fist0urs
Copy link
Contributor

Fist0urs commented Oct 7, 2018

Hi!

Thank you for this PR, it looks promising!

Few questions:

  • have you checked how Windows behaves in a local context? Indeed, you wrote that on Windows 10 version 1607 in a domain context things are like that, but does this mean that local context behavior stays unchanged?
  • In your code the iteration number of sha256 is hardcoded (10k). Where does this come from? Usually the number of pbkdf2 iterations can be extracted from the DPAPI blob (at least for the other parts of the algorithm):

https://github.com/magnumripper/JohnTheRipper/blob/7b22b132a2269e098bb48971847c67aab511152f/run/DPAPImk2john.py#L369-L375

This can be explained by the fact that this iteration number will vary upon Windows versions (it can also be custom by modifying the registry). I want to make sure that this is not a particular usecase :)

Finally, the DPAPImk2john.py script also gives the ability to test passwords on provided samples.
Take a look at --password option:

https://github.com/magnumripper/JohnTheRipper/blob/7b22b132a2269e098bb48971847c67aab511152f/run/DPAPImk2john.py#L635-L636

and the corresponding try_credential function that provided the ability to decrypt stuff:

https://github.com/magnumripper/JohnTheRipper/blob/7b22b132a2269e098bb48971847c67aab511152f/run/DPAPImk2john.py#L583-L586

This would be awesome if you could add the version 3 support (ie. domain1607+) to this script.

@jagotu
Copy link
Contributor Author

jagotu commented Oct 8, 2018

@Fist0urs

  • have you checked how Windows behaves in a local context? Indeed, you wrote that on Windows 10 version 1607 in a domain context things are like that, but does this mean that local context behavior stays unchanged?

The local context remains unchanged, using the SHA-1 hash of the password directly.

  • In your code the iteration number of sha256 is hardcoded (10k). Where does this come from? Usually the number of pbkdf2 iterations can be extracted from the DPAPI blob (at least for the other parts of the algorithm):
    [...]
    This can be explained by the fact that this iteration number will vary upon Windows versions (it can also be custom by modifying the registry). I want to make sure that this is not a particular usecase :)

These values are hardcoded in dpapi.dll. It is possible that they will change in future Windows versions (mainly once this knowledge becomes more public, as the changes are just an attempt at obscurity from Microsoft and add almost no real security), but they are not dependant on the masterkey file and as such cannot be variable.

Finally, the DPAPImk2john.py script also gives the ability to test passwords on provided samples.

I will udpate the script to support this scenario.

@Fist0urs
Copy link
Contributor

Fist0urs commented Oct 8, 2018

These values are hardcoded in dpapi.dll

Could you please insert a comment in your code stating this? So that if this iteration number happens to change (very unlikely though) someone wanting to add support in the format will spot directly where things should be added :)

Edit: I could confirm that this value is hardcoded on Windows 10 version 1803 (build 17134) too

mov     r9d, 8          ; dwFlags
lea     rdx, pszAlgId   ; "SHA256"
xor     r8d, r8d        ; pszImplementation
lea     rcx, [rbp+57h+phAlgorithm] ; phAlgorithm
call    cs:__imp_BCryptOpenAlgorithmProvider
mov     ebx, eax
test    eax, eax
js      loc_18000225E
and     [rsp+0A0h+var_60], 0
lea     rcx, [rbp+57h+Dst]
movzx   eax, [rbp+57h+UnicodeString.Length]
mov     r8d, 10h        ; cbPassword
mov     r9, [rbp+57h+UnicodeString.Buffer] ; pbSalt
mov     rdx, rsi        ; pbPassword
mov     [rsp+0A0h+cbDerivedKey], 20h ; cbDerivedKey
mov     [rsp+0A0h+pbDerivedKey], rcx ; pbDerivedKey
mov     rcx, [rbp+57h+phAlgorithm] ; hPrf
mov     [rsp+0A0h+cIterations], 10000 ; cIterations
mov     [rsp+0A0h+cbSalt], eax ; cbSalt
call    cs:__imp_BCryptDeriveKeyPBKDF2

I will udpate the script to support this scenario.

Great, thx.

Ok for me when discussed elements will be added, thank you for your contribution 👍

* DPAPImk2john.py supports --password for new masterkey
* Documented that the derivation algorithm is hardcoded in NtlmShared.dll!MsvpDeriveSecureCredKey
* Code style
@jagotu
Copy link
Contributor Author

jagotu commented Oct 8, 2018

One of the builds timeouted for some reason, but as far as I'm concerned, all concerns raised so far were resolved. :)

@magnumripper magnumripper merged commit ad3682f into openwall:bleeding-jumbo Oct 10, 2018
@magnumripper
Copy link
Member

Please note I squashed the commits into a single one while merging. Thanks!

@mpgn
Copy link

mpgn commented Aug 3, 2021

Hello @jagotu

When I test the script it seems the context is not working properly

└─$ python DPAPImk2john.py -S S-1-5-21-3902381005-3621640295-1501945936-500 -c domain1607+ -mk fc4691a6-29c0-47e2-b484-8edd06508327
domain1607+
$DPAPImk$1*3*S-1-5-21-3902381005-3621640295-1501945936-500*des3*sha1*18000*e0c423993bd2f0a870090f2292c9ba6c*208*3c2cd5955d05c0694ff18a2bbe722b53f94fa476f8bea46193bf5f13dc4d695442c604c59881d53230aca4532e73399b2fca93f6ca03cc0ed460c3c7d8e0aef1ec4a51ca8fa304e0529d9d7d2188015eb754010e4770182bddaa0e3017ef4ebf39d3ae2056aaea9b

Since the context is domain1607+ the hash should start with $DPAPImk$2 and not $DPAPImk$1.

(I try all the option it's always version 1. Tested on windows server 2019) I can provide the file masterkey if you want.

@jagotu
Copy link
Contributor Author

jagotu commented Aug 3, 2021

@mpgn you're looking at the wrong number. The second number is the context, which is 3 as it should be for domain1607+

@mpgn
Copy link

mpgn commented Aug 3, 2021

Yep, my bad. Any idea how can I have a hash with version 2 ? meaning no DES since from what I understand DES is for xp and vista and AES for win7 and more.

Indeed version 1, which concerns DPAPI until Microsoft Vista (and workstations that migrated from XP or Vista), is using hmac-sha1 and 3DES, whereas version 2, which concerns DPAPI beginning with 7, is using hmac-sha512 and AES256.
Thus perfomances vary between these 2 versions (even if the Windows 10 client version is not that worse compared with Vista, which is quite a fail...).

hashcat/hashcat#1365

My goal is to get a hash like this: DPAPI masterkey file v2 + Active Directory domain context $DPAPImk$2*2*S-15-21-423929668-478423897-4895237151834*aes256*sha512*8000*740866e4105c77f800f02d367dd96699*288*ebc2907e16245dfe6c902ad4be70a079e62204c8a947498455056d150e6babb3c90b1616a8dff0e390dd26dda1978dffcbd7b9d7d1ea5c6d3e4df36db4d977051ec01fd6f0882a597c51834cb86445cad50c716f48b37cfd24339d8b43da771526fb01376798251edaa868fa2b1fa85c4142864b899987d4bbdc87b53433ed945fa4ab49c7f9d4d01df3ae19f25013b2

Since with format $DPAPImk$1, the cracking does not work.
https://hashcat.net/wiki/doku.php?id=example_hashes

Or john

└─$ python DPAPImk2john.py -S S-1-5-21-3902381005-3621640295-1501945936-500 -c domain1607+ -mk fc4691a6-29c0-47e2-b484-8edd06508327 --password October2021
domain1607+
DES3 [0x6603]
$DPAPImk$1*3*S-1-5-21-3902381005-3621640295-1501945936-500*des3*sha1*18000*e0c423993bd2f0a870090f2292c9ba6c*208*3c2cd5955d05c0694ff18a2bbe722b53f94fa476f8bea46193bf5f13dc4d695442c604c59881d53230aca4532e73399b2fca93f6ca03cc0ed460c3c7d8e0aef1ec4a51ca8fa304e0529d9d7d2188015eb754010e4770182bddaa0e3017ef4ebf39d3ae2056aaea9b
Decrypted succesfully as domain1607+
1
                                                                                                                                                                                                                                            
└─$ cat hash                                                                                                                                              
$DPAPImk$1*3*S-1-5-21-3902381005-3621640295-1501945936-500*des3*sha1*18000*e0c423993bd2f0a870090f2292c9ba6c*208*3c2cd5955d05c0694ff18a2bbe722b53f94fa476f8bea46193bf5f13dc4d695442c604c59881d53230aca4532e73399b2fca93f6ca03cc0ed460c3c7d8e0aef1ec4a51ca8fa304e0529d9d7d2188015eb754010e4770182bddaa0e3017ef4ebf39d3ae2056aaea9b
                                                                                                                                                                                                                                            

└─$ cat pass        
October2021                                                                                                                                                                                                                                            

└─$ john hash --wordlist pass                                                                                                                             
Using default input encoding: UTF-8
Loaded 1 password hash (DPAPImk, DPAPI masterkey file v1 and v2 [SHA1/MD4 PBKDF2-(SHA1/SHA512)-DPAPI-variant 3DES/AES256 256/256 AVX2 8x])
Cost 1 (iteration count) is 18000 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Warning: Only 26 candidates left, minimum 64 needed for performance.
0g 0:00:00:04 DONE (2021-08-03 18:14) 0g/s 817.0p/s 817.0c/s 817.0C/s paagal..sss
Session completed

@jagotu
Copy link
Contributor Author

jagotu commented Aug 4, 2021

@mpgn If for the same key the password checks out in the python script but isn't found by John that is, indeed, an issue.

What I see is that while two lines are in the hash file, only Loaded 1 password hash. Isn't the hash already cracked? (john hash --show)

If not, could you open a new issue, preferably with the master key file attached?

@mpgn
Copy link

mpgn commented Aug 4, 2021

Done @jagotu #4777 !

edit: It was my fault on John sorry !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants