git clone https://github.com/kholia/fvde2john.git && cd fvde2john/
./configure && make
git clone https://github.com/hashcat/hashcat.git && cd hashcat/
make
$diskutil list
... /dev/disk2 (external): #: TYPE NAME SIZE IDENTIFIER 0: GUID_partition_scheme 251.0 GB disk2 1: EFI EFI 209.7 MB disk2s1 2: Apple_CoreStorage Macintosh HD 250.1 GB disk2s2 3: Apple_Boot Recovery HD 650.0 MB disk2s3 Offline Logical Volume Macintosh HD on disk2s2 C59F0385-4F65-7EBA-36DB-3977388EB4AA Locked Encrypted $diskutil mount /dev/disk2s3
Volume Recovery HD on /dev/disk2s3 mounted $find /Volumes/Recovery\ HD -name Encry*
/Volumes/Recovery HD/com.apple.boot.S/System/Library/Caches/com.apple.corestorage/EncryptedRoot.plist.wipekey $sudo ./fvdetools/fvdeinfo -e /Volumes/Recovery\ HD/com.apple.boot.S/System/Library/Caches/com.apple.corestorage/EncryptedRoot.plist.wipekey -p dont-know /dev/disk2s2
... $fvde$1$16$3fc886d887bef6f52b6d3f275c290e23$135098$5f852cd981bdad55bd8e60de04ab28742961b3c55e28a0f5 ... $diskutil unmount /Volumes/Recovery\ HD/
Volume Recovery HD on disk2s3 unmounted
$ ./hashcat/hashcat -a 0 -m 16700 -o found.txt hash.txt wordlist.txt
sudo add-apt-repository universe && sudo apt update
sudo apt install fuse3 libfuse3-dev libbz2-dev cmake git libattr1-dev zlib1g-dev
git clone https://github.com/sgan81/apfs-fuse.git && cd apfs-fuse/
git submodule update --init
mkdir build && cd build
cmake ..
make
$ cat /proc/partitions
major minor #blocks name
8 0 125034840 sda
...
8 16 118489088 sdb
$sudo ./apfs-dump-quick /dev/sdb log.txt
Device /dev/sdb opened. Size is 121332826112 Info: Found valid GPT partition table on main device. Dumping first APFS partition. ... Volume Macintosh HD is encrypted. ... Enter Password:JUST PRESS ENTER
... [KEK] Unk 80 : 0 UUID : 48BCAEEB-4E7A-C5D2-B7EB-C21DCD1366F9 Unk 82 : 00000000 0002 15 174 KEK Wrpd: 2FDEAFAA0F6A971F674B487270A5AE59578B29FB377F76E35CF23985E045EBB8F70687086B6ED7F5 Iterat's: 100000 Salt : 692B540738291E8B5248A74444E5B1EF ...
$fvde$2$16$692B540738291E8B5248A74444E5B1EF$100000$2FDEAFAA0F6A971F674B487270A5AE59578B29FB377F76E35CF23985E045EBB8F70687086B6ED7F5
$ hashcat -a 0 -m 18300 -o found.txt hash.txt wordlist.txt
brew install cmake pkg-config git
git clone "https://github.com/Banaanhangwagen/apfs2hashcat.git" && cd apfs2hashcat
git submodule update --init --recursive
mdkir build && cd build
cmake .. -DCMAKE_POLICY_VERSION_MINIMUM=3.5
make
% diskutil list
...
/dev/disk5 (external, physical):
#: TYPE NAME SIZE IDENTIFIER
0: GUID_partition_scheme *251.0 GB disk5
1: EFI EFI 209.7 MB disk5s1
2: Apple_APFS Container disk6 250.8 GB disk5s2
/dev/disk6 (synthesized):
#: TYPE NAME SIZE IDENTIFIER
0: APFS Container Scheme - +250.8 GB disk6
Physical Store disk5s2
1: APFS Volume Macintosh HD - Data 122.3 GB disk6s1
2: APFS Volume Preboot 365.5 MB disk6s2
3: APFS Volume Recovery 613.8 MB disk6s3
4: APFS Volume VM 1.1 GB disk6s4
5: APFS Volume Macintosh HD 24.0 GB disk6s5
% sudo ./apfs-dump-quick /dev/disk5 log.txt
...
$fvde$1$16$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$93003$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX00000000000000000000000000000000
...
Whether specifying the physical disk (disk5
) or the synthesized logical container (disk6
), the resulting hash was identical (salt and wrapped KEK segment redacted here).
Strip any zero padding at the end of the wrapped KEK segment prior to saving the hash as hash.txt
.
$fvde$1$
(vs. $fvde$2$
) indicates FileVault was enabled on HFS+ pre-APFS, so hash mode 16700 applies instead of 18300, despite the current APFS format.
%brew install hashcat
%hashcat -a 0 -m 16700 -w 4 --force hash.txt combos.txt
Options: straight attack (-a 0
), hash mode 16700 (not 18300 — see above), workload profile 4 ("insane"), --force
to bypass warnings, hash.txt
saved in step 3.3, and combos.txt
generated with this Python script based on user's vague recollection:
from itertools import product
symbols = ['@', '!', '#', '$', '%', '^', '&', '*']
words = [
'sing', 'sinG', 'siNg', 'siNG', 'sIng', 'sInG', 'sINg', 'sING',
'Sing', 'SinG', 'SiNg', 'SiNG', 'SIng', 'SInG', 'SINg', 'SING'
]
with open('combos.txt', 'w') as f:
for sym, word in product(symbols, words):
# Just symbol + word
f.write(f"{sym}{word}\n")
# symbol + word + 1-digit numbers
for i in range(10):
f.write(f"{sym}{word}{i}\n")
# symbol + word + 2-digit numbers
for i in range(100):
f.write(f"{sym}{word}{i:02}\n")
# symbol + word + 3-digit numbers
for i in range(1000):
f.write(f"{sym}{word}{i:03}\n")
# symbol + word + 4-digit numbers
for i in range(10000):
f.write(f"{sym}{word}{i:04}\n")
System volume vs. removable media volume: "For the system volume you'll first need to obtain the EncryptedRoot.plist.wipekey and pass it to fvdemount. For removable media volumes this is not necessary because the relevant data is stored on the encrypted volume."
If a firmware password is set, there are a few options:
The full output of apfs-dump-quick /dev/sdb log.txt
included two distinct KEK sections; the first contained the desired hash.
Pairing rules with wordlists increases efficacy. According to Tevora.com, "Append_d is by far the most effective rule. It added an average of 10% more cracks to each wordlist it was paired with." Can be appended to the above hashcat commands like so: -r ./hashcat/rules/hybrid/append_d.rule
.
See also Recovering saved macOS user passwords, Crack Mac user password, and Cracking hashes in the cloud with hashcat
created: 2019.05.27, updated: 2025.04.12