Skip to content

Siemphony is in beta and still being built. What ships today, and what does not.

Siemphony’s repertoire

Kernel module loaded or the module tree modified on Linux

Siemphony@siemphonylowT1547.006unverified
Covers both halves of AN1243 on the one log source they share: an auditd SYSCALL record whose `exe` is a module-management tool, and an auditd PATH record naming a kernel object file or anything inside the module tree. The path half is MITRE's `FilePathRegex` knob, populated here with the `/lib/modules/` substring — a substring rather than a prefix so that distributions which ship the tree at `/usr/lib/modules/` are included — plus the kernel object suffixes themselves, and those are listed as `.ko`, `.ko.xz`, `.ko.zst` and `.ko.gz` because most current distributions install modules compressed and a bare `.ko` endswith silently misses every one of them. The tool half needs the same care in the other direction: on Debian, Ubuntu, RHEL, Fedora and Arch, `insmod`, `rmmod`, `modprobe`, `depmod`, `lsmod` and `modinfo` are all symlinks to a single `kmod` binary, and auditd resolves `exe=` to the executable that was actually mapped, so a selector listing only `/insmod` and `/modprobe` is dead on a modern host. `/kmod` is therefore in the list, and the price of including it is that the read-only queries `lsmod` and `modinfo` match exactly as a load does. Four limits are worth stating before this is deployed. First, the loading paths that skip the tools entirely are missed: `systemd-modules-load` and `systemd-udevd` call `finit_module` directly at boot, and a rootkit dropper that calls `init_module` from its own compiled code execs nothing at all, so the SYSCALL leg never sees either. Second, the `.ko` selection is only as good as the audit configuration behind it — a PATH record is emitted for an audited syscall or a watched path, so a module staged in `/tmp` and loaded from there produces no PATH record unless `openat` is audited globally, which almost nobody does for cost reasons. Third, MITRE's `UserContext` knob cannot be applied inside this rule: auditd splits one event across records and `uid`/`auid` live only on the SYSCALL side, so the PATH selections have no user to filter on. Fourth, MITRE's `TimeWindow` knob is a change-window suppression, which lib/sigma has no way to express. The macOS arm AN1244 is not attempted — its sources are `macos:unifiedlog` and `macos:osquery`, neither of which has a standardised Sigma field vocabulary, so `kextload`, the `/Library/Extensions` write and the KextPolicy database change would all have to be written against invented field names; that is the same ground on which T1543.001 and T1546.014 declined their macOS legs. The osquery leg of AN1243 is unattempted for the same reason. Prerequisite: auditd ships with no rules loaded on any mainstream distribution, so this rule returns zero rows until both an execve rule such as `-a always,exit -F arch=b64 -S execve -k exec` and a watch such as `-w /lib/modules -p wa -k modules` are in place — and zero rows reads as quiet when it actually means blind. The watch permission also sets the noise floor: `wa` records writes and attribute changes only, whereas adding `r` makes every module the kernel loads on demand match as well. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0450, not hand-written and not tested by its author. Any lab result is on this rule's own page.Full description

The detection

The 3 SIEM queries below are previews produced by Siemphony’s own translator, not pySigma, and none has been executed against a real backend — review before you deploy.

detection.yml

Splunk · SPL

Run this as a search.

index=* ((type="SYSCALL" AND (exe="*/insmod" OR exe="*/rmmod" OR exe="*/modprobe" OR exe="*/depmod" OR exe="*/kmod")) OR (type="PATH" AND (name="*.ko" OR name="*.ko.xz" OR name="*.ko.zst" OR name="*.ko.gz")) OR (type="PATH" AND name="*/lib/modules/*"))

Elastic · ES|QL

Run this as a search.

FROM logs-*| WHERE ((TO_LOWER(type) == "syscall" AND (TO_LOWER(exe) LIKE "*/insmod" OR TO_LOWER(exe) LIKE "*/rmmod" OR TO_LOWER(exe) LIKE "*/modprobe" OR TO_LOWER(exe) LIKE "*/depmod" OR TO_LOWER(exe) LIKE "*/kmod")) OR (TO_LOWER(type) == "path" AND (TO_LOWER(name) LIKE "*.ko" OR TO_LOWER(name) LIKE "*.ko.xz" OR TO_LOWER(name) LIKE "*.ko.zst" OR TO_LOWER(name) LIKE "*.ko.gz")) OR (TO_LOWER(type) == "path" AND TO_LOWER(name) LIKE "*/lib/modules/*"))

Wazuh · XML rule

Deploy to your manager — this is a rule, not a search.

<group name="sigma,linux,">  <!-- Rule ids must be unique on your manager; 100000+ is the user range. -->  <!-- 3 rules: the Sigma condition ORs across different fields,       which one rule cannot express. Any one matching is a hit. -->  <rule id="100000" level="5">    <!-- Set <if_sid> to the decoder/base rule for linux so this only evaluates relevant events. -->    <field name="type" type="pcre2">(?i)^SYSCALL$</field>    <field name="exe" type="pcre2">(?i)(/insmod$|/rmmod$|/modprobe$|/depmod$|/kmod$)</field>    <description>Kernel module loaded or the module tree modified on Linux (1/3)</description>    <mitre>      <id>T1547.006</id>    </mitre>  </rule>   <rule id="100001" level="5">    <!-- Set <if_sid> to the decoder/base rule for linux so this only evaluates relevant events. -->    <field name="type" type="pcre2">(?i)^PATH$</field>    <field name="name" type="pcre2">(?i)(\.ko$|\.ko\.xz$|\.ko\.zst$|\.ko\.gz$)</field>    <description>Kernel module loaded or the module tree modified on Linux (2/3)</description>    <mitre>      <id>T1547.006</id>    </mitre>  </rule>   <rule id="100002" level="5">    <!-- Set <if_sid> to the decoder/base rule for linux so this only evaluates relevant events. -->    <field name="type" type="pcre2">(?i)^PATH$</field>    <field name="name" type="pcre2">(?i)/lib/modules/</field>    <description>Kernel module loaded or the module tree modified on Linux (3/3)</description>    <mitre>      <id>T1547.006</id>    </mitre>  </rule></group>

Sentinel · KQL

Run this as a search.

Sentinel cannot express this construct. No Sentinel table is modelled for this logsource ({"product":"linux","service":"auditd"}), so there is nothing honest to query. Pick a logsource this translator maps, or write the KQL by hand. The Sigma source is on the first tab, unchanged.

Verdicts · reactions · comments

Community

Verdicts from engineers who actually deployed it, and the conversation around it.

Log in to react
Not yet reported on

Nobody has run this in a real environment and said what happened.

Verdicts from engineers who deployed it

0 cast

No verdicts reported yet. The first one is worth more than the tenth — say what you ran it against.

Log in to report a verdict.

Log in to join the discussion.

No comments yet. Someone who deploys this will have something to say about it.