Symbol stripping run against a compiled binary on Linux
The observable this technique is named for is a property of a *file* — no symbol table, no readable strings — and no log source in this brief carries it. Sysmon EventID 1 emits Image, CommandLine and Hashes, EventID 11 emits TargetFilename and the writing process, and Zeek http.log and files.log emit MIME type and size; none of them records whether a binary has a .symtab section, and MITRE's `EntropyThreshold` knob is not a field on any of them. So this rule takes the Linux leg of AN0056 and matches the stripping *act* instead of the stripped artefact: an execution of the binutils strip tool, an objcopy invocation carrying one of the flags that removes symbols, or a Go build whose linker flags discard the symbol table and DWARF data. That is MITRE's `StripFlags` knob — flag combinations indicating symbol table removal — populated here with those specific tools and switches rather than taken from MITRE. Because `endswith` anchors on the tail of the path, the tool list carries both `/strip` and `-strip`, so the prefixed builds of the same binary that are what is actually installed on many hosts — `llvm-strip`, `eu-strip`, `x86_64-linux-gnu-strip`, `aarch64-linux-gnu-strip` — are covered as well as a bare `strip`. Three limits are structural and none of them is fixable from this source. Stripping is overwhelmingly done on the adversary's build host before delivery, or inside a compiler the victim never runs, so the common case produces no event on the victim at all — this rule sees only the unusual case where the payload is built or post-processed in place. `gcc -s` and `ld -s` are deliberately absent: compiler binaries are version-suffixed and target-prefixed (`gcc-12`, `x86_64-linux-gnu-gcc-12`), which defeats an `endswith` on `/gcc`, and a bare ` -s ` on a compiler command line is not specific enough to carry the rule on its own. Packers are also out of scope by design — a UPX-compressed payload is T1027.002, not this. The other three analytics under DET0019 are not attempted: AN0055 (Windows) and AN0058 (network) have no field for symbols or strings as described above, and AN0057 (macOS), whose real observable is a run-only AppleScript produced by `osacompile -x`, offers only unifiedlog, EndpointSecurity and osquery, none of which has a standardised Sigma field vocabulary — inventing one would produce a rule that parses, renders in four backends and matches nothing. Vocabulary and prerequisite: this rule is written in the Sysmon-for-Linux shaped `process_creation` vocabulary (Image, CommandLine) that the brief maps `auditd:EXECVE::EXECVE` onto. Raw auditd carries the same values as `exe=` on the SYSCALL record and `a0`..`aN` on a separate EXECVE record, so that feed needs a field mapping before this rule applies to it, and auditd records no execve at all until a rule such as `-a always,exit -F arch=b64 -S execve -k exec` is loaded. Until one is, this rule returns zero rows, and zero rows here means blind rather than quiet. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0019, not hand-written and not tested by its author. Any lab result is on this rule's own page.Full descriptionShow less
The detection
The 4 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
title: Symbol stripping run against a compiled binary on Linuxid: cc4c67e1-fdc9-4074-9cdc-950b0ac78ad0status: experimentaldescription: | The observable this technique is named for is a property of a *file* — no symbol table, no readable strings — and no log source in this brief carries it. Sysmon EventID 1 emits Image, CommandLine and Hashes, EventID 11 emits TargetFilename and the writing process, and Zeek http.log and files.log emit MIME type and size; none of them records whether a binary has a .symtab section, and MITRE's `EntropyThreshold` knob is not a field on any of them. So this rule takes the Linux leg of AN0056 and matches the stripping *act* instead of the stripped artefact: an execution of the binutils strip tool, an objcopy invocation carrying one of the flags that removes symbols, or a Go build whose linker flags discard the symbol table and DWARF data. That is MITRE's `StripFlags` knob — flag combinations indicating symbol table removal — populated here with those specific tools and switches rather than taken from MITRE. Because `endswith` anchors on the tail of the path, the tool list carries both `/strip` and `-strip`, so the prefixed builds of the same binary that are what is actually installed on many hosts — `llvm-strip`, `eu-strip`, `x86_64-linux-gnu-strip`, `aarch64-linux-gnu-strip` — are covered as well as a bare `strip`. Three limits are structural and none of them is fixable from this source. Stripping is overwhelmingly done on the adversary's build host before delivery, or inside a compiler the victim never runs, so the common case produces no event on the victim at all — this rule sees only the unusual case where the payload is built or post-processed in place. `gcc -s` and `ld -s` are deliberately absent: compiler binaries are version-suffixed and target-prefixed (`gcc-12`, `x86_64-linux-gnu-gcc-12`), which defeats an `endswith` on `/gcc`, and a bare ` -s ` on a compiler command line is not specific enough to carry the rule on its own. Packers are also out of scope by design — a UPX-compressed payload is T1027.002, not this. The other three analytics under DET0019 are not attempted: AN0055 (Windows) and AN0058 (network) have no field for symbols or strings as described above, and AN0057 (macOS), whose real observable is a run-only AppleScript produced by `osacompile -x`, offers only unifiedlog, EndpointSecurity and osquery, none of which has a standardised Sigma field vocabulary — inventing one would produce a rule that parses, renders in four backends and matches nothing. Vocabulary and prerequisite: this rule is written in the Sysmon-for-Linux shaped `process_creation` vocabulary (Image, CommandLine) that the brief maps `auditd:EXECVE::EXECVE` onto. Raw auditd carries the same values as `exe=` on the SYSCALL record and `a0`..`aN` on a separate EXECVE record, so that feed needs a field mapping before this rule applies to it, and auditd records no execve at all until a rule such as `-a always,exit -F arch=b64 -S execve -k exec` is loaded. Until one is, this rule returns zero rows, and zero rows here means blind rather than quiet. UNVERIFIED AS AUTHORED — derived from MITRE ATT&CK DET0019, not hand-written and not tested by its author. Any lab result is on this rule's own page.references: - https://attack.mitre.org/techniques/T1027/008 - https://attack.mitre.org/detectionstrategies/DET0019author: Siemphony pipeline (machine-derived from MITRE ATT&CK v19.2)date: 2026-08-17tags: - attack.defense-evasion - attack.t1027.008logsource: category: process_creation product: linuxdetection: selection_strip: Image|endswith: - '/strip' - '-strip' - '/sstrip' selection_objcopy: Image|endswith: - '/objcopy' - '-objcopy' CommandLine|contains: - '--strip-all' - '--strip-debug' - '--strip-unneeded' - '--strip-symbol' - '--discard-all' selection_go_build: Image|endswith: '/go' CommandLine|contains: '-ldflags' selection_go_stripflags: CommandLine|contains: - '-s -w' - '-w -s' condition: selection_strip or selection_objcopy or (selection_go_build and selection_go_stripflags)falsepositives: - "Ordinary software packaging. Debian helper dh_strip and the RPM find-debuginfo pass run strip or objcopy over every binary and shared object in a package, which is hundreds of executions per build, and make install-strip does the same for hand-built software. On any build server, CI runner or developer workstation this is the dominant match by a very wide margin, and it is why the level is low rather than medium." - "Separate-debuginfo workflows, where the standard recipe is objcopy --only-keep-debug, then objcopy --strip-debug, then objcopy --add-gnu-debuglink. Distribution build systems, Yocto and Buildroot images, and crash-reporting toolchains all run that sequence on every artefact they produce." - "Go release builds. Passing -ldflags with -s and -w is the documented way to shrink a Go binary, so it appears in the Makefile, goreleaser config or Dockerfile of a large share of Go projects and fires on every build and every container image rebuild." - "Kernel and out-of-tree module installation. make modules_install strips debug information from every .ko when INSTALL_MOD_STRIP is set, and DKMS repeats it for third-party drivers after each kernel upgrade." - "Embedded and appliance image builds that strip binaries purely to fit a size budget, including cross-compiled firmware trees where the tool that runs is a target-prefixed strip such as arm-linux-gnueabihf-strip."level: lowSentinel · KQL
Run this as a search.
DeviceProcessEvents| where (((FolderPath endswith "/strip" or FolderPath endswith "-strip" or FolderPath endswith "/sstrip") or ((FolderPath endswith "/objcopy" or FolderPath endswith "-objcopy") and (ProcessCommandLine contains "--strip-all" or ProcessCommandLine contains "--strip-debug" or ProcessCommandLine contains "--strip-unneeded" or ProcessCommandLine contains "--strip-symbol" or ProcessCommandLine contains "--discard-all"))) or ((FolderPath endswith "/go" and ProcessCommandLine contains "-ldflags") and (ProcessCommandLine contains "-s -w" or ProcessCommandLine contains "-w -s")))
Splunk · SPL
Run this as a search.
index=* (((Image="*/strip" OR Image="*-strip" OR Image="*/sstrip") OR ((Image="*/objcopy" OR Image="*-objcopy") AND (CommandLine="*--strip-all*" OR CommandLine="*--strip-debug*" OR CommandLine="*--strip-unneeded*" OR CommandLine="*--strip-symbol*" OR CommandLine="*--discard-all*"))) OR ((Image="*/go" AND CommandLine="*-ldflags*") AND (CommandLine="*-s -w*" OR CommandLine="*-w -s*")))Elastic · ES|QL
Run this as a search.
FROM logs-*| WHERE (((TO_LOWER(process.executable) LIKE "*/strip" OR TO_LOWER(process.executable) LIKE "*-strip" OR TO_LOWER(process.executable) LIKE "*/sstrip") OR ((TO_LOWER(process.executable) LIKE "*/objcopy" OR TO_LOWER(process.executable) LIKE "*-objcopy") AND (TO_LOWER(process.command_line) LIKE "*--strip-all*" OR TO_LOWER(process.command_line) LIKE "*--strip-debug*" OR TO_LOWER(process.command_line) LIKE "*--strip-unneeded*" OR TO_LOWER(process.command_line) LIKE "*--strip-symbol*" OR TO_LOWER(process.command_line) LIKE "*--discard-all*"))) OR ((TO_LOWER(process.executable) LIKE "*/go" AND TO_LOWER(process.command_line) LIKE "*-ldflags*") AND (TO_LOWER(process.command_line) LIKE "*-s -w*" OR TO_LOWER(process.command_line) LIKE "*-w -s*")))
Wazuh · XML rule
Deploy to your manager — this is a rule, not a search.
<group name="sigma,linux,process_creation,"> <!-- 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="Image" type="pcre2">(?i)(/strip$|-strip$|/sstrip$)</field> <description>Symbol stripping run against a compiled binary on Linux (1/3)</description> <mitre> <id>T1027.008</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="Image" type="pcre2">(?i)(/objcopy$|-objcopy$)</field> <field name="CommandLine" type="pcre2">(?i)(--strip-all|--strip-debug|--strip-unneeded|--strip-symbol|--discard-all)</field> <description>Symbol stripping run against a compiled binary on Linux (2/3)</description> <mitre> <id>T1027.008</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="Image" type="pcre2">(?i)/go$</field> <field name="CommandLine" type="pcre2">(?i)-ldflags</field> <field name="CommandLine" type="pcre2">(?i)(-s -w|-w -s)</field> <description>Symbol stripping run against a compiled binary on Linux (3/3)</description> <mitre> <id>T1027.008</id> </mitre> </rule></group>
Verdicts · reactions · comments
Community
Verdicts from engineers who actually deployed it, and the conversation around it.
Nobody has run this in a real environment and said what happened.
Verdicts from engineers who deployed it
0 castNo 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.