Built a Linux persistence hunting & artifact collection tool in Bash - persisthunt
Posted by Longjumping_Year6448@reddit | linuxadmin | View on Reddit | 2 comments
I’ve been working on a Bash-based Linux persistence detection and artifact collection script called persisthunt.
The goal is to help defenders and incident responders quickly identify suspicious persistence mechanisms and collect relevant artifacts during investigations without immediately jumping into full disk forensics.
The script currently hunts for a variety of Linux persistence techniques including:
- suspicious network listeners/reverse shells
- eBPF based raw network socket persistence (bpfdoor)
- hidden processes
- systemd services/timers/generators
- cron jobs
- shell profile persistence
- ld.so.preload
- SSH authorized_keys abuse
- world-writable SUID/SGID files
- references to
/tmp,/dev/shm,/dev/tcp,curl,wget,nc, etc. in autorun locations - more...
Findings are categorized as:
- High
- Low
- Informational
based on confidence and severity.
The project is designed to be lightweight and easily customizable depending on the environment and threat model.
Would appreciate feedback, ideas for additional persistence mechanisms to cover, and suggestions.
m15f1t@reddit
I'll follow this. But output currently is perhaps a bit noisy. Some findings (user & external IP obfuscated by me):
=== [HIGH] Running processes referencing a suspicious keyword ===
root 1506971 0.7 1.1 17364 10856 ? Ss May22 4:11 /usr/bin/ssh -D 192.168.1.8:1337 -q -C -N -i /root/.ssh/id_rsa_pi-user -p 20022 user@123.123.123.123
.. here highlighting the suspicious keyword might help (i guess it's the 1337-part)
Some false positives perhaps (rasperry pi running pi-hole):
=== [HIGH] Systemd service/timer referencing a suspicious keyword ===
/usr/lib/systemd/system/apparmor.service:AssertPathIsReadWrite=/sys/kernel/security/apparmor/.load
/usr/lib/systemd/system/apparmor.service:Documentation=https://gitlab.com/apparmor/apparmor/wikis/home/
/usr/lib/systemd/system/rsync.service:ExecStart=/usr/bin/rsync --daemon --no-detach
=== [HIGH] Init/rc.local/profile script referencing a suspicious keyword ===
/etc/init.d/x11-common: DIR="/tmp/$1"
/etc/init.d/x11-common: fn="$(mktemp /tmp/testwriteable.XXXXXXXXXX)" || return 1
/etc/init.d/x11-common: if [ -d "/tmp/$ICE_DIR" ] && [ -d "/tmp/$SOCKET_DIR" ]; then
/etc/init.d/inetutils-syslogd:if [ ! -c /dev/.devfsd ]; then
/etc/init.d/alsa-utils: # /usr is mounted on a system that has which in /usr/bin/.
/etc/init.d/udev: if mountpoint -q /dev/shm/; then
/etc/init.d/udev: umount -n -l /dev/shm/
=== [HIGH] Shell profile referencing a suspicious keyword ===
/etc/profile.d/bash_completion.sh: [ -r "${XDG_CONFIG_HOME:-$HOME/.config}/bash_completion" ] &&
/etc/profile.d/bash_completion.sh: . "${XDG_CONFIG_HOME:-$HOME/.config}/bash_completion"
/root/.profile: if [ -f \~/.bashrc ]; then
/root/.profile: . \~/.bashrc
/home/frederique/.bashrc: test -r \~/.dircolors && eval "$(dircolors -b \~/.dircolors)" || eval "$(dircolors -b)"
/home/frederique/.bashrc: if [ -f \~/.bash_aliases ]; then
/home/frederique/.bashrc: . \~/.bash_aliases
/home/frederique/.profile: if [ -f "$HOME/.bashrc" ]; then
/home/frederique/.profile: . "$HOME/.bashrc"
/home/frederique/.profile: if [ -d "$HOME/.local/bin" ] ; then
/home/frederique/.profile: PATH="$HOME/.local/bin:$PATH"
And this one was interesting:
Probably the grip running on line 209.
Longjumping_Year6448@reddit (OP)
Thanks for your feedback. Really appriciate it. The first hit is because of the hidden directory (
.ssh) as theSUS_KEYWORDS_REGEXhas the last regex.*/\..* . I will consider highlighting the keyword that matched.The false positives are because of similar regex matches. I recommend updating the regex to suit your enviornment.
The goal of this script is to be a flexible foundation that defenders can customize for their environments by adding or removing detection logic and keywords. The output can be large and may require environment-specific analysis, but it is also suitable for review and summarization using LLMs or AI agents.