Processes

Overview

A process is a running instance of a program. Every command you execute, every service running on a target, and every exploit you deploy is a process. Understanding process management matters for penetration testers — you need to identify what is running on a compromised system, find processes running as root that you might hijack, manage long-running tools during engagements, and clean up after yourself.

Key Concepts

Viewing Processes

ps — Process Snapshot

ps shows a snapshot of current processes. Two common syntax styles exist: BSD style (no dashes) and UNIX style (with dashes). Both work.

# BSD style — most common in pentest contexts
ps aux
Column Meaning
USER Process owner
PID Process ID
%CPU CPU usage percentage
%MEM Memory usage percentage
VSZ Virtual memory size (KB)
RSS Resident set size — physical memory (KB)
TTY Terminal associated with the process (? = no terminal, daemon)
STAT Process state
START Start time
TIME Cumulative CPU time
COMMAND Command that started the process

Process states (STAT column):

State Meaning
R Running or runnable
S Interruptible sleep (waiting for event)
D Uninterruptible sleep (usually I/O)
T Stopped (by signal or job control)
Z Zombie (terminated but not reaped by parent)
I Idle kernel thread (Linux 4.14+, common in ps output)

Additional STAT modifiers: s = session leader, l = multi-threaded, + = foreground process group, < = high priority, N = low priority.

# UNIX style — full format
ps -ef

# Filter for specific user
ps -u root

# Filter by process name
ps aux | grep apache2
ps aux | grep -v grep | grep apache2   # Exclude grep itself

# Show process tree (parent-child relationships)
ps auxf
ps -ejH

ps auxf shows the process tree with indentation — useful for understanding which process spawned which. Web shells, reverse shells, and injected processes become visible in the tree structure.

top / htop — Real-Time Monitoring

# top — built-in process monitor
top

Inside top: P sorts by CPU, M sorts by memory, k kills a process (prompts for PID), q quits. top updates every 5 seconds by default.

# Single snapshot (non-interactive)
top -bn1 | head -20

The -b flag enables batch mode (non-interactive), -n1 limits to one iteration. Useful in scripts and when piping output.

Process Information from /proc

Every running process has a directory under /proc/[PID]/ containing detailed information.

# Command that started the process
cat /proc/[PID]/cmdline | tr '\0' ' '

# Environment variables (may contain secrets)
cat /proc/[PID]/environ | tr '\0' '\n'

# Current working directory
ls -la /proc/[PID]/cwd

# Executable path
ls -la /proc/[PID]/exe

# Open file descriptors
ls -la /proc/[PID]/fd/

# Process status (UID, GID, memory, state)
cat /proc/[PID]/status

/proc/[PID]/environ is a high-value target during post-exploitation. Applications frequently pass database passwords, API keys, and tokens through environment variables. These are readable by the process owner or root.

/proc/[PID]/cmdline often reveals command-line arguments including credentials passed as flags (e.g., mysql -u admin -pSecretPass).

Signals

Signals are software interrupts sent to processes. The kill command sends signals despite its name — not all signals terminate the process.

# Send SIGTERM (15) — polite termination request
kill [PID]
kill -15 [PID]

# Send SIGKILL (9) — force kill (cannot be caught or ignored)
kill -9 [PID]

# Send SIGHUP (1) — hangup (often causes config reload)
kill -1 [PID]

# Send SIGSTOP (19) — pause process
kill -STOP [PID]

# Send SIGCONT (18) — resume paused process
kill -CONT [PID]

# Kill by name
killall apache2             # All processes named apache2
pkill -f "python3 server"   # Match against full command line

Key signals:

Signal Number Default Action Notes
SIGHUP 1 Terminate Many daemons reload config instead
SIGINT 2 Terminate Ctrl+C sends this
SIGQUIT 3 Terminate + core dump Ctrl+\ sends this
SIGKILL 9 Terminate (forced) Cannot be caught, blocked, or ignored
SIGTERM 15 Terminate (graceful) Default signal sent by kill
SIGSTOP 19 Stop (pause) Cannot be caught or ignored (unlike SIGTSTP)
SIGTSTP 20 Stop (pause) Ctrl+Z sends this; can be caught by programs
SIGCONT 18 Continue Resumes a stopped process
# List all available signals
kill -l

Job Control

Job control lets you manage multiple processes from a single terminal — essential during engagements when running listeners, scans, and exploits simultaneously.

# Nmap
# https://nmap.org/
# Run command in background
nmap -sV 192.168.1.0/24 &

# Ctrl+Z — suspend current foreground process
# (sends SIGTSTP)

# List background jobs
jobs

# Resume job in background
bg %1               # Resume job 1 in background

# Bring job to foreground
fg %1               # Bring job 1 to foreground

# Disown — detach job from terminal (survives terminal close)
disown %1

Job numbers are shown in jobs output as [1], [2], etc. The % prefix references job numbers (not PIDs).

Persistent Processes

Processes started in a terminal die when the terminal closes (SIGHUP). Several methods keep processes running after disconnection:

# nohup — immune to hangup signal, output goes to nohup.out
nohup ./long_scan.sh &

# screen — terminal multiplexer
screen -S scan              # Create named session
# (run commands inside screen)
# Ctrl+A then D — detach
screen -ls                  # List sessions
screen -r scan              # Reattach to session

# tmux — modern terminal multiplexer
tmux new -s scan            # Create named session
# (run commands inside tmux)
# Ctrl+B then D — detach
tmux ls                     # List sessions
tmux attach -t scan         # Reattach to session

screen and tmux are essential for engagements — run Metasploit in one pane, a listener in another, and enumeration in a third. If your SSH connection drops, everything keeps running.

Service Management (systemd)

Most modern Linux distributions use systemd to manage services.

# Check service status
systemctl status ssh
systemctl status apache2

# Start, stop, restart
systemctl start ssh
systemctl stop apache2
systemctl restart nginx

# Enable/disable at boot
systemctl enable ssh         # Start on boot
systemctl disable apache2    # Don't start on boot

# List all running services
systemctl list-units --type=service --state=running

# List all enabled services
systemctl list-unit-files --type=service --state=enabled

During post-exploitation, systemctl list-units --type=service --state=running shows every active service — databases, web servers, monitoring agents, and security tools that might detect your presence.

Practical Examples

Post-Exploitation Process Enumeration

# What's running?
ps aux

# What's running as root?
ps aux | awk '$1 == "root" {print}'

# What's listening on the network?
ss -tlnp

# Check for credentials in process arguments
ps aux | grep -iE "pass|pwd|key|token|secret" | grep -v grep

# Check for credentials in environment variables
for pid in $(ls /proc/ | grep -E "^[0-9]+$"); do
  cat /proc/$pid/environ 2>/dev/null | tr '\0' '\n' | \
    grep -iE "pass|pwd|key|token|secret" && echo "  ^ PID: $pid"
done

# Find processes running from unusual locations
ps aux | awk '{print $11}' | sort -u | grep -vE "^\[|^/usr|^/sbin|^/bin|^/lib"

References

Official Documentation