1

Apple FSEvents Forensics

Undocumented, unexplored, and underutilized, that is until now. Apple FSEvents or File System events are an invaluable artifact for every Apple examiner and should be a go to resource for artifacts relating to file system activity that occurred in the past. In this post I will be covering a high-level overview of Apple FSEvents logs that are stored to disk including background information and behavior of FSEvents, mainly dealing with OS X but also touching on iOS.

Topics of discussion include:

  • Introduction to FSEvents
  • FSEvent log locations
  • FSEvent record structure
  • FSEvents behavior
  • Parsing FSEvents
  • Interesting events
  • FSEvents caveats

Introduction

FSEvents or File System Events are recorded events of changes to file system objects such as files and folders that occur on a volume mounted in OS X. It is used by several components of the OS including TimeMachine and Spotlight.
OS X 10.5 and 10.6 only captured events related to folders. Starting with OS X 10.7, file events were introduced. Similar to the NTFS change journal for Windows systems which records file system activity over time and stores the data in the UsnJrnl:$J, FSEvents records file system activity over time also and stores the data in FSEvent log files.
When FSEvent logs are parsed, file system events that have occurred in the past such as file, folder, symbolic link and hard link creations, removes, renames, modifications, permission changes and more can be reviewed providing another great resource of forensic artifacts to the examiner.
Information recorded in the logs that can be of value to an investigation include: mounting and unmounting external drives and disk images, activity within a users profile directory, document editing, internet activity, files moved to the trash, downloaded files, and much more.

FSEvent Logs Location

OS X Location

On OS X, FSEvent logs are located in a hidden folder named ‘.fseventsd/’ in the root directory of the system partition. Note that by default, this folder is hidden from view within Finder on a running Mac and accessing it requires elevated privileges.

iOS Locations

For iOS devices there are multiple locations where FSEvent logs are stored. Note that jailbreaking a device is often required to pull FSEvent logs. FSEvent log locations include:
1) System: /.fseventsd’

2) Data: /private/var/.fseventsd’

a. Usage after the device was first used by a user.

3) Developer Patch:/DeveloperPatch/.fseventsd’

a. Contains records prior to the devices first use by a user. This might also include patch activity if the OS was patched after being purchased, but this has not been verified.

External Device Locations

For external devices that were plugged into a Mac, when they exist they will be located in the root folder of the device within the “.fseventsd/” directoryThere are several scenarios however that will result in an external device having a “.fseventsd/” folder, but no logs within the folder:

a. An external device was plugged in to a Mac, but the device was unplugged without safely removing it resulting in FSEvent logs being lost. For example, the user pulls a usb drive from a Mac without using the unmount icon in Finder.

b. An external device was plugged in to a Mac, the device was safely removed (unmounted), but the device was unplugged before the OS could finalize writing FSEvents to disk.

c. An external device was plugged in to a Mac, but there is an unknown file system compatibility issue with the device.

FSEvent Log Files

The ‘.fseventsd/’ directory can contain anywhere from one log file, a few, or even as many as hundreds each of which contain historical file system and user activity over the course of a few days to months.

An individual log file can span multiple days depending on how much activity was occurring on the volume. System updates, upgrades, and application installs tend to generate a large number of FSEvents.

The logs are gzip archives and are named using a specific naming standard which is represented in hexadecimal format. The name of each FSEvent log refers to the last Event ID stored in the FSevent log file plus 1.

For example, using the first FSEvent log listed in the figure below, when the file name is converted from the hex value of ‘00000000000a4b3e’ to decimal, the value is 674,622. Therefore, the last Event ID within this file is 674,621 which is 1 less than 674,622.

FSEvent Record Lifecycle

FSEvent records are initially stored in memory. When a change occurs to an object on a volume, the FSEvents API checks to see if the object has already been assigned an Event ID using the relative full path of the object. Components of an FSEvent Record including Event ID’s will be discussed in more detail later. If no event ID has been assigned for the object in memory, one will be assigned to it and the relative full path of the object, the record flags, and the event ID will be stored in memory. If the object was already assigned an event ID, the API will update the record flags to include the current change. For each subsequent change that the object incurs while it has been assigned an event ID in memory, the API coalesces the changes (the record flags) and stores it as a single event for the object.

When the FSEvents API has determined that the memory buffer is full or the volume is being unmounted it flushes the events to disk in the form of FSEvent log files. Once flushed to disk, the API will not modify the contents of the logs.

As previously mentioned, multiple changes can be recorded in a single FSEvent record, each of which indicates what kind of changes occurred to the object. If for example, a text file on the user’s desktop was created, then modified, five minutes later modified again, and then finally removed (deleted) the two modifications will only be recorded once as a single event. The event record for the text file when parsed might look something like the following:

Note that even though the FSEvent record above shows what kinds of changes occurred, the order of changes are not accounted for within the logs.
These limitations are the result of the lack of granularity imposed by the FSEvents API when recording changes and not the result of parsing what was recorded.

FSEvent Log Format

FSEvent logs are stored as compressed archive files in gzip format. Once the files are uncompressed they can be opened using a hex editor so that raw strings can be viewed.

FSEvent Record Components

Each FSEvent log contains records that represent historical changes to objects on a volume. Each record within an FSEvent log consists of three major components:

Record Full Path

The Record Full Path is the unique relative full path to the file system object that incurred a change.

Record Event IDs

According to Apple documentation, event IDs are “monotonically increasing per system, even across reboots and drives coming and going. They bear no relation to any particular clock or timebase.” [1]
The Full Path to a file system object is only assigned one Event ID per FSEvent log. However, it can have multiple Event IDs across multiple logs.

Record Event Flags

Event Flags are stored in each FSEvent record and contain bit flags that indicate:

  • What the “Record Full Path” is (type flags):
    • File, Folder, Hard link, or Symbolic link
  • What has changed for the “Record Full Path” (reason flags):
    • Created, Removed, Modified, Renamed, Permissions, Inode metadata, Finder information, Mount, or Unmount
    • Other reason flags include: Last hard link removed, End of transaction, and Document revisions

Looking at the Hex

The example below is of an unzipped FSEvents log from a thumb drive containing activity that occurred on the drive.

The first twelve bytes of the log are allocated to the FSEvents log file page header and begins with a magic number of “1SLD”. There can be multiple page headers in one FSEvents log. Following each page header is the start of a Record Full Path of an event.
In the figure below, there are three events in total but only the first will be discussed. The first stored event has a Record Full Path of “My_File_1.txt” at offset 0x0C.

The Null Terminator “0x00” which is at the end of every Record Full Path indicates that it is the end of the full path.
Following the full path’s null terminator is the record’s Event ID. For the first event in our example this is located at offset 0x1a. The Event ID for this record is 0x01548d or 87,181 in decimal.
After the Event ID are the Record Flags which is stored at offset 0x22 for this event. Decoding record flags will not be covered in great detail but for this event the hex value of 0x5505800 indicates that this is a file that has been created, modified, finder information changed, and inode metadata changed.

FSEvent Record Flags

In the table below information about each of the possible flags is covered including but not limited to possible scenarios that would cause this flag to be set.

Flag Name Description Possible Scenarios
0x00000001  Item is Folder The path reported in the event refers to a folder.
0x00000002  Mount A volume was mounted at the path reported in the event. – A network drive or share was connected
– A removable drive was plugged in- A DMG was double-clicked
– The mount command was used in the terminal
– The system was started and the internal volumes were mounted
0x00000004  Unmount A volume was unmounted at the path reported in the event. – A network drive or share was unmounted
– A removable drive was unmounted- A DMG was unmounted
– The unmount command was used in the terminal
– The system was shut down or restarted and mounted volumes were unmounted
0x00000020  End of Transaction A volume was unmounted and indicates the end of transaction for the mount.
0x00000800  Last Hard Link Removed The path reported in the event is the last hard link and it has been removed.
0x00001000  Item is Hard Link The path reported in the event is a Hard Link. – Using the terminal command ln
0x00004000  Item is Symbolic Link The path reported in the event is a Symbolic Link. – Using the terminal command ln -s
0x00008000  Item is File The path reported in the event is a file.
0x00010000  Permissions Changed Permission changes have occurred to the path reported in the event. – Using the terminal command chmod or chown.
– Changing ownership within Finder by control-clicking an item and selecting “Get Info” and modifying ownership information.
0x00020000  Extended Attributes Modified Extended attributes have been modified for the path reported in the event. – Using the terminal command xattr
– Modifying a tag of an object within Finder
– Changing the default application used to open a file
0x00040000  Extended Attributes Removed Extended attributes have been removed for the path reported in the event. – Usage of the terminal command xattr -d
0x00100000  Document Revisions Changed Document revisions have changed for a file. – When a document with revisions enabled is changed
0x01000000  Created A file was created at the path reported in the event. Note that this flag is not set for folders, only files. – Copying files from one mounted volume to another
– Using the terminal command touch
– Using copy and paste for a file
0x02000000  Removed A file or folder was removed at the path reported in the event. This flag can be set for files or folders. – Moving files from one mounted volume to another
– Emptying the Trash- Using the rm command
0x04000000  Inode Metadata Modified Inode metadata was modified for the path reported in the event – A file or folder was locked or unlocked
0x08000000  Renamed The item at the path reported in the event was renamed. Note that a rename could indicate that the item was renamed to a new name or that it was moved from one directory to another. – Renaming a file or folder

– Moving a file or folder within the same volume
– Using the terminal command ren to rename a file or folder

– Using the terminal command mv to move a file or folder within the same volume

0x10000000  Content Modified Contents of the file at the path reported in the event was modified. – Editing the contents of a file
– Changing the default application used to open a file
0x20000000  Exchange Content was exchanged between the path reported in the event and another file. – A document was edited then saved and the temp file for that document shared information with the document being saved
0x40000000  Finder Information Modified Finder information was modified for the path reported in the event. – The stationary pad option was changed
– Tags were changed
0x80000000  Folder Created A folder was created at the path reported in the event. – Using the terminal command mkdir
– Using copy and paste for a folder

Parsing FSEvents

There are both paid and open-source tools available that parse FSEvents.

  • BlackBag Technologies BlackLight as of 2016 R1 supports parsing FSEvents as seen on The Forensic Lunch 2/26/2016.
  • FSEventParser is a free and open-source Python based tool developed by G-C Partners which also parses FSEvents. Download the latest version on GitHub at https://github.com/dlcowen/FSEventsParser .
    Instructions are available on the GitHub page which include the command line options to use after you have extracted the FSEvent logs from the volume to be analyzed. Remember that you can also carve for gzip files using your data recovery tool of choice and parse those as well.

———————————-

Usage: FSEParser_v2.1.py -c CASENAME -s SOURCEDIR -o OUTDIR

Options:*

-h, –help    show this help message and exit

-c CASENAME   The name of the current session, used for naming standards

-s SOURCEDIR  The source directory containing fsevent files to be parsed

-o OUTDIR     The destination directory used to store parsed reports

———————————

Once the command is issued, the parser will extract the records contained in each of the FSEvent log files located in the SOURCEDIR supplied in the command, placing the parsed data into a tab delimited tsv file and an SQLite database located in the OUTDIR supplied.

FSEventsParser Output

When the parser has finished parsing, the tab delimited file can by opened using Excel. FSEvent records are stored in the log in alphabetical order using the record full path (filename column in the screenshot below). To achieve a more chronological sort order in the parsed output, sort by the “event_id”  column as ascending. Keep in mind however that the chronological order relates only to when the first change occurred to an object.

The FSEventsParser script also produces an SQLite database containing parsed records which is useful for times when parsed records can be in excess of 1 million. The SQLite database also comes in handy when running queries to narrow down the records of interest.

Interesting Events in OS X

All events discussed were parsed using G-C Partners’ FSEventParser tool which output events into an SQLite database. Events listed here only scratch the surface of what can be found in FSEvents logs. This section is provided to give you an idea of what can be found within those logs. Interpreting the exact cause as to how these events were generated requires additional testing and validation.

Trash Activity

FSEvents log files record Trash activity which includes files sent to the Trash and Trash emptying. Files that were sent to the Trash will include the mask “Renamed”. Files that were emptied from the Trash will include the mask “Removed”.

The image below shows files and folders that were sent to the Trash. Note that in the Mask column, all events include the word “Renamed”. Note that “Renamed” is somewhat of a misnomer. A “Renamed” mask is assigned to an event in two ways:

  1. The name of the file was changed.
  2. The file was moved from one folder to another (local moves only, not moves across volumes).

In the case of the Trash folder, when files are sent to the Trash they receive a “Renamed” mask because they were moved to the Trash from some other location on the volume.

SQLite Query Example

SELECT
*, _ROWID_ “NAVICAT_ROWID”
FROM
“fsevents”
WHERE
“filename” LIKE ‘Users/%/.Trash/%’

System Boots

When a system is booted, the OS mounts “/home” and “/net”. We can query the SQLite database to get a list of approximate dates that the system was booted. In the image below, only “/home” was queried.

SQLite Query Example

SELECT
*, _ROWID_ “NAVICAT_ROWID”
FROM
“fsevents”
WHERE
(
“filename” = ‘/home’
OR “filename” = ‘/net’
)
AND “mask” LIKE ‘%mount%’

User Profile Folders

Activity within the User’s profile can also be of particular interest. This can include documents, downloads, and desktop activity. In the image below, a folder was renamed and two DMGs were created on the Desktop. In the Downloads directory, a ZIP file was created.

Note that the creation of some of these files was initiated by the user (me), and some were created by an application or the OS. In the Downloads directory, .BAH.XSEHo, .DS_Store, and M9hlK5RI.zip.part were not created nor modified by me directly.

SQLite Query Example

SELECT
*, _ROWID_ “NAVICAT_ROWID”
FROM
“fsevents”
WHERE
(
“filename” LIKE ‘Users/%/Documents/%’
OR “filename” LIKE ‘Users/%/Downloads/%’
OR “filename” LIKE ‘Users/%/Desktop/%’
)
AND “filename” NOT LIKE ‘Users/%/Library/Caches/com.%’
AND “filename” NOT LIKE ‘Users/%/Library/Containers/com.%’
AND “filename” NOT LIKE ‘Users/%/Documents/Microsoft User Data/Office %’

Mounted Volumes

When a drive is plugged in, the OS will try to mount it. When a DMG is double clicked, the OS will try to mount it. Mounts are also recorded within FSEvents.

SQLite Query Example

SELECT
*, _ROWID_ “NAVICAT_ROWID”
FROM
“fsevents”
WHERE
“mask” LIKE ‘%mount%’
AND “filename” NOT LIKE ‘/net’
AND “filename” NOT LIKE ‘/home’

Internet Activity

Web browsers such as Safari and Chrome store website addresses or URLs in the name of a files associated with internet activity. The changes to those files are recorded in FSEvents. Most of the websites listed in the image below were the result of me directly visiting the site, others appear to have been from third party sites not directly visited.

SQLite Query Example

SELECT
*, _ROWID_ “NAVICAT_ROWID”
FROM
“fsevents”
WHERE
“filename” LIKE ‘Users/%/Library/Caches/Metadata/Safari/History/%’
OR “filename” LIKE ‘Users/%/Library/Application Support/Google/Chrome/Default/Local Storage/%’
OR “filename” LIKE ‘Users/%/Library/Safari/LocalStorage/%’

Interesting Events in iOS

iCloud Synced Files

File synced from a connected iCloud account are recorded by FSEvents.

SQLite Query Example

SELECT
*, _ROWID_ “NAVICAT_ROWID”
FROM
“fsevents”
WHERE
“filename” LIKE ‘mobile/Library/Mobile Documents/com~apple~CloudDocs/%’

Internet Activity

Internet activity on a mobile device is also recorded.

SQLite Query Example

SELECT
*, _ROWID_ “NAVICAT_ROWID”
FROM
“fsevents”
WHERE
“filename” LIKE ‘%websitedata/local%’

Email Activity

Email activity including received items (inbox), sent items, and associated attachment names are also recorded by FSEvents.

SQLite Query Example

SELECT
*, _ROWID_ “NAVICAT_ROWID”
FROM
“fsevents”
WHERE
“filename” LIKE ‘mobile/Library/Mail/%’

Caveats

Like any forensic artifact there are caveats the one must be familiar with. For FSEvents these include:

  • Lost FSEvents
  • Lack of timestamps
  • External devices and FSEvents volatility
  • Anti-forensics
  • Coalescing of multiple changes

Lost FSEvent Logs

There are several scenarios that will result in FSEvent logs becoming lost or removed (deleted) from the volume. This can include:

  • A hard reset of a system
  • A system crash
  • Not properly unmounting a volume
  • System upgrades

On OS X, when FSEvent logs are removed from a volume, they become unallocated. Therefore, it is possible to carve for FSEvent logs using data recovery techniques and carving tools to carve for gzip files.

Lack of Timestamps

As previously mentioned, FSEvent records consist of three components: the full path, record flags, and the event ID. Note that a timestamp is not one of the three components.

There are ways to overcome this but so far none will give you precise timestamps for when an event occurred. Temporal data can be pulled from the names of Apple system log files and potentially the names of other files that are recorded within FSEvent logs to help determine the approximate time that an event occurred.

External Devices

FSEvents on external devices can be especially volatile.

  • When a safe removal takes place, the operating system writes the FSEvent records to the device. This can be observed by watching the read/write light equipped on some removable devices. After safe removal has been initiated within the OS, the light will flash and will stop when completed. If the drive is unplugged before the light has stopped flashing, the OS might not have finalized writing to disk and those FSEvent records may be lost and unrecoverable.
  • When a drive has been unplugged but the user did not perform a safe removal, FSEvents that were stored in memory for the device will be lost and will not be written to the drive.
  • It has also been observed that if a drive is formatted with EXFAT or FAT32, using a safe removal does not always ensure that events will be written to disk. The exact cause has not yet been determined, but lost events have been consistently observed for non-hfs formatted removable devices.

Anti-Forensic Measures

According to Apple documentation, it is possible to disable FSEvents on a volume. The existence of a file named “no_log” in the .fseventsd folder is a tipoff that FSEvents has been disabled for a volume. In the wild and in testing, this was never the observed case. [2]

Coalescing of Multiple Changes

FSEvent record flags can indicate that multiple changes occurred to a file or folder. Due to the nature of how the FSEvents API records and stores changes, the granularity required to determine in what sequence each individual change occurred and how many times those changes occurred is not possible.

At best, using FSEvents, we can only determine the sequence of when the first change occurred for an objected.

The bad news is that there is a major issue to be mentioned here. Remember that FSEvents stores changes primarily based off of the relative full path of a file system object. So, lets say for example that I created a file on my Desktop named “example.zip” .  Within a short period of time, this file became deleted in whatever fashion, then another file with the exact same name and location is created again. I now how an entirely different file on my desktop. The FSEvents API, sees them both as the same file because it only takes into account the relative full path when recording changes. So even though “example.zip” was created twice and is two completely different files it is only recorded once (keeping in mind that this occurred within a short period of time).

The good news is that FSEvents does record the fact that a file/folder was changed, and we know what kinds of changes occurred. Just not the order and frequency.

References

[1] https://developer.apple.com/reference/coreservices/fseventstreameventid

[2] https://developer.apple.com/library/content/documentation/Darwin/Conceptual/FSEvents_ProgGuide/FileSystemEventSecurity/FileSystemEventSecurity.html#//apple_ref/doc/uid/TP40005289-CH6-SW5

 

Nicole Ibrahim

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *