monitor macOS for malicious activity
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Mk Merge release 0.1.7 into develop Sep 21, 2018
extra/splunk Improve docs Jul 24, 2018
kext Avoid warnings about alignment by checking instead of packing Oct 5, 2018
pkg Do not include any non-Apple default suppressions Nov 5, 2018
test Work around removal of security/mac.h Dec 16, 2018
.gitignore Automate plist generation, fixes file/symlink.test Aug 11, 2018
.travis.yml Add xcode10 and remove xcode9.3 Sep 21, 2018
AUTHORS.md Add CONTRIBUTING.md Jul 24, 2018
CONTRIBUTING.md Describe branching model used Jul 24, 2018
GNUmakefile Add buttons Dec 16, 2018
LICENSE xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
LICENSE.contrib xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
LICENSE.third Merge release 0.1.7 into develop Sep 21, 2018
NEWS.md Merge branch 'master' into develop Nov 7, 2018
README.md Add buttons Dec 16, 2018
aev.c Push env reduction into aev_new and omit empty env Jul 28, 2018
aev.h Push env reduction into aev_new and omit empty env Jul 28, 2018
atomic.h Improve atomics compat layer Nov 5, 2018
attrib.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
auclass.c Handle AUE_UNLINK in symlink management Aug 25, 2018
auclass.h Initial set of socket events: bind(exp), accept, connect Aug 1, 2018
auditdump.c Add -v for printing auditpipe stats before and after Dec 16, 2018
auevent.c Handle multiple text tokens in events, such as SecSrvr AuthEngine Aug 26, 2018
auevent.h Handle multiple text tokens in events, such as SecSrvr AuthEngine Aug 26, 2018
aupipe.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
aupipe.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
aupolicy.c Watchdog timer for reacting to audit(4) policy clobbering Jul 29, 2018
aupolicy.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
build.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
build.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
cachecsig.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
cachecsig.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
cachehash.c Mutex should have been static all along Jul 25, 2018
cachehash.h Consider nanoseconds in cachehash Jul 23, 2018
cacheldpl.c Mutex should have been static all along Jul 25, 2018
cacheldpl.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
cf.c Push env reduction into aev_new and omit empty env Jul 28, 2018
cf.h Do not validate resources and support code sig acquisition from pid Jul 23, 2018
chkcs.c Various documentation improvements Jul 29, 2018
codesign.c Suppress debug message on errSecCSBadObjectFormat Aug 26, 2018
codesign.h Do not validate resources and support code sig acquisition from pid Jul 23, 2018
config.c Revert accidental macro rename Aug 26, 2018
config.h Rename strset to setstr Aug 18, 2018
debug.c Make DEBUG() facility thread-safe Jul 25, 2018
debug.h Make DEBUG() facility thread-safe Jul 25, 2018
evtloop.c Merge branch 'master' into develop Nov 7, 2018
evtloop.h Detect radar 43151662, linkat(2) without destination path Aug 10, 2018
filemon.c Unlink target if obj has one before changing to regular file Nov 7, 2018
filemon.h Handle AUE_UNLINK in symlink management Aug 25, 2018
hackmon.c Merge branch 'master' into develop Nov 7, 2018
hackmon.h Merge branch 'master' into develop Nov 7, 2018
hashes.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
hashes.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
ipaddr.c Improve socket related core and detect raw sockets Aug 6, 2018
ipaddr.h Improve socket related core and detect raw sockets Aug 6, 2018
kextctl.c Reimplement kext loading using c API Jul 27, 2018
kextctl.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
kqueue.c Remove priority function mechanism from kqueue subsystem Jul 25, 2018
kqueue.h Remove priority function mechanism from kqueue subsystem Jul 25, 2018
log.c Track sockets per process and revamp socket events Aug 6, 2018
log.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
logdst.h Refactor log destinations Jul 26, 2018
logdstfile.c Refactor log destinations Jul 26, 2018
logdstfile.h Refactor log destinations Jul 26, 2018
logdststdout.c Refactor log destinations Jul 26, 2018
logdststdout.h Refactor log destinations Jul 26, 2018
logdstsyslog.c Refactor log destinations Jul 26, 2018
logdstsyslog.h Refactor log destinations Jul 26, 2018
logevt.c Merge branch 'master' into develop Nov 7, 2018
logevt.h Track sockets per process and revamp socket events Aug 6, 2018
logfmt.h Add xml log format Jul 26, 2018
logfmtjson.c Add xml log format Jul 26, 2018
logfmtjson.h Add json-seq log format as defined in RFC 7464 Jul 8, 2018
logfmtxml.c Various documentation improvements Jul 29, 2018
logfmtxml.h Add xml log format Jul 26, 2018
logfmtyaml.c Add xml log format Jul 26, 2018
logfmtyaml.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
logutl.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
logutl.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
lrucache.c Deduplicate hash table sizing Jul 29, 2018
lrucache.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
map.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
memstream.c Reverting 683333e Jul 14, 2018
memstream.h Reverting 683333e Jul 14, 2018
minmax.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
mklaunchdplist.c Integrate launchd.c into mklaunchdplist.c - there no other callers Aug 23, 2018
os.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
os.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
policy.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
policy.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
proc.c Fix memory leak in open file tracking Aug 26, 2018
proc.h Trigger open fd also when reusing an already existing ctx Aug 15, 2018
procmon.c Merge branch 'master' into develop Aug 26, 2018
procmon.h Rename strset to setstr Aug 18, 2018
queue.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
queue.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
setstr.c Fix one-time memory leaks in initialization of setstr_t Aug 26, 2018
setstr.h Rename strset to setstr Aug 18, 2018
sockmon.c Silence bind()/listen()/accept()/connect() on non-AF_INET[6] sockets Sep 2, 2018
sockmon.h Track sockets per process and revamp socket events Aug 6, 2018
str.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
str.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
sys.c Revert accidental change of rerrno to bool Nov 5, 2018
sys.h Fix initial symlink loading Aug 25, 2018
time.c Improve procmon debugging and remove time check Jun 24, 2018
time.h Improve procmon debugging and remove time check Jun 24, 2018
timeops.c Do not validate resources and support code sig acquisition from pid Jul 23, 2018
tommy_ext.h Fix one-time memory leaks in initialization of setstr_t Aug 26, 2018
tommychain.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
tommyhash.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
tommyhash.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
tommyhashdyn.c Add tommyhashdyn Aug 18, 2018
tommyhashdyn.h Add tommyhashdyn Aug 18, 2018
tommyhashtbl.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
tommyhashtbl.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
tommylist.c xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
tommylist.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
tommytypes.h xnumon 0.1.0 initial release at a41con.ch Jun 14, 2018
work.c Allow configuration of events that should be logged Jun 24, 2018
work.h Allow configuration of events that should be logged Jun 24, 2018
xnumon.c Watchdog timer for reacting to audit(4) policy clobbering Jul 29, 2018

README.md

xnumon - monitor macOS for malicious activity

https://www.roe.ch/xnumon

Build status Gitter chat

Overview

xnumon is a monitoring agent that produces system activity logs intended to be suitable for monitoring potentially large fleets of macOS systems for malware and intrusions. It aims at providing similar capabilities on macOS that sysmon provides on Windows.

Currently implemented are the following log events:

  • xnumon-ops[0] and xnumon-stats[1]: for in-band monitoring of agent status and activity metrics. *
  • image-exec[2]: a process has replaced its executable image as a result of calling execve(2) or posix_spawn(2). *
  • process-access[3]: a process has accessed and possibly manipulated another process using either task_for_pid or ptrace(2). *
  • launchd-add[4]: a process has added or modified a launch daemon or launch agent plist. 
  • socket-listen[5]: a process has started listening on a socket. *
  • socket-accept[6]: a process has accepted an incoming connection. *
  • socket-connect[7]: a process has initiated an outgoing connection. 

* stable
experimental and under active development
stable, but limited to blocking sockets due to an unresolved bug in audit(4)

xnumon provides context information such as executable image hashes, code signature meta-data, script shebang handling, and the history of previous executable images that led to the current process state. It does so by tracking fork and other syscalls instead of relying only on the ppid, which can change over the lifetime of a process. For the reliable acquisition of image hashes even from short-living or self-modifying executables, xnumon comes with an optional kernel extension.

xnumon is configurable. It supports different log formats and hash algorithms. In order to reduce log volume close to the source, xnumon implements a number of suppression mechanisms and allows tuning the level of information per event. The log subsystem was designed to be easy to extend with custom log drivers.

Requirements

A supported version of OS X or macOS, currently:

  • OS X 10.11 El Capitan
  • macOS 10.12 Sierra
  • macOS 10.13 High Sierra
  • macOS 10.14 Mojave

Releases of xnumon are considered safe to deploy in production environments.

Documentation

See the xnumon wiki for further documentation. While the wiki is still work in progress, some useful starting points:

  • cat /var/log/xnumon.log | jq 'select(.eventcode==0)'
  • xnumonctl
  • xnumon -h
  • dmesg | grep xnumon

Installing

The installer package published on the xnumon website will install the daemon, the control utility and a default configuration which by default will log to /var/log/xnumon.log in JSON Lines format. It will also install a matching newsyslog configuration and the kernel extension.

As of macOS 10.13 High Sierra, the kext needs to be explicitly approved by the user before it can be loaded. For enterprise deployments, you will want to allow the Team ID C9BFEG985N to bypass user approval using spctl kext-consent from Recovery OS or NetBoot/NetInstall/NetRestore images, or using Mobile Device Management (MDM). For details, refer to TN2459.

The extensively commented default configuration is installed to /Library/Application Support/ch.roe.xnumon/configuration.plist-default. While the defaults are as sensible as possible, you will most likely want to maintain a custom configuration at /Library/Application Support/ch.roe.xnumon/configuration.plist to be used in favour of the default configuration, especially for enterprise deployments.

In addition to installing xnumon, you will want to make sure that auditd does not clobber the global kernel audit policy. Make sure the argv policy flag is enabled in /etc/security/audit_control, which is the default. If you are using envlevel dyld or full, then arge is needed in addition to argv.

In order to make the logs useful and to get them out of reach of malware and attackers, it is recommended to continuously forward logs to central log collection infrastructure. A minimal sample Splunk configuration for ingesting xnumon logs can be found in extra/splunk.

Uninstalling

xnumonctl uninstall

This will remove all traces of this package from your system, including logs at the default location /var/log/xnumon.log*, but not including the config at /Library/Application Support/ch.roe.xnumon/configuration.plist unless it is the same as the default config.

Build Dependencies

Building an unsigned userland binary and kernel extension requires Xcode command line tools. The userland binary requires only the CoreFoundation and Security frameworks and libbsm; there are no third-party dependencies.

Building a signed userland binary requires an Application Developer ID certificate from Apple.

Building a signed kernel extension requires a Kext Developer ID certificate from Apple.

Building signed binary packages requires pandoc and an Installer Developer ID certificate from Apple.

Debugging

Use make test while xnumon is logging to /var/log/xnumon.log to execute a set of automated test cases, exercising different APIs and automatically checking the log file for the expected events. Submitting a pull request with a failing testcase is the best way to report bugs.

Use the metrics in eventcode 1 events to monitor xnumon internals, possibly reducing the interval it gets generated in the configuration.

Enable debug in the configuration and run xnumonctl logstderr to change the launchd plist for xnumon to send stderr to /var/log/xnumon.stderr. This will allow you to get context information for fatal events that would otherwise only be visible in one of the eventcode 1 metrics.

For short-term debugging during development you can also just unload xnumon using xnumonctl unload and run xnumon with -o debug=true on the command line.

Pass DEBUG=1 to make in order to build a debug version of xnumon that includes symbols, assertions and additional debugging code. See make file for details.

To load an unsigned, modified kext for testing and development, you need to disable System Integrity Protection (SIP) for kexts. Reboot to Recovery OS by pressing cmd⌘+r during boot and from within the repair console, run csrutil enable --without kext. This will also turn off the kext user consent requirement of High Sierra and later.

Copyright and License

Copyright (c) 2017-2018, Daniel Roethlisberger.
All rights reserved.
Licensed under the Open Software License version 3.0.
Contains components licensed under BSD and MIT licenses as well as components released under the Unlicense.

See LICENSE, LICENSE.contrib and LICENSE.third as well as the respective source file headers for details.

Sponsoring

If you are interested in supporting the development and maintenance of xnumon, contact me.