diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..c568984 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +TUNNEL_TOKEN= diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0c0fed7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,44 @@ +# ---- Phase 1: Compile ---- +FROM golang:1.23-bookworm AS builder + +RUN apt update && apt -y install \ + git \ + nasm \ + mingw-w64 \ + pkg-config \ + wget \ + && rm -rf /var/lib/apt/lists/* + +# Manually install upx +RUN wget https://github.com/upx/upx/releases/download/v4.2.4/upx-4.2.4-amd64_linux.tar.xz \ + && tar -xf upx-4.2.4-amd64_linux.tar.xz \ + && mv upx-4.2.4-amd64_linux/upx /usr/local/bin/ \ + && rm -rf upx-4.2.4-amd64_linux* + +WORKDIR /build +RUN git clone https://github.com/HavocFramework/Havoc.git . + +# Patch strict go.mod and compile standalone +RUN cd teamserver/ \ + && chmod +x ./Install.sh \ + && ./Install.sh \ + && sed -i 's/go 1.21.0/go 1.23/' go.mod \ + && go build -v -o /build/havoc-ts main.go + +# ---- Phase 2: Execute ---- +FROM debian:bookworm-slim + +RUN apt update && apt -y install \ + nasm \ + mingw-w64 \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +# Import only compiled binary and data folder +COPY --from=builder /build/havoc-ts /app/havoc-ts +COPY --from=builder /build/data /app/data + +EXPOSE 40056 + +ENTRYPOINT ["/app/havoc-ts"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2821166 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,33 @@ +services: + havoc-teamserver: + container_name: havoc-teamserver + build: + context: . + dockerfile: Dockerfile + volumes: + - ./profiles:/app/profiles + - havoc-data:/app/data + ports: + - "40056:40056" + networks: + - c2-network + restart: unless-stopped + command: ["server", "--profile", "/app/profiles/default.yaotl", "--debug"] + + cloudflare-tunnel: + container_name: havoc-cloudflare-tunnel + image: cloudflare/cloudflared:latest + restart: unless-stopped + command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} + depends_on: + - havoc-teamserver + networks: + - c2-network + +networks: + c2-network: + driver: bridge + +volumes: + havoc-data: + driver: local diff --git a/profile/default.yaotl b/profile/default.yaotl new file mode 100644 index 0000000..d2d0a08 --- /dev/null +++ b/profile/default.yaotl @@ -0,0 +1,63 @@ +Manifest = { + Type = "Valid" + Name = "Cloudflare Listener" +} + +Http = { + Host = "0.0.0.0" + PortBind = 80 + PortConn = 443 + + Hosts = [ + "c2.example.com" # replace with your actual host + ] +} + +Teamserver { + Host = "0.0.0.0" + Port = 40056 + + Build { + Compiler64 = "data/x86_64-w64-mingw32-cross/bin/x86_64-w64-mingw32-gcc" + Compiler86 = "data/i686-w64-mingw32-cross/bin/i686-w64-mingw32-gcc" + Nasm = "/usr/bin/nasm" + } +} + +WebHook { + Discord { + # required + Url = "https://discord.com/api/webhooks//" # replace this with your webhook + + # optional + AvatarUrl = "https://raw.githubusercontent.com/HavocFramework/Havoc/main/assets/Havoc.png" # url to an image to use as an avatar + + # optional + User = "Havoc" # User name of the webhook bot + } +} + +# For God's sake, change this... +Operators { + user "admin" { + Password = "admin" + } +} + +# this is optional. if you dont use it you can remove it. +Service { + Endpoint = "service-endpoint" + Password = "service-password" +} + +Demon { + Sleep = 2 + Jitter = 15 + + TrustXForwardedFor = true + + Injection { + Spawn64 = "C:\\Windows\\System32\\notepad.exe" + Spawn32 = "C:\\Windows\\SysWOW64\\notepad.exe" + } +}