Question

I am trying to write kext for Mac OS X which will get notified when any process is started.

In Windows you can do this by calling PsSetLoadImageNotifyRoutine(...) and specify callback which will be called when the process is starting. This is documented way and it works in all Windows starting from Win 2k.

Is there anything similar for Mac? It seems like this is possible to achieve using kauth process listeners, but process scope has never been implemented in OS X.

Another alternative is to hook SYS_execve and friends, but this is undocumented and unsupported way. I really don't want to go this way.

I don't need any cancelling - just want to be notified when process is started, and get it's pid & path.

Était-ce utile?

La solution

Well, your question is a bit ambiguous.

Being "notified when any process is started" IMHO means the fork syscall, not execve. However I have no idea if you can be notified on fork by any official API.

If the execve is what you are interested in, take a look at the kernel authorization (kauth) API.

You can register in KAUTH_SCOPE_VNODE and track for KAUTH_VNODE_EXECUTE to be notified before the execve performs (and possibly deny it to succeed by return value from your callback); or register in KAUTH_SCOPE_FILEOP and track for KAUTH_FILEOP_EXEC to be notified after the execve() is performed.

Autres conseils

Old question - but - The answer stating SYS_execve hooking is the only way to be notified is incorrect and dangerous. For one, the sysent table is not exported (though arguably it can be found fairly easily). For two, you have to patch the memory and ensure it's rw.

A MUCH better way, in a kext, is to use the MAC framework (that would be Mandatory Access Control). That's in the XNU sources, in the /security branch. The MAC Framework was designed for exactly this kind of operations - i.e. notifications/hooking without actual function or address overwrite, but with callouts. This is also detailed in a book titled "Mac OS X and iOS Internals", Chapter 14.

SYS_execve hooking is only way to be notified when any process is started. Also, you could try to use DTrace and libdtrace for receiving process started notification; I've been trying that way but without success.

For anyone finding this question after 2019:

Apple has a relatively new (macOS 10.15+) C framework called Endpoint Security which provides process lifecycle events (among other things) and can be consumed either by a user mode daemon or a new "System Extension" (successor to the "Kernel Extension") provided the proper code signing entitlements are secured from Apple. Some notable features are:

  • Efficient / Event-driven model (es_new_client())
  • Granular event type subscription model (e.g. ES_EVENT_TYPE_NOTIFY_EXEC, ES_EVENT_TYPE_NOTIFY_FORK, ES_EVENT_TYPE_NOTIFY_EXIT via es_subscribe())
  • rich event context including pid, uid, and much more (e.g. An event message for process creation (es_event_exec_t) includes an es_process_t field with process details including executable path)
  • Events can be 'muted' (masked) based on source (parent) process (e.g. es_mute_process()) to help with signal v. noise and performance impact.

Apple has been pushing developers to adopt this new framework for a while now in favor of previous monitoring APIs (like KAUTH, MAC and OpenBSM (/dev/auditpipe)) so it's the only solution I can recommend investing in going forward.

There are some WWDC sessions and example projects available on the subject: https://developer.apple.com/documentation/endpointsecurity/monitoring_system_events_with_endpoint_security

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top