I'm working on a System Extension that uses the EndpointSecurity framework to monitor various events. For some events, we're using ES_EVENT_TYPE_AUTH_*
events, and actively preventing certain changes. All this works fine, while the extension is running.
This is not an anti-virus product, but is similar enough that it might help to think of it that way for purposes of this discussion.
Much like any anti-malware tool, we'd like for the System Extension to be resilient to malicious processes, even processes running as root. If any random process that gets root can do the equivalent of kill -9 <my extension>,
or systemextensionsctl uninstall <my extension>,
then it's easy enough for them to kill the extension, then do something we would otherwise prevent.
It's also possible for an end user to drag-uninstall the app, which disables the extension immediately, before we even have a chance to respond to any changes.
I know that various anti-virus software for Macs address this, and prevent a user from, for example, using sudo kill -9 <pid>
to disable them. How is that typically done?
Some possible approaches could be:
- Have two processes that watch each other, and restart each other if killed. There's a timing issue there that I'm not sure is easy to resolve, and I haven't tried launching a detached process from a system extension - that might not even work. I could have a separate launchdaemon which periodically checks to see if the extension (and app) are installed, and reinstalls them if they're missing. That leaves plenty of time for mischief to occur, but at least I'd have a window to detect it.
- It sounds like the
NSEndpointSecurityRebootRequired
Info.plist key might have some effect here, in that it prevents an extension from being replaced until a reboot. I should check and see what effect if any this has on removing the app or killing the extension. - Maybe there's a System Profile setting that could be set through an MDM to prevent the application from getting uninstalled? I don't know my way around profiles very well, and I doubt this would address the "kill" issue, in any case.
- Probably there's some lower-level BSD or Mach API that could prevent attempts to kill the process. I could make a kernel extension for just this one thing, maybe using kauth(), but that seems overkill, and kernel extensions are not the Apple-suggested way to do anything these days. If EndpointSecurity is intended to replace using kexts for anti-malware and detection uses, there must be a way to do this inside a system extension, right?
So, yeah - preventing the user from doing something is going against the spirit of "do what you like with your own computer, especially if you have admin powers", but this software is typically going to be installed by corporate IT, not end users, and some end users "need" admin permissions (e.g. software developers)...
Any suggestions would be appreciated.