FSEvents

Created: 28.09.2020

Intro

Directory events only 10.5-10.6. File events since 10.7. Each record is assigned a name which is constucted the following way: hex(last_event_id + 1). Lots of zeroes appended at the beginning of the file name. Example: 000000000112f2d8.

fsevents_example1

⚠️ Records are stored alphabetically, not chronologically!!! By alphabetically I mean sorted by file/dir full path.

/.fseventsd # root of the system partition

Like $UsnJrnl for Windows. Contains lots of logs gzip-compressed archive files. Magic number: 1SLD or 2SLD in an uncompressed file marks a page.

Log entries contain file ids which is useful for sequencing files and events. Since there are dozens of entries, it’s better to filter them. “Renamed” can mean the file was moved on the same volume.

Like $UsnJrnl. ❗️It keeps track of file ids, which is useful for sequencing events. Can be found /.fseventsd. Lot’s of gzip archives.

πŸ§ͺ However, I couldn’t find it on my M1 (macOS Big Sur, 11.2.3). The daemon was running (checked with Activity Monitor). Grabbing the processes path on disk (search for fseventsd, double-click, choose Sample and get the path from the result)

πŸ‘Œ I have found it here: ./System/Volumes/Data/.fseventsd. On iOS - /private/var/.fseventsd, for System: /.fseventsd and Developer Patch at /DeveloperPatch/.fseventsd.

fseventsd-path

  python FSEParser_V3.3.py -s -t folder /.fseventsd -o /Users/sentinel/Desktop/FSEvents_Out

Keywords: Mount/Volume, Safari/Chrome (web search), Renamed/.trash (trash).

Lot’s of information, so, think well whether to process it or not, since it’ll take time.

⚠️ If you insert a FAT-formatted thumb drive into a macOS machine, it will create fervents.

Tools πŸ› 

FSEventsParser. More about FSEvents might be seen here [10]. Thanks to Nicole Ibrahim from OSDFCon, we have this filetype reverse engineered and documented. At least, v1.

😭 Getting an error when trying to run FSEventsParser on a M1. No excpetion when running it on an Intel machine though. 😊 βœ… My solution was to run a windows version on a VM. Worked fine. ✍🏻 Another solution is to use mac_apt.py

mac_apt.py. Requires python to be installed. Consists of: extract_apfs_fs, ios_apt, mac_apt_artifact_only, mac_apt_mounted_sys_data and mac_apt.

Usage example:

python mac_apt_artifact_only.py SCREENTIME -i "/Users/username/Documents/RMAdminStore-Local.sqlite" -o "/Users/username/Documents/"

Querying Interesting Data

SELECT
*, _ROWID_ "NAVICAT_ROWID"
FROM
"fsevents"
WHERE
"filename" LIKE 'Users/%/.Trash/%'

010 Editor Template

I’m writing a template for parsing these files. However, the v2 seems to be a little different from the v1, which was described in the presentation mentioned above. Below is the structure of a file header + single page for v1.

πŸ”¬ v2 might need more research from my part.

//------------------------------------------------
//--- 010 Editor v11.0.1 Binary Template
//
//      File: 
//   Authors: 
//   Version: 
//   Purpose: 
//  Category: 
// File Mask: 
//  ID Bytes: 
//   History: 
//------------------------------------------------
SetForeColor( cRed );
char     header[4];
SetForeColor( cNone );
int     unknown;
SetForeColor( cYellow );
int     pagesize;
SetForeColor( cPurple );
string  full_path1;
uint64 event_id;
int reason_flags;

The structure is however quite trivial. Following the header of 4 bytes and 4 bytes of some undocumented mysterious value, there are 4 bytes defining page size, the full path of the file and the event id of the event.

❓ May be it’s better to write a script for 010 Editor?

Turning Off Logging

From Apple’s official documentation:

In some cases, the contents of a volume are sufficiently secret that it is not appropriate to log them. To disable logging on a per-volume basis (for creating a backup volume, for example), you must do the following:

  • Create a .fseventsd directory at the top level of the volume.
  • Create an empty no_log file in that directory.

So if your volume is mounted at /Volumes/MyDisk, you would create an empty file called /Volumes/MyDisk/.fseventsd/no_log.

Problems

Problem #1. When the USB drive or another external media is not safely removed (by ejecting it properly, not just viciously unplugging it like a sword πŸ—‘ from the corps by some primeval man from the Middle Ages), the fsevents will have no time to write to the file. If the device was unplugged too soon, this may also result in lost events (even if the sword analogy could not be applied here). If the FS on the device is incompatible, the same result you’ll get.

Problem #2. When several operations were performed on the same file or directory, there is only one record for that in the logs. I presume, as long as these events are sufficiently sparsed in memory, the get to different buffers, thus to different files and this would be the only way to observe changes.

πŸ§ͺ How long does it take for a fsevent buffer in memory to fill up?

Problem #3. They can be turned off. But that would require sufficient knowledge of logging system on macOS. Most users of macOS are not forensics experts, I presume. Not even hackers. Though there are many of them… However, even those are not experts in macOS.

Problem #4. Fsevents logs do not keep timestamps. See the rightmost column. How’s that likely, that all of these events have the EXACT same timestamp? Not very. That’s source_modified_time. To overcome this limitation Ibrahim [1] recommends using temporal data from the names of logs.

πŸ§ͺ Not quite sure what he meant by that… .

πŸ§ͺ I presume, that’s the date and time when the log files were created. Or is this the date and time when FSEventsParser was performing its duties?

timestamps

Artifacts

macOS

iOS

References

[1] OSDFCon, Introduction to FSEvents

[2] Preventing File System Event Storage, official Apple docs