Of Mace and Club, or borrowing Pike's tale

macOS forensics remains a rare specialisation.

Very few experienced analysts on the market carry it, and in a small team still in its build phase, it is expensive to hire for and slow to train.

Meanwhile the actual macOS triage loop looked like this: pull a collection off the host, open six terminal tabs in a row, grep strings, remember that LC_FUNCTION_STARTS exists, lose forty minutes to a base64 chain, write the findings into a document by hand. Besides, for half a day of analysis, expect two hours of transcription.

In the AI era, the notion of speed is tumbling down. Something had to be done.

🐟 The origin is a fish

A northern pike swimming among weeds

The idea is not ours. On 23 April 2026, Synacktiv published Pike, an experimental LLM agent for Linux execution traces. The architecture is three moves long:

  1. strace records every syscall a program makes.
  2. The trace is indexed into SQLite with FTS5 full-text search over arguments and paths.
  3. An LLM agent gets a read-only connection and writes its own SQL.

What I found compelling was the third move. Pike does not hand the model a set of high-level abstractions like "list the network connections". It hands it the schema and a database, and lets it decide what to ask. The reasoning belongs to the model, the facts belong to the store.

That inverts the usual failure. Most attempts at AI-assisted analysis stuff evidence into a context window and hope. Pike keeps hundreds of thousands of syscalls in a queryable store and spends context on questions instead.

I wanted this for macOS.

🔨 Why macOS needed two tools instead of one

There is no strace on macOS. ptrace is crippled, dtrace is fenced off by System Integrity Protection (SIP), and the sanctioned telemetry source is the Endpoint Security framework (ES).

ES is (or at least should be) the same plumbing every commercial macOS EDR sits on, and Apple gates it behind an entitlement you do not get for a side project.

Mace

So the runtime tracer, mace, runs in a VM in Reduced Security with the AMFI bypass active, which is what makes the entitlement assertion pass. It subscribes to 29 ES event types covering process lifecycle, file operations, code-injection observables, IPC, and identity and persistence events, then normalises everything into a SQLite database alongside a filtered slice of the Unified Log.

                     ┌──────────────────────┐
  sudo mace run      │ native ES subscriber │
  -- <sample>   ────►│ (root + AMFI bypass) ├──► ES NDJSON ──┐
                     └──────────────────────┘                │
                                                              ▼
                     ┌──────────────────────┐    ┌───────────┬────────┐
                     │ log stream (filtered)├───►│   async writer +   │
                     └──────────────────────┘    │  SQLite normaliser │
                                                 └─────────┬──────────┘
                                                           │
                                                           ▼
                                                 manifest.json   (run-level facts)
                                                 trace.db        (queryable)
                                                 *.ndjson.zst    (raw archive)

Same shape as Pike, different sensor: mace run -- <argv> to spawn and trace, mace attach <pid> to pick up a detonation that already forked away from you, then a bundled skill that answers analyst questions against trace.db.

The second tool exists because Pike has no static half, and on macOS the static half is where most of the answer lives. In the macOS realm, a typical stealer is a signed .pkg wrapping an .app wrapping a universal Mach-O with an AppleScript payload three base64 layers down. You need to know what a sample is before you spend a detonation on what it does.

Club

club does that. It recursively unpacks .dmg, .pkg, .app, .zip and universal Mach-O, then gathers entitlements, signing and notarization verdicts, imports, Objective-C class dump, Swift type detection, per-section entropy with a packer deny-list, and deterministic base64 chain decoding. Last but not least, it is capable of XOR and affine cipher recovery, .pyc and AppleScript decompilation, and comes with an 18-pattern anti-analysis library. Output is one report.json plus verbatim tool stdout in raw/ and deobfuscated layers in extracted/.

Both tools ship a skill with reference docs loaded on demand, including one I believe mandatory: a blind-spots.md that states what the tool cannot see. Writing that file down is what stops the agent from inferring past the evidence.

Together they took macOS triage from a half-day session to roughly 60 minutes end to end.

🪖 Plug, baby plug!

Two tools do not make a response capability. Watson, our IR agent, is what sequences them effectively, against a NIST-like five-phase runbook, whose grammar is very well-known among the DFIR community.

Watson is our agentic orchestrator, not an analyst, built on a set of narrow, single-purpose skills. It reads which phase we are in, restates the goal of that phase, and runs an OODA loop dispatching sub-agents for DFIR analysis, threat intelligence, malware analysis and reporting. Each of them comes with its own scaffolding and templates to follow.

When the investigation needs to know what a dropped binary is, Watson stops and asks the analyst to pull the sample and run club on it in the VM. The artifact lands in the shared folder, the analyst points the session at that directory, and club's bundled skill answers from there. Same handoff for mace on the runtime side.

That handoff is the design. Each tool answers only against its own store, with its own schema and its own blind-spots file. Watson holds the phase goal and the timeline, does the transcription, lets the analyst challenge the hypothesis, and never touches the evidence directly.

After a few incidents behind us, I can measure Pike's real contribution as the contract that structures the agent's work. It helps us bind pieces together into a coherent workflow that greatly enhances our security posture.

Thanks @Synacktiv for this idea.