The ESF Playground

Published by jaron.bradley on

Download ESFPlayground

A Note: This tool has been upgraded since it’s original creation. Read the changes here

The ESF Playground

Over the past few months there have been multiple times where I’ve wanted to view all of the events in which the Apple Endpoint Security Framework (ESF) has to offer as they occur in real time and yet, no such tool exists. One of the reasons no such tool exists could be due to the fact that the only way to build one requires someone who has the interest and also holds an entitlement from Apple (com.apple.developer.endpoint-security.client). I decided to develop a tool for this exact use case and I’m happy to announce I’m releasing it to aid others in their research as well.

Meet The ESFPlayground!

The ESFPlayground can be used to view all raw events coming from the ESF and print them in JSON form. To get started make sure that Terminal.app has been granted Full Disk Access within your tcc permissions (Preferences > Security > Privacy > Full Disk Access). 

Then within the terminal simply execute the application executable using sudo.

sudo /Applications/ESFPlayground.app/Contents/MacOS/ESFPlayground 
Screen Shot 2021-10-11 at 10.46.47 PM

Yes. Admittedly, running an application as sudo is fairly non-traditional which is why I’ve chosen to make the UI itself completely non-interactive. It simply displays information about enabled and disabled events. The terminal in which the application was executed is where the occurring events will be printed. Using this setup, the program can be simply started and stopped without having to install a system extension.

Screen Shot 2021-10-12 at 5.13.02 PM

The UI will also give you a rough idea of the noise level of each individual event based on the judgement of myself. Note that these noise levels will vary based on what software is running on your computer and they are simply there to give you a rough idea.

It's Customizable

At the current moment The ESFPlayground supports all available ESF notify events and I will do my best to keep it up to date as new events are added.   Available event descriptions can be seen on Apple’s website here.

The ESFPlayground is customizable so you can pick and chose which events you want to see. A default config file will be created the first time you run the program and will be recreated should you ever delete it. To enabled or disable the tracking of a specific event simply remove or add the pound sign in front of the event in the config file located at “/var/root/Library/Application Support/playground.config”.

sudo vim "/var/root/Library/Application Support/playground.config" 
#---Processes---#
ES_EVENT_TYPE_NOTIFY_EXEC
ES_EVENT_TYPE_NOTIFY_FORK
ES_EVENT_TYPE_NOTIFY_EXIT
ES_EVENT_TYPE_NOTIFY_SIGNAL


#---File---#
ES_EVENT_TYPE_NOTIFY_TRUNCATE
ES_EVENT_TYPE_NOTIFY_STAT
ES_EVENT_TYPE_NOTIFY_LOOKUP
ES_EVENT_TYPE_NOTIFY_FSGETPATH
ES_EVENT_TYPE_NOTIFY_DUP
ES_EVENT_TYPE_NOTIFY_FCNTL
ES_EVENT_TYPE_NOTIFY_CLONE
ES_EVENT_TYPE_NOTIFY_EXCHANGEDATA
ES_EVENT_TYPE_NOTIFY_RENAME
ES_EVENT_TYPE_NOTIFY_LINK
ES_EVENT_TYPE_NOTIFY_UNLINK
ES_EVENT_TYPE_NOTIFY_OPEN
ES_EVENT_TYPE_NOTIFY_CLOSE
ES_EVENT_TYPE_NOTIFY_CREATE
ES_EVENT_TYPE_NOTIFY_WRITE
ES_EVENT_TYPE_NOTIFY_CHROOT
ES_EVENT_TYPE_NOTIFY_ACCESS
ES_EVENT_TYPE_NOTIFY_CHDIR
ES_EVENT_TYPE_NOTIFY_READLINK
ES_EVENT_TYPE_NOTIFY_READDIR
ES_EVENT_TYPE_NOTIFY_FILE_PROVIDER_MATERIALIZE
ES_EVENT_TYPE_NOTIFY_FILE_PROVIDER_UPDATE


#---Permissions---#
ES_EVENT_TYPE_NOTIFY_SETACL
ES_EVENT_TYPE_NOTIFY_SETMODE
ES_EVENT_TYPE_NOTIFY_SETFLAGS
ES_EVENT_TYPE_NOTIFY_SETOWNER


#---Attributes--#
ES_EVENT_TYPE_NOTIFY_DELETEEXTATTR
ES_EVENT_TYPE_NOTIFY_LISTEXTATTR
ES_EVENT_TYPE_NOTIFY_GETEXTATTR
ES_EVENT_TYPE_NOTIFY_SETEXTATTR
ES_EVENT_TYPE_NOTIFY_GETATTRLIST
ES_EVENT_TYPE_NOTIFY_SETATTRLIST


#---PTY---#
ES_EVENT_TYPE_NOTIFY_PTY_GRANT
ES_EVENT_TYPE_NOTIFY_PTY_CLOSE


#---IOKit---#
ES_EVENT_TYPE_NOTIFY_KEXTLOAD
ES_EVENT_TYPE_NOTIFY_KEXTUNLOAD
ES_EVENT_TYPE_NOTIFY_IOKIT_OPEN


#---Misc---#
ES_EVENT_TYPE_NOTIFY_MMAP
ES_EVENT_TYPE_NOTIFY_MPROTECT
ES_EVENT_TYPE_NOTIFY_GET_TASK
ES_EVENT_TYPE_NOTIFY_MOUNT
ES_EVENT_TYPE_NOTIFY_UNMOUNT
ES_EVENT_TYPE_NOTIFY_PROC_CHECK
ES_EVENT_TYPE_NOTIFY_UTIMES
ES_EVENT_TYPE_NOTIFY_SETTIME


#---Network---#
ES_EVENT_TYPE_NOTIFY_UIPC_BIND
ES_EVENT_TYPE_NOTIFY_UIPC_CONNECT 

For example, let’s say you want to see any time a process is created or stopped. Maybe you also want to see if a drive is mounted or unmounted. To accomplish this you could simply uncomment the following events (uncomment means making sure they don’t begin with a # symbol).

ES_EVENT_TYPE_NOTIFY_EXEC
ES_EVENT_TYPE_NOTIFY_SIGNAL
ES_EVENT_TYPE_NOTIFY_MOUNT
ES_EVENT_TYPE_NOTIFY_UNMOUNT 

Example

Let’s get a little more hands on. Here’s what it looks like when someone mounts and runs a piece of Shlayer malware while tracking these four events. Make note I’ve cleaned up some of the surrounding noise and just focused in on the good stuff.

1. {"event":"ES_EVENT_TYPE_NOTIFY_EXEC","process":{"uid":501,"ppid":21795,"original_ppid":21795,"username":"test","tty":"None","path":"/System/Library/Filesystems/hfs.fs/Contents/Resources/mount_hfs","command":" /sbin/mount_hfs -u 501 -g 20 -m 755 -o nodev -o noowners -o nosuid -o rdonly -o quarantine /dev/disk4s1 /Volumes/Install Flash Player","pid":21796},"timestamp":"2021-10-12 11:22:12"}

2. {"event":"ES_EVENT_TYPE_NOTIFY_MOUNT","mount":{"path":"/Volumes/Install Flash Player","proc_path":"/System/Library/Filesystems/hfs.fs/Contents/Resources/mount_hfs","device":"/dev/disk4s1","pid":21796},"timestamp":"2021-10-12 11:22:12"}

3. {"event":"ES_EVENT_TYPE_NOTIFY_MOUNT","mount":{"path":"/private/var/folders/ys/7s0k9bj56s1f6lspzq0c93qh0000gn/T/AppTranslocation/83A7C18B-CFB0-4218-89A1-68E9053ACECA","proc_path":"/usr/libexec/lsd","device":"/Volumes/Install Flash Player/Sgh7g/s1yT.app","pid":767},"timestamp":"2021-10-12 11:22:16"}

4. {"event":"ES_EVENT_TYPE_NOTIFY_SIGNAL","signal":{"sig":19,"proc_path":"/System/Library/CoreServices/launchservicesd","target_path":"/bin/sh","pid":374,"target_pid":21797},"timestamp":"2021-10-12 11:22:16"}

5. {"event":"ES_EVENT_TYPE_NOTIFY_SIGNAL","signal":{"sig":9,"proc_path":"/usr/libexec/syspolicyd","target_path":"/bin/sh","pid":496,"target_pid":21797},"timestamp":"2021-10-12 11:22:18"}
 

Lets break down what’s happening here line by line.

  1. We see the mount command execute (The dmg was double clicked)
  2. We see a new drive was mounted at “/Volumes/Install Flash Player”. As I’ve stated in nearly every talk, many users often fall victim to the fake Flash Player trick where they think they are installing Flash, but really it’s something malicious.
  3. We see another mount. We see the words “AppTranslocation” in the path which tells us that this mounted path was actually created by the operating system (the lsd process) so that Gatekeeper will be able to prompt the user while this application sits in a read only location and can’t be modified in the mean time.
  4. Launchservicesd sends a 19 (continue) signal to /bin/sh. This makes sense as the Shlayer malware is nothing more than a bash script.
  5. Gatekeeper (syspolicyd) then immediately sends a kill signal (sig 9) to /bin/sh as it has decided that this script should not be allowed to execute. (this is because the application isn’t signed)

If the script had been allowed to continue executing we would see a large number of “exec” events all stemming below the /bin/sh process.

But wait. There's more!

Json recorded from The ESFPlayground can also be loaded into MonitorUI. At the current moment, only the process events are supported.

Screen Shot 2021-10-12 at 4.59.34 PM

And although it’s a bit of a “beta” feature right now, you can also use MonitorUI to view the process tree of all the collected exec events.

Screen Shot 2021-10-12 at 4.58.14 PM

Down The Road

In the future I’d love to turn this into a full fledged XPC application where a system extension feeds events down to monitorUI so that users don’t have to take the extra step to load a text file. However, this would take quite a bit of time to develop. So maybe somewhere down the road. For now, this is what I have time for. Use it well and let me know about bugs. ESFPlayground is written primarily in Swift and I will at some point make it open source.

Categories: Tools