MacSecLabs
0.3Free preview
DE 00 · Module 0.3 · Beginner

Endpoint Security as a Detection Source

Endpoint Security (ES) gives an entitled client structured records about selected operations on a Mac. A detection built from ES must name the event, the fields it uses, and the client configuration that delivers it. A system supporting an event type, product subscription, and retained export are separate checks.

This module uses Apple's estrace to observe one harmless child process. That successful capture establishes the shape of an ES record. Later modules build a sensor, measure delivery, and test detection logic.

What the client receives

An ES client subscribes to specific event types. The operating system delivers es_message_t records with the actor, event payload, timestamps, and versioned fields. An authorization event asks a client for a decision before the operation completes. A notification reports an operation without asking the client to decide it.

A production client's useful data also depends on its entitlement, privileges, subscriptions, mute rules, processing capacity, retention, and export pipeline. A vendor's process feed may omit fields present in the underlying ES message. Inspect the product's actual schema before porting a rule from this course.

A custom client requires Apple's Endpoint Security entitlement and appropriate deployment. Apple's built-in estrace can follow a child on the validation VM without root. That observation does not grant a third-party application permission to subscribe system-wide.

Read the event catalog on the target build

macOS 27 event catalog
% eslogger --list-events | wc -l
% eslogger --list-events | grep -E '^(exec|open|mmap|mprotect|uipc_bind|uipc_connect|iokit_open|xpc_connect)$'
     106
exec
iokit_open
mmap
mprotect
open
uipc_bind
uipc_connect
xpc_connect

The count is the number of lines printed by this tool on build 26A434, not a promised count for every macOS version. The names are short names accepted by eslogger; they are not the C enum constants. Read the installed SDK header to determine which AUTH and NOTIFY forms exist. For example, the macOS 27 SDK declares AUTH_MMAP, NOTIFY_MMAP, AUTH_MPROTECT, NOTIFY_MPROTECT, AUTH_IOKIT_OPEN, and NOTIFY_IOKIT_OPEN.

The presence of iokit_open is especially important for this course. The SDK defines an IOKit-open event. Test the event, target, and client on the build under discussion before claiming product visibility.

Capture an execution event

Run a program with no output through a child-scoped trace, then select only the fields needed for this lesson:

child execution event
% (set -o pipefail; estrace --event-types exec /usr/bin/true 2>&1 | jq -c '{event_type, path: .event.exec.target.executable.path, signing_id: .event.exec.target.signing_id, seq_num, global_seq_num}')
{"event_type":9,"path":"/usr/bin/true","signing_id":"com.apple.true","seq_num":0,"global_seq_num":1}

event_type: 9 identifies the notification form of exec in the installed header. The target path and signing identifier belong to /usr/bin/true. The sequence values describe this trace's delivery order; one record cannot demonstrate a drop or establish lossless collection. The full JSON also contains process identities and environment values, which should be minimized before sharing a capture.

The command deliberately follows its own child. It does not observe all execution on the host. Use a privileged, entitled sensor or a product feed for fleet-wide validation.

Inspect the record before choosing fields

Do not begin a rule by copying field names from another product. Ask the source what the macOS 27 record contains. The following query prints only key names, so audit-token values and environment data do not enter the course evidence:

inspect the exec record schema
% estrace --event-types exec /usr/bin/true 2>&1 |
% jq -c '{top:(keys),
% process:(.process|keys),
% target:(.event.exec.target|keys)}'
{"top":["action","action_type","event","event_type","global_seq_num","mach_time","process","schema_version","seq_num","thread","time","version"],"process":["audit_token","cdhash","codesigning_flags","cs_validation_category","executable","group_id","is_es_client","is_platform_binary","original_ppid","parent_audit_token","ppid","responsible_audit_token","session_id","signing_id","start_time","team_id","tty"],"target":["audit_token","cdhash","codesigning_flags","cs_validation_category","executable","group_id","is_es_client","is_platform_binary","original_ppid","parent_audit_token","ppid","responsible_audit_token","session_id","signing_id","start_time","team_id","tty"]}

The top-level process is the actor that caused the exec operation. The event.exec.target object describes the new process image. Treating those objects as interchangeable can reverse an investigation. For example, a trusted launcher in process can execute an unfamiliar target, while an untrusted actor can request execution of a platform binary.

Fields have different jobs:

Field groupDetection use
audit_token, start_time, session_idCorrelate identity while avoiding PID reuse
executable.path, signing_id, team_id, cdhashDescribe the actor or target image
parent_audit_token, responsible_audit_token, original_ppidReconstruct launch responsibility beyond one parent edge
seq_num, global_seq_numDetect possible delivery gaps within their documented scope
version, schema_versionSelect fields that exist in the received record

Normalize the fields your own sensor exports and retain the original event for forensic review. Do not hard-code numeric event_type values as the primary rule interface when a stable normalized event name is available.

AUTH and NOTIFY have different contracts

An AUTH event arrives before the protected action is decided. The client must reply before the event's deadline. A NOTIFY event describes an action without a response from the client. The event name alone does not say whether the action succeeded; read the event payload and result fields relevant to that operation.

Slow clients, full queues, missed deadlines, and process restarts have different consequences. Do not reduce those conditions to "AUTH never drops" or "NOTIFY always drops silently." DE 01 measures sequence behavior and recovery with a test client, then defines what the result permits you to claim. A gap in a sequence number is evidence that records may be missing. It cannot reconstruct the missing actions.

Event families and limits

QuestionES candidateAdditional source to consider
Which binary executed?EXEC, FORK, EXITShell history or application log for context
Which file operation occurred?OPEN, CREATE, RENAME, UNLINK, CLOSEResulting file and filesystem metadata
Was memory mapped or reprotected?MMAP, MPROTECTProcess memory analysis, when authorized
Was a Unix-domain socket used?UIPC_BIND, UIPC_CONNECTDaemon and XPC service inventory
Was a user client opened?IOKIT_OPENIORegistry, driver logs, entitlement checks
Was an XPC connection attempted?XPC_CONNECTService-side logs and request semantics
Was a TCP connection made?No general ES TCP flow eventNetwork Extension, firewall, DNS, proxy, packet capture

An ES event for a Unix-domain socket does not provide general TCP connection telemetry. Likewise, an XPC connection record does not reveal the meaning of every message sent over that connection. Correlate process identity, destination, time, and a second source before claiming a network or IPC technique was detected.

The event catalog changes across OS releases. The schema version in a message and the SDK's availability annotations matter when a rule moves between fleet populations. DE 01 turns those details into a version-aware sensor contract.

State the coverage claim precisely

For the command above, a defensible statement is:

On macOS 27.0.1 build 26A434, the child-scoped estrace run delivered one exec notification for /usr/bin/true, including its path and signing identifier.

Fleet coverage, EDR subscription, queue health, and network visibility each need their own collection test.

Detection engineering

An ES-based rule is supported by a subscribed event, an observed message, and a validated export path. The child trace demonstrates one exec notification. Later labs test delivery under load and correlate ES records with other sources.

What Comes Next

Module 0.4 uses Unified Logging as a separate source. It checks actual messages before treating a predicate as a detection signal.

Continue macOS Detection Engineering

These foundation modules are open as a preview. Full modules, lab downloads, progress tracking, and certificate workflow require active course access.

Get full access