Overview
Understanding the HFS+ file system is an important step to analyzing Mac systems. It tracks all of the metadata associated with files and folders on a system among things.
Suggested Reading
NOTE: Any discussions about Mac systems will assume you are running 10.11.x That's all I have for testing on my Surface Pro 4 :)
HFS+ Structure
The core files (aka – “special files”) that make up the HFS+ filesystem according to TN1150 are listed below. This blog post will cover the Volume Header. I will cover the others in order as they are listed here in subsequest blog posts.
- Volume Header
- Catalog File
- Extents Overflow File
- Attributes File
- Allocation File
- Startup File
Table 1 – Special File Reservation C struct depicts the C struct code for the 16 reserved Catalog Node IDs (CNID/inode) for HFS+ special files per the TN1150
Table 1 – Special File Reservation C struct
enum {
kHFSRootParentID = 1,
kHFSRootFolderID = 2,
kHFSExtentsFileID = 3,
kHFSCatalogFileID = 4,
kHFSBadBlockFileID = 5,
kHFSAllocationFileID = 6,
kHFSStartupFileID = 7,
kHFSAttributesFileID = 8,
kHFSRepairCatalogFileID = 14,
kHFSBogusExtentFileID = 15,
kHFSFirstUserCatalogNodeID = 16
};
Volume Header
Every HFS+ volume must have a volume header. The volume header is important to the overall filesystem because it provides the analyst with volume creation, modification, and checked dates. It specifics the block size, the locations of our 16 special files, boot files (boot.efi), bootable folder (CoreServices), number of files and folders on the volume and also lets us know if journaling is enabled among other details.
There are two volume headers. The volume header and the alternate volume header. The volume header is located at offset 0x400h, which is 1024 bytes from the start of the volume. The alternate volume header is located 1024 bytes before the end of the volume. Both are 512 bytes in size and are at fixed locations.
Extract Volume Header
In this example I show you how you can extract the volume header for analysis.
In our case I extract 4096 bytes, which is our first block. This will contain all of our volume header information that we can use during analysis.
In order to do the extraction, I used the following. If you prefer you can also open the entire disk with your hex editor. For size/portability reasons I will be using dd to extract the first 4096 bytes.
First we will look at the mapping of our disk.
Table 2 - mmls disk layout
sudo mmls /dev/rdisk1
We can see here that item 05 (HFSDemo) is what we want.
GUID Partition Table (EFI)
Offset Sector: 0
Units are in 512-byte sectors
Slot Start End Length Description
000: Meta 0000000000 0000000000 0000000001 Safety Table
001: ------- 0000000000 0000000039 0000000040 Unallocated
002: Meta 0000000001 0000000001 0000000001 GPT Header
003: Meta 0000000002 0000000033 0000000032 Partition Table
004: 000 0000000040 0000409639 0000409600 EFI System Partition
005: 001 0000409640 0030703575 0030293936 HFSDemo
006: ------- 0030703576 0030965759 0000262184 Unallocated
Table 3 - dd block 1 - header volume
sudo dd if=/dev/disk1 of=volheader bs=4096 count=1
After running dd we now have our 4096 byte dump, which will contain our volume header.
1+0 records in
1+0 records out
4096 bytes transferred in 0.000940 secs (4357055 bytes/sec)
Analyze Volume Header
Now that we have the volume header extracted we can move to offset: 0x400h with our hex editor (010 Hex Editor), which is sector 2 (0, 1) as depicted in Figure 1 – HFS+ Offset – 0400h (1,024 bytes). On a Mac, you can easily skip to an offset in 010 by using the Command + L keys. You could have also skipped these bytes using dd as well.
Figure 1 - HFS+ Offset - 0x400h (1,024 bytes)
To make things easier to see and separate out I created a Synalyze It! template for parsing the HFS+ volume header. The results of the grammar file can be seen in Figure 2 – HFS+ Synalyze It! Volume Header Grammar.
You can download the Synalyze It grammar file on my GitHub.
Figure 2 - HFS+ Synalyze It! Volume Header Grammar
NOTE: The volume header creation date is stored in local time, not GMT.
Table 3 – HFS+ Volume Header Output
Here is the parsed hex from Figure 2 above using the Synalyze It! Pro Grammar file I created.
Now that we have "manually" parsed the volume header using a hex editor let’s go over some of the more useful information that we were able to uncover.
Volume Header Analysis Results
- HFS+ filesystem
- H+
- Version 4 = HFS+
- A journaled filesystem - Journaling is enabled
- Creation Date (Local time) - 2016-07-23 11:08:47
- Modify Date(UTC) - 2016-07-23 18:09:36
- Backup Date (UTC) - 00 00 00 00
- Checked Date (UTC) - 2016-07-23 18:08:47
- File count – 66
- Folder count – 19
- Volume UUID - 37a4e9fdeafc14ea
- Block size is 4096
- Total Blocks – 3,786,742
- Free Blocks - 3,777,448
- Drive size = Total Blocks * Block Size (4096), which is 15,510,495,232 bytes, or 15 GB
- Location and Size of Special files (Extent, Catalog, Attributes, and Startup) via the Fork Data Structures.
To make converting the hex times easier I went ahead and wrote a simple Python method below to convert our times and print them out in a human readable format.
Table 4 - Python Datetime Conversion
>>> print mactimeConvert(0xD3B900BF)
2016-07-23 11:08:47
>>> print mactimeConvert(0xD3B96360)
2016-07-23 18:09:36
>>> print mactimeConvert(0xD3B9632F)
2016-07-23 18:08:47
The Easy Way
Now that we parsed the volume header the “hard” way, it is time to go over an easier method using one of my favorite tools.
This is accomplished via Sleuth Kit’s fsstat command.
fsstat displays details of a file system. The “f” set of tools within Sleuth Kit are file system specific (fls, fsstat, ffind, etc.) You could also use the native Mac tool, hdiutil (hdiutil fsid /dev/
You can see within Table 5 – fsstat - Sleuth Kit, fsstat provides us with all of the information we were able to obtain via hex analysis and then some.
It also provides us this information within a faction of a second vs. the time required for manual analysis/parsing like we did above.
Table 5 - fsstat - Sleuth Kit
You can run it via:
sudo fsstat /dev/rdisk2s2
And here are the results of using The Sleuth Kit's fsstat command.
FILE SYSTEM INFORMATION
File System Type: HFS+
File System Version: HFS+
Volume Name: HFSDemo
Volume Identifier: 37a4e9fdeafc14ea
Last Mounted By: Mac OS X, Journaled
Volume Unmounted Properly
Mount Count: 203
Creation Date: 2016-07-23 11:08:47 (PDT)
Last Written Date: 2016-07-23 11:09:36 (PDT)
Last Backup Date: 0000-00-00 00:00:00 (UTC)
Last Checked Date: 2016-07-23 11:08:47 (PDT)
Journal Info Block: 117
METADATA INFORMATION
--------------------------------------------
Range: 2 - 108
Bootable Folder ID: 0
Startup App ID: 0
Startup Open Folder ID: 0
Mac OS 8/9 Blessed System Folder ID: 0
Mac OS X Blessed System Folder ID: 0
Number of files: 66
Number of folders: 19
CONTENT INFORMATION
--------------------------------------------
Block Range: 0 - 3786741
Allocation Block Size: 4096
Number of Free Blocks: 3777448
Summary
Keep in mind tools are not always 100% accurate.
I have personally written tools that parsed artifacts incorrectly. I do this all the time. Do not blindly rely on them for your analysis. Learn how to do things manually, then go about writing your own tools, or verifying other people's tools.
Enjoy!