Skip to content

Instantly share code, notes, and snippets.

@glarizza
Created December 8, 2011 00:24
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save glarizza/1445481 to your computer and use it in GitHub Desktop.
Save glarizza/1445481 to your computer and use it in GitHub Desktop.
OS X Lion Password Hash Instructions

Password Hash Accessing:

  • Grab plist file from /var/db/dslocal/nodes/Default/users/username.plist

  • Convert to xml

      plutil -convert xml1 username.plist
    
  • Grab the ShadowHashData key and base64 decode it (install base64 with port install base64)

      echo "Data from ShadowHashData Key" | base64 -d > ShadowHashData
    
  • Convert the resultant binary plist file into xml

      plutil -convert xml1 ShadowHashData
    
  • Grab the SALTED-SHA512 Key and base64 decode it

      echo "Data from SALTED-SHA512 Key" | base64 -d > hashfile
    

*Reveal hash:

    xxd -p -c 256 hashfile | cut -c 9-

Opening a user plist from 10.7 and getting the binary-encoded bit

    require 'facter/util/plist'
    users_plist = Plist::parse_xml(`plutil -convert xml1 -o /dev/stdout /var/db/dslocal/nodes/Default/users/brit_xml.plist`)
    password_hash_plist = users_plist['ShadowHashData'][0].string
    IO.popen('plutil -convert xml1 -o - -', mode='r+') do |io|
      io.write password_hash_plist
      io.close_write
      @converted_plist = io.read
    end
    converted_hash_plist = Plist::parse_xml(@converted_plist)
    password_hash = converted_hash_plist['SALTED-SHA512'].string.unpack("H*")[0]
    puts password_hash

The problems here are that facter/util/plist cannot handle binary plists - so we need to convert them. Which sucks.

Using CFPropertyList

    require 'cfpropertylist'
    require 'base64'
    newplist = CFPropertyList::List.new(:file => 'demouser_edit.plist')
    newdata = CFPropertyList.native_types(newplist.value)
    bplist = CFPropertyList::List.new
    bplist.load_binary_str(newdata['ShadowHashData'][0])
    bplistdata = CFPropertyList.native_types(bplist.value)
    password_hash = bplistdata['SALTED-SHA512'].unpack("H*")[0][8..-1]

Nate's Gist --> https://gist.github.com/1445697

user { 'testuser': ensure => 'present', comment => 'Demonstration User', gid => '20', home => '/Users/testuser', password => 'aaa6c1f945132d2599079fe90c9d20e608e607344b86328c1ef8ad8dc820c1bb5a31fd816b8ae546fed6dcf58ff023794f8250a66935d6d0687b737f24aae2ed', shell => '/bin/bash', uid => '1026', }

@dayglojesus
Copy link

Can you do it in RubyCocoa without converting the plist with plutil? I can't seem to figure it out.

@glarizza
Copy link
Author

glarizza commented Jan 6, 2012

Updated plist to include revised/updated facter/util/plist method WITHOUT writing a file.

@dayglojesus
Copy link

https://gist.github.com/1587231
Thanks for the tip. Getting the password is simple, but storing it again is problem. There is a RubyCocoa bug in Lion that generates a Segmentation fault when trying to init an NSData object.
http://stackoverflow.com/questions/6775316/segmentation-fault-on-lion-creating-nsdata-from-rubycocoa-with-any-bytes-127

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