---
# System prepended metadata

title: Leveraging FSEvents for Mac Forensic Analysis

---

## What are FSEvents on macOS ?? 
FSEvent is a short for File System Events, FSEvents is a macOS-specific API allows applications to register for notifications of changes such as file creation, deletion, modification, and renaming to a given directory tree which helps applications to keep track of file system changes in real-time without continuously scanning the disk, which would be inefficient and resource-intensive. Whenever the filesystem is changed, the kernel passes notifications via the special device file /dev/fsevents to a userspace process called **fseventsd**. This process combines multiple changes to a single directory tree that occur within a short period of time, then notifies applications that have registered for changes to the affected directory.

They are introduced in **10.5** (**only directory events up to 10.6**), then **file events are added with 10.7**. They are stored in FSEvent log files **(gzip)**.



They can be found on iOS, OS X devices and external devices plugged into a Mac.
## Location of FSEvents
### In OS X devices : 
1. **/.fsevents**   : macOS versions below BigSur
2. **/System/Volumes/Data/.fseventsd/**  : macOS BigSur and higher

### In iOS Devices : 
1. Data partition :  **/private/var/.fseventsd**     
2. System Partition :  **/.fseventsd**      
3. Developer patch : **/DeveloperPatch/.fseventsd** 
## The Forensic Insights Provided by FSEvents


FSEvents captures detailed information  about modifications occurring within the file system such as file **creation**, **deletion**, **modification**, **renaming** and **mounting**. offering a timeline of changes that can help identify patterns or anomalies, and can uncover critical artifacts that play a key role in cross-referencing and validating other digital evidence during investigations.







## Structure of FSEvent file

Based on "Mac Forensics_ Looking into the Past with FSEvents - SANS DFIR Summit 2017" introduced by Nicole Ibrahim, this is the structure of the FSEvents after unzipping the log file.

![image](https://hackmd.io/_uploads/r1RIlSTzkx.png)


1. **Page Magic Number** `4-bytes` :  In macOS **versions prior to 10.13**, the magic header within a decompressed FSEvents log was `1SLD`. **Beginning with 10.13**, the magic header `2SLD`, now the magic header is `3SLD`
2. **Record Full Path** : full path of the file, starts at offset `0x0c` (not a standard but, you will always notice it in the structure), and length is variable.
3. **Record Event ID** : starts after `00 null byte` after end of **Full Path** and it is `8-bytes` size.
4. **Record Reason Flags** : starts after **Event-ID** directly and it is `4-bytes` 

![image](https://hackmd.io/_uploads/B1eAO96Gyl.png)

To make sure that our analysis is good, we will try **FSEvent-parser** to check it's results.

![image](https://hackmd.io/_uploads/Hy9RIcpGJe.png)


## What does FSEvent API  record on Mac ? 
 Based on [David Cown's repo](https://github.com/dlcowen/FSEventsParser), FSEvent records the following categories : 

- UserProfileActivity
- UsersPictureTypeFiles
- UsersDocumentTypeFiles
- DownloadsActivity
- TrashActivity
- BrowserActivity
- MountActivity
- EmailAttachments
- CloudStorageDropBoxActivity
- CloudStorageBoxActivity
- DSStoreActivity
- SavedApplicationState
- RootShellActivity
- GuestAccountActivity
- SudoUsageActivity
- BashActivity
- FailedPasswordActivity
- iCloudSyncronizationActivity
- SharedFileLists




## Tools to parse FSEvents 

1. **FSEventsParser** : the patched version from [Nicole Ibrahim](https://github.com/nicoleibrahim/FSEventsParser/tree/patch-1) or from [mac4n6](https://github.com/mac4n6/FSEventsParser).
2. **macos-fseventsd** : from [puffyCid](https://github.com/puffyCid/macos-fseventsd?tab=readme-ov-file) 
3. **mac-apt** : from [Yogesh Khatri](https://github.com/ydkhatri/mac_apt/releases/tag/v1.7.5-dev)


## Demo Time 



**Tools** : macOS v10.13 machine, FSEventparser_v4.0 
#### 1- Create file &  directory

I created 2 files one using **TextEdit** and the other one using **nano commandline**, then I parsed the **.fseventsd/** directory.

```
python2.7 FSEParser_V4.0.py -s ./fsevent/ -t folder -o output -q report_queries.json
```


1. The file created with **TextEdit** `tes.no1.rtf` has many records within the log file. You can trace this when ordering Event-IDs.

- The record has `Renamed;ExtendedAttrModified;ExtendedAttrRemoved;` flag.


![image](https://hackmd.io/_uploads/SJYMQTazJx.png)


2. The second one which created with command line `test1.txt` has few events, maybe there are more, but i assumed this based on event's sequence. 

- The record has `Modified;Created;` flag.

![2](https://hackmd.io/_uploads/rkK38aTMJe.png)


#### 2- Rename file & directory

I removed event log files, then I will wait few minutes to  rename `test1.txt` to `test2.txt`, then renaming `output` directory to output2, then shutdown the machine to force the content within memory to be written to the disk.

1. Firstly I renamed `output` directory to `output2`. the 2 events are **Consecutive**, and the flags will be `Renamed`  

![image](https://hackmd.io/_uploads/rkZYXxAMJg.png)

![image](https://hackmd.io/_uploads/Hkz1VeRGkg.png)

2. Secondly, I renamed **test1.txt** to **test2.txt** with command `mv test1.txt test2.txt`, lets check if the node_id is the same. Yes they have the same node_id .

![image](https://hackmd.io/_uploads/B1SBKg0fyl.png)

![image](https://hackmd.io/_uploads/B1G6FeAzJe.png)

3. Renamed **test_no1.rtf** to **test_no1.rtf** through **Finder** app.

![image](https://hackmd.io/_uploads/rkNuilRzkl.png)

![image](https://hackmd.io/_uploads/r1Dk3xRGyl.png)

Finding **.DS_Store** in fsevents after any renaming or modification or deletion, indicating that that action happened through **Finder** app.



#### 3- Copying file to a directory

I copied **test2.txt** from root directory to **Users/m4shl3/Desktop** through `cp` command, then I copied it **from Desktop to Documents** through **Finder GUI Window**. 

When I run the parser, I found the 2 events under Desktop and Documents.
1. The one in Desktop which was copied from root directory using `cp` was found with `Modified;ItemCloned;Created;PermissionChange;` flag.
2. The second one under Documents, was found with `ItemCloned;Created;PermissionChange;` flag.


![image](https://hackmd.io/_uploads/SyX9x70M1x.png)


 I will back and copy the file again  from root directory to **Music** Directory with **cp** command.

![image](https://hackmd.io/_uploads/HyZE0f0zJx.png)




It appears as a record with `Modified;Created;PermissionChange` flag without `ItemCloned` 

![image](https://hackmd.io/_uploads/HyrjTMAz1g.png)

I will do copy the file from **Music/** to **Library/** using `cp` command then to **Applications/** using Finder and see what flags will hit.

![image](https://hackmd.io/_uploads/S1LrsFRMyg.png)

![image](https://hackmd.io/_uploads/S1xLjtRz1x.png)



**Hypothesis** : 
1. Copying file through **command line** will always generate `Modified;Created;PermissionChange;` flag.
2. Copying file through **Finder GUI Window** will always generate `ItemCloned;Created;PermissionChange;` or `Modified;ItemCloned;Created;PermissionChange;` flag. And log file will show **2 files** before and after copying.

I made same process again just to be sure about Hypothesis. And same results.


![image](https://hackmd.io/_uploads/Bkv91q0Gyx.png)


#### 4- Moving file to a directory

I have test2.txt on **Desktop**, I will move it to **Documents** directroy.

It will generate **Renamed** flag.

![image](https://hackmd.io/_uploads/rkw8wc0zJg.png)


#### 5- Unzipping file

I will unzip **sample-2** file  and see what recoreds we will get.

1. Unzpping as  a default command will generate `InodeMetaMod;FolderCreated;`
2. Unzipping to new directory will generate `InodeMetaMod;PermissionChange;FolderCreated;`

![image](https://hackmd.io/_uploads/ry4cui0Gkl.png)

3. Also, If you downloaded a **.zip** file, it will automatically be unzipped and appear as directory on **Downloads/**, and will generate `Modified;Renamed;Created;ExtendedAttrModified;`, and creates an entry into **.Trash** directory 

![image](https://hackmd.io/_uploads/H1a0tjCf1l.png)

As seen you can know the content of each file in the zip file. This is so important from forensics perspective.

#### 6- moving file to the Trash

Moving the file to Trash means the file is still exist but in the Trash itself.

There will be `Renamed` flag within **.Trash** record.

![image](https://hackmd.io/_uploads/HJCtijCGkx.png)


#### 7- Removing file from the Trash (Empty Trash)

Removing file from the Trash means file will no longer exist.

There will be `Renamed;Removed` flag.

![image](https://hackmd.io/_uploads/BysTssCz1e.png)


#### 8- Mounting dmg file

when you need to install dmg app on mac, you just can double click the dmg file, that will mount the dmg file on disk.

There will be some checks before mounting and the record will have flag  `Mount`

![image](https://hackmd.io/_uploads/HyWp1n0Myg.png)



#### 9- Browsing through Safari app

Browser events will not tell you  the urls or even  what you typed in safari search, it is just will tell you that there was a browser activity by the user.

Here is an example of downloading a zip file using safari, you can notice that there are events (modification of files) related to safari **cache/** directory, indicating of downloading something.


![image](https://hackmd.io/_uploads/SJmVz3Czkl.png)

 


| Action | Flag | 
| -------- | -------- | 
| Creating text file  with nano command  | Modified;Created;    | 
|Creating file with TextEdit|Renamed;ExtendedAttrModified;ExtendedAttrRemoved |
|Renaming a File |Renamed|
|Renaming a Directory |Renamed|
|Copying file through command line |Modified;Created;PermissionChange|
|Copying file through Finder GUI Window|ItemCloned;Created;PermissionChange; **or**   Modified;ItemCloned;Created;PermissionChange;|
|Moving file to a directory|Renamed|
|Unzpping a file with default command |InodeMetaMod;FolderCreated;|
|Unzipping to new directory  |InodeMetaMod;PermissionChange;FolderCreated;|
|Moving file to the Trash|Renamed|
|Removing file from the Trash (Empty Trash)|Renamed;Removed|
|Mounting dmg file|Mount|


**This is what I got during my tests, The events may change based on macOS versions or the way the examiner doing the test, you will never know till you try.**


## FSEvents Caveats
FSEvents are stored in memory so, they are lost due to either : 
1. A hard reset of the system
2. A system crash
3. Not properly unmounting a volume
4. System Upgrades

There is no timestamp within each record, so we can't determine from those events when exactly if something changed. All what we can got the nearly day the event was added to the logs.

The FSEvents API coalesces multiple changes into a single record, This file may have been created 3 times and removed twice, but we will never know.



## References 

1. https://github.com/libyal/dtformats/blob/main/documentation/MacOS%20File%20System%20Events%20Disk%20Log%20Stream%20format.asciidoc
2. https://www.hexordia.com/blog/mac-forensics-analysis#:~:text=FSEvents%20are%20generally%20found%20in,compressed%20binary%20format%20(gzip)
3. https://exposed425.rssing.com/chan-6927338/article437-live.html
4. https://youtu.be/bv5gu5reKEA?si=vs7FhixAOr50YMY8

----

<iframe src="https://giphy.com/embed/MTdNrKa1i1iy3lrJWH" width="480" height="271" style="" frameBorder="0" class="giphy-embed" allowFullScreen></iframe><p><a href="https://giphy.com/gifs/pcmag-retro-apple-macintosh-MTdNrKa1i1iy3lrJWH"> </a></p>