⚠️ Safety & Ethics
These scripts are designed for lab use only (your VMs, CTF boxes, or explicitly authorized targets). They automate enumeration and provide defensive suggestions — they are not exploit payloads for attacking real systems. Running these against networks or hosts you do not own or have permission to test is illegal.
🧠 What this post covers
How to design modular recon/exploit-helper scripts
Best practices for argument parsing, logging, and safety
A reusable recon driver script (lab-only)
A “suggestions” engine that maps findings to safe next steps
Lab exercises to extend and harden the tools
⚙️ Design Principles (How pros structure recon scripts)
Modularity: Break tasks into functions (gather_info, port_scan, banner_grab). Easier to test and reuse.
Safety-first defaults: Default target =
127.0.0.1orlocalhost.--targetmust be explicit.Idempotence: Running script twice should not corrupt data or flood the network.
Logging & output: Save structured outputs (text files, optionally JSON) for later analysis.
Limited aggression: Use light nmap flags by default; require
--aggressiveor--fullto escalate scans (and still lab-only).Advisory suggestions: Provide defensive next steps (fix file perms, tighten sudo) — not exploit commands.
Argument validation: Don’t accept arbitrary privileged targets unless running as a non-root user in a controlled lab.
🧩 Script Blueprint — lab_recon.sh (modular, safe)
Save as lab_recon.sh, chmod +x lab_recon.sh. Defaults to localhost. This script:
collects basic host info
runs a light nmap scan
grabs open banner info (ss + netcat banner grab with timeout)
produces a plain-text report and a short CSV summary
prints safe suggestions based on findings
#!/usr/bin/env bash
set -euo pipefail
trap 'echo "Script failed at line $LINENO"; exit 1' ERR
USAGE() {
cat < [--outdir DIR] [--full]
Defaults: target=127.0.0.1, outdir=./lab_recon_YYYYMMDD_HHMMSS
Options:
--target Target host (default: 127.0.0.1)
--outdir Output directory
--full Run additional checks (use in lab only)
-h|--help Show this help
EOF
}
# Defaults
TARGET="127.0.0.1"
OUTDIR=""
FULL=false
# Parse args (simple)
while [[ $# -gt 0 ]]; do
case "$1" in
--target) TARGET="$2"; shift 2;;
--outdir) OUTDIR="$2"; shift 2;;
--full) FULL=true; shift;;
-h|--help) USAGE; exit 0;;
*) echo "Unknown arg: $1"; USAGE; exit 2;;
esac
done
if [[ -z "$OUTDIR" ]]; then
OUTDIR="./lab_recon_$(date +%F_%H%M%S)_${TARGET//[:\/]/_}"
fi
mkdir -p "$OUTDIR"
log() { echo "[$(date +%T)] $*"; }
# Function: gather system/banner info
gather_basic() {
log "Gathering basic system info for $TARGET"
echo "Target: $TARGET" > "$OUTDIR/report.txt"
echo "Scan time: $(date +%F_%T)" >> "$OUTDIR/report.txt"
uname -a >> "$OUTDIR/report.txt" 2>/dev/null || true
echo -e "\n-- Listening sockets (local view) --" >> "$OUTDIR/report.txt"
ss -tulwn >> "$OUTDIR/report.txt" || true
}
# Function: nmap quick scan (non-aggressive)
port_scan() {
if command -v nmap >/dev/null 2>&1; then
log "Running light nmap scan (safe defaults)"
nmap -sC -sV -oN "$OUTDIR/nmap_quick.txt" "$TARGET" || echo "nmap failure (nonfatal)" >> "$OUTDIR/report.txt"
else
echo "nmap not found; skipping nmap" >> "$OUTDIR/report.txt"
fi
}
# Function: banner grab simple (non-blocking)
banner_grab() {
log "Grabbing simple banners from open ports (lab-only)"
# create a short CSV of host,port,banner
echo "host,port,banner" > "$OUTDIR/banners.csv"
if [[ -f "$OUTDIR/nmap_quick.txt" ]]; then
# parse open ports (simple heuristic)
grep -E "^[0-9]+/tcp" "$OUTDIR/nmap_quick.txt" | awk '{print $1,$3}' | while read -r port state; do
pnum=$(echo "$port" | cut -d/ -f1)
# attempt a quick banner with timeout using bash + /dev/tcp
banner=$(timeout 2 bash -c "echo | nc -w 2 $TARGET $pnum" 2>/dev/null || true)
banner_clean=$(echo "$banner" | tr '\n' ' ' | tr -d '\r' | sed 's/,/ /g')
echo "${TARGET},${pnum},\"${banner_clean}\"" >> "$OUTDIR/banners.csv"
done
fi
}
# Function: basic suggestions engine (non-exploit)
suggestions() {
log "Generating safe suggestions based on findings"
echo -e "\n-- Suggestions (lab-only) --" >> "$OUTDIR/report.txt"
# Suggest if world-writable dirs found (based on permission audit artifacts if present)
if [[ -f "$OUTDIR/perm_audit.txt" ]]; then
if grep -q "No such file" "$OUTDIR/perm_audit.txt" 2>/dev/null; then
:
fi
fi
# Nmap-based hints (very high-level)
if [[ -f "$OUTDIR/nmap_quick.txt" ]]; then
if grep -q "22/tcp" "$OUTDIR/nmap_quick.txt"; then
echo "SSH (22) found: ensure key-based auth and disable password auth where possible." >> "$OUTDIR/report.txt"
fi
if grep -q "80/tcp" "$OUTDIR/nmap_quick.txt" || grep -q "443/tcp" "$OUTDIR/nmap_quick.txt"; then
echo "Web service detected: review webserver permissions and config files; avoid world-readable secrets." >> "$OUTDIR/report.txt"
fi
fi
echo "Review the report and cross-check file permissions and sudo rules in your lab VM." >> "$OUTDIR/report.txt"
}
# Run steps
gather_basic
port_scan
banner_grab
suggestions
log "Recon complete. Results in $OUTDIR"
echo "Report saved: $OUTDIR/report.txt"
🔍 How the script is safe / limited
Defaults to
127.0.0.1if you forget--target.Uses a lightweight nmap profile (
-sC -sV) by default — not aggressive.Banner grabbing uses short timeouts and
ncwith a limit; still requires lab discipline.Suggestions are high-level defensive hints (no exploit payloads or commands).
🛠️ Extending the Script (Ideas for practice)
Add
--fullto enable deeper scans (only lab):nmap -p- --script vuln— gated behind an explicit flag and an extra confirmation prompt.JSON output support — parse nmap XML to JSON for programmatic pipelines.
Integrate permission audit — run the permission script from Part 7 and include
perm_audit.txtso suggestions can include permission hardening.Add a results dashboard — simple static HTML output summarizing findings (useful for reporting during CTF writeups).
Add rate-limiting or delays to avoid accidental DoS in poorly provisioned lab VMs.
🧪 Lab Exercises
Run the driver on localhost
./lab_recon.sh --target 127.0.0.1Inspect
report.txt,nmap_quick.txt, andbanners.csv.
Connect the permission audit
Run the permission audit from Part 7, save as
perm_audit.txtinto the same OUTDIR, and updatelab_recon.shto include findings insuggestions().
Add argument parsing with
getoptsReplace the simple parser with
getoptsand add--skip-nmap,--json, and--confirm-fullflags.
Create a non-root check
Add a runtime check that refuses to run if the script is launched as root unless
--allow-rootis explicitly provided. This prevents accidental damage.
Build a modular library
Extract common functions (banner_grab, port_scan) into
lib_recon.shandsourceit fromlab_recon.shfor reuse across tools.
✅ Best Practices Recap
Default to safe targets (localhost) and gentle scan settings.
Ask for explicit confirmation before running aggressive scans.
Always snapshot VMs before experiments and keep backups.
Log everything with timestamps and rotate logs.
Convert findings into defensive actions, not exploit commands.
Use version control and code reviews — treat automation like production code.
🎯 Coming Up Next
Part 9: Networking Basics Every Hacker Should Know — we’ll map the networking concepts that make recon meaningful: routes, interfaces, DNS, ARP, routing tables, and how to interpret them in the field (lab-first).
💬 Got Questions?
Drop them in the comments or join our community on Discord for exclusive hacking tips and resources.
Don’t worry — mastery comes with practice.
Just open your terminal and hack your brain into CLI mode daily.
Let’s keep building. 💻⚔️
