Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Extract a Mac OSX Catalina user's password hash as a hashcat-compatible string
#!/usr/bin/env python3
Mac OSX Catalina User Password Hash Extractor
Extracts a user's password hash as a hashcat-compatible string.
Mac OSX Catalina (10.15) uses a salted SHA-512 PBKDF2 for storing user passwords
(hashcat type 7100), and it's saved in an annoying binary-plist-nested-inside-xml-plist
format, so previously reported methods for extracting the hash don't work.
** You must be root to do this. **
Example Usage:
sudo ./ <username> > hash.txt
hashcat -a 0 -m 7100 --username hash.txt wordlist.dat
import plistlib
import sys
def read_user_plist(username):
plist_path = f"/var/db/dslocal/nodes/Default/users/{username}.plist"
with open(plist_path, "rb") as f:
plist = plistlib.load(f)
return plist
def extract_shadow_hash(user_plist):
# Nested binary plist
nested_bplist = user_plist["ShadowHashData"]
shadow_hash_plist = plistlib.loads(nested_bplist[0])
shadow = shadow_hash_plist["SALTED-SHA512-PBKDF2"]
pbkdf2 = {"iterations": shadow["iterations"],
"entropy": shadow["entropy"][:64].hex(), # Only the first 512 bits
"salt": shadow["salt"].hex()}
return pbkdf2
def format_hashcat(username, pbkdf2):
hc_line = f"{username}:$ml${pbkdf2['iterations']}${pbkdf2['salt']}${pbkdf2['entropy']}"
return hc_line
def main(args):
username = args[1]
user_plist = read_user_plist(username)
shadow = extract_shadow_hash(user_plist)
hc_input = format_hashcat(username, shadow)
if __name__ == "__main__":
Copy link

Rickorn622 commented Dec 31, 2020

Hi Everyone,

I was hoping someone could give me some directions on how to use this script. I am relatively new or let's say first experience with Python. Until now I figured out how to run this script from the command line on macOS 10.15.7.

The usage example, I am not sure I get it:

  1. script saves user(s).plist hash(es) to a hash.txt file, correct?
  2. hashcat uses that hash.txt file to extract the pwd(s), correct?

When I run this script on the command line, first I was getting syntax error with lines 28 and 48, is the f supposed to be there? If I removed them, then I get error message with lines 54 and 62. I am at lost at this point. I am just trying to figure out the user(s).plist hash(s) for a group of users I manage, and for which we currently migrated to Catalina.

Previous versions of macOS, was easy to retrieve the user.plist hash, but with 10.15.x doesnt seem to be as easy.
Any assistance will be greatly appreciated. Thanks


Copy link

mnrkbys commented Jan 20, 2021

You should use Python 3 and give an username as the argument of this script.

Copy link

sunknudsen commented Aug 4, 2021

Thanks for the script @teddziuba!

Can you please expand on

Only the first 512 bits


Copy link

HudsonOnHere commented Aug 18, 2021

this is amazing. been looking for something like this for the longest, thank you so much!!

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