How Antinomie works
Antinomie runs a Linux program in a QEMU virtual machine on your own computer and observes it from inside the guest kernel. The host app keeps what the kernel reports, captures the VM’s network traffic from outside, and analyses the evidence in sandboxed workers.
Guest VM QEMU, one per VM
Host Linux x86-64, your user, no root
The guest kernel recorder
Section titled “The guest kernel recorder”Every base boots a patched Debian Linux 6.12.94 kernel. The patches add a recorder to the kernel itself. For each program you run, its descendants, a process you attach to, or all of userspace with Capture all, the recorder writes:
- each system call, at entry and exit, with its arguments, its return value and the bytes it passed: paths, buffers read and written, socket addresses, structures. Inputs that were not resident at entry are read again at exit;
- records beside the calls: process creation and exit, the credentials a task ran as, the SHA-256 of files the program ran, wrote or deleted, the interpreter of an executed script, the file requests of io_uring and AIO, and the guest’s own RAM and disk use for the Summary;
- from a revision-18 base New in 0.8.0, the
position a read or write used in its file, the operands of in-kernel copies
(
sendfile,splice,copy_file_range, clones,fallocate) and the pages written back through shared file mappings.
Memory can change while it is read, so a captured value carries a capture status, and bytes the recorder could not read stay marked as missing instead of guessed. What the recorder does not see is listed in Known gaps.
The same kernel carries a debug engine for the
Debugger tab: breakpoints, stepping, threads and
memory without ptrace, so TracerPid stays 0 and the sample’s own
PTRACE_TRACEME succeeds. gdb and the GEF or pwndbg console run on the host and
talk to it through a local server.
Each base records a guest contract revision, the version of what its kernel offers the host: 0.7.1 uses revision 17, 0.8.0 revision 18. The app asks the guest what it supports before using an addition, so an older base keeps working with fewer records. See Compatibility.
The shared-memory transport
Section titled “The shared-memory transport”Records leave the guest through one ring buffer per virtual CPU in guest RAM. QEMU keeps the VM’s RAM in a file in the VM’s private runtime folder (mode 0700); the host app maps the data rings read-only and a small control region read-write, and parses every record in its own process with bounded, checked parsing. Commands (upload, run, terminal input, signals, shutdown) and their replies travel through the control region. No network, no shared folder and no device file in the guest is involved.
When a ring is full, When buffers fill in the VM’s telemetry transport settings decides:
| Mode | What happens | Cost |
|---|---|---|
| Never drop (default) | The system call waits until the host has room, up to Longest wait per event (5 s by default) | Heavy tracing can slow the guest; a wait that runs out still drops, and is counted |
| Drop new telemetry | The guest never waits | The guest keeps its timing; what did not fit is counted as lost |
The ring size (Guest buffer per vCPU, 256 KiB to 4 MiB, 1 MiB by default) decides how long a burst the guest can ride out.
Loss accounting
Section titled “Loss accounting”Nothing is dropped silently. The status bar counts loss at each stage, and the Summary’s health card breaks it down:
| Counter | Where the loss happened |
|---|---|
| TRL | In the transport: records the guest could not hand over |
| UIL | In the window: preview rows the interface could not display (the recording is unaffected) |
| STL | On disk: data that could not be saved |
| Guest hash / credential drops | Records the guest tracer could not send |
From 0.8.0 New in 0.8.0 the host also times each pause between its reads of the rings and records its cause, so a guest drop can be tied to what held the host up. A missing event is never proof that something did not happen; see Loss counters and Recording incomplete.
The host app
Section titled “The host app”The host app is a native Rust desktop application (egui) that runs as your user, without root. It starts and stops QEMU, attaches to the transport, assembles records into calls, writes recordings, runs the per-run network gateway, and draws every view: Run History, Syscall Trace, Triage, Network, Memory, Disks, Core dumps, Static Analysis and the Debugger. Only one VM runs at a time.
Recordings and the object store
Section titled “Recordings and the object store”Everything a run produced is saved as it arrives, so a run can be reopened from
Run History long after the VM is stopped or deleted. A run folder holds the
raw telemetry in order, the run’s summary and health, its terminal output, and
an object store (objects/): captured buffers packed into segment files
with an index, which Triage, File Reconstruction and the Syscall Trace read
back byte for byte. Network captures, memory dumps, process cores and disk
dumps sit beside the runs, and a recording quota (4 GiB per boot by
default) bounds what one boot may save.
From 0.8.0 New in 0.8.0 a boot’s recording also keeps the earlier bytes of the files its runs changed, copied from the disk the boot started from, and the sample library keeps an encrypted archive of every sample. See Data folders and run layout and Live versus saved recordings.
Sandboxed workers
Section titled “Sandboxed workers”Host tools that read hostile data run in a bubblewrap sandbox:
| Component | Where it runs | Handles |
|---|---|---|
| Static analysis: built-in ELF, PE and Mach-O parsing and strings, capa, FLOSS, UPX, Detect It Easy, Ghidra | bubblewrap | The specimen |
| Properties (hashes, ssdeep, TLSH, Magika) and detection (YARA, Sigma, Suricata) | bubblewrap | Specimens, recordings, captures |
| TShark: packet list, display filters, network triage | bubblewrap and prlimit, as user 65534 |
Packet captures |
Disk browser, and qemu-img for imported qcow2 images |
bubblewrap and prlimit |
Disk images |
| MemNixFS | bubblewrap | Memory dumps |
| Volatility 3 and its community plugins | Your user, no sandbox | Memory dumps |
| gdb console (GEF or pwndbg) | Your user, no bubblewrap; cleared environment, private home | The debugged guest process |
| Open in Wireshark | Your user, no sandbox | The capture |
The sandbox unshares every namespace (network included), drops all
capabilities and clears the environment. Inside are only /usr, a few
read-only /etc entries, a private /etc/passwd, a minimal /dev, /proc and
a size-limited /tmp; your home, the data directory, /run, X11, D-Bus and
/dev/shm are not visible. Each tool gets its input read-only and one folder
to write to, with address-space, open-file and time limits. If bubblewrap
cannot start, the analysis fails with that reason instead of running
unsandboxed. See the security model.
Network capture and routes
Section titled “Network capture and routes”Packets are captured outside the guest, on the VM’s network interface, so the sample cannot hide them from the capture. Each VM has one network mode:
| Mode | What the guest gets |
|---|---|
| Disconnected (default) | No network card, nothing to capture |
| Isolated | A card and an address; QEMU forwards nothing |
| Routed | A card wired to Antinomie’s own gateway in the host app; each run picks a route |
| NAT (Internet) | QEMU user-mode networking without restriction; the least isolated mode |
On a Routed VM the run’s route is None (drop), InetSim, Internet, Tor, VPN (WireGuard) or SOCKS5 proxy, all without root, firewall rules or a VPN client on the host. A route that cannot start stops the run; Antinomie never falls back to another route. With a Cloud VPS profile New in 0.8.0 the gateway also answers the provider’s metadata address itself. See Network routes and Network isolation.
What never runs in the guest
Section titled “What never runs in the guest”- No agent or monitor process. The recorder is part of the kernel; nothing is started in the guest to watch the program. On bases built before 0.7.0 only, a temporary collector is uploaded to measure guest RAM and disk.
- No
ptrace, for tracing or for the debugger. - No shared host folder. Files reach the guest only through Upload file or the Upload source of Run program, and an upload never runs the file.
- No analysis tool. Static analysis, rule scans, packet parsing and disk reading all happen on the host, on the saved evidence.