- Go 74.6%
- HTML 21.8%
- Makefile 2.5%
- Dockerfile 1.1%
| .forgejo/workflows | ||
| cmd | ||
| internal | ||
| .dockerignore | ||
| .gitignore | ||
| AGENTS.md | ||
| Design.md | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| Makefile | ||
| PLAN.md | ||
| README.md | ||
| server.example.toml | ||
mockvirus
WARNING: This is very much an LLM-Hallucinated proof-of-concept
Penetration-testing tool that simulates malware behavior to test anti-malware defenses. No actual malicious behavior — designed not to harm systems; has built-in expiration.
Features
- C2 server — Go-based command & control with TLS, SQLite persistence, task queue
- Dual clients — Go clients for Linux and Windows (build-tag separated)
- Persistence simulation — copies binary to
~/.local/share/mockvirus/%APPDATA%\mockvirus, creates cron / Run key with full connection flags - DLL hijacking demo — writes
%TEMP%\win32.dll.txt//tmp/libhijack.so.txt(path configurable from dashboard) - System info collection — OS, hostname, users, uptime, network info
- Kerberos proxy auth — authenticate to HTTPS proxies using Negotiate/SPNEGO (SSPI on Windows, gokrb5 on Linux). Auto-detects system proxy (WinINet on Windows, env vars on Linux).
- ClickFix simulation — fake CAPTCHA page that copies a payload download command to clipboard
- Base64 payload delivery — HTML page at
/with JS-decoded payload; falls back to/payload/<os>download. OS auto-detected from User-Agent. - Operator dashboard — Vue.js SPA bundled in binary (no CDN), session persists in localStorage, auto-refreshes every 10s
- Safe mode — dry-run flag that logs actions without executing anything
- String obfuscation — XOR obfuscation on registry-related strings
- Auth — separate
client_auth_tokenandoperator_auth_tokenin server config - Expiration — hardcoded to 2027-01-01; server rejects registration after expiry
Build
Requires Go 1.22+.
make all # server + linux client
make server # build/mockvirus-server
make client-linux # build/mockvirus-client-linux
make client-windows # cross-compile for Windows (no CGO)
make release # stripped binaries (-ldflags="-s -w")
make run # build & run server (uses server.toml)
make lint # go vet ./...
make tidy # go mod tidy
Quickstart
# Build all targets
make all
# Copy and edit the example config
cp server.example.toml server.toml
# (edit server.toml: set tokens, binary paths)
# Start the server
make run
Usage
Server
./mockvirus-server -config server.toml
addr = ":8443"
cert_file = "/path/to/cert.pem"
key_file = "/path/to/key.pem"
client_auth_token = "secret-for-clients"
operator_auth_token = "secret-for-operator"
clickfix_cmd = "powershell -e <base64>"
windows_binary_path = "build/mockvirus-client-windows.exe"
linux_binary_path = "build/mockvirus-client-linux"
download_name = "update.bin"
redirect_url = "https://example.com/thanks"
db_path = "mockvirus.db"
Set cert_file + key_file for HTTPS. Without them, the server runs plain HTTP.
SSL_ERROR_RX_RECORD_TOO_LONGmeans you're usinghttps://against a plain HTTP server.
Linux client
./mockvirus-client-linux \
-server https://c2.example.com:8443 \
-secret client-secret \
-proxy https://proxy.corp:3128 \
-safe \
-audit /var/log/mockvirus.log
No --proxy needed for system proxy — auto-detected from HTTPS_PROXY/HTTP_PROXY env vars.
Windows client
mockvirus-client-windows.exe \
-server https://c2.example.com:8443 \
-secret client-secret \
-proxy https://proxy.corp:3128 \
-safe \
-audit C:\ProgramData\mockvirus.log
No --proxy needed for system proxy — auto-detected from WinINet/IE proxy settings.
Operator dashboard
Open https://c2.example.com:8443/dashboard in a browser,
enter the operator_auth_token, and click Connect.
Session persists in localStorage across page reloads.
ClickFix payload delivery
Serve the ClickFix page at https://c2.example.com:8443/clickfix.
Set clickfix_cmd in server.toml to define the PowerShell command copied to clipboard.
Payload delivery
/payload/windows— Windows client binary (base64-encoded)/payload/linux— Linux client binary (base64-encoded)/payload— auto-detects OS from User-Agent header (base64-encoded)/— HTML page that detects OS client-side, fetches the base64 payload from/payload/<os>, and decodes it into a binary download
All payload endpoints return base64 text; decoding happens in client-side JS so no
executable crosses web gateways. When fetching directly (e.g. curl), decode with
base64 -d.
Project structure
cmd/
server/main.go — C2 server entrypoint
client/linux/main.go — Linux client entrypoint
client/windows/main.go — Windows client entrypoint
internal/
protocol/types.go — shared types, task definitions, expiry
server/
config.go — TOML config loading
server.go — Server struct, New(), Handler(), auth, payload binary endpoints
handlers_client.go — handleRegister, handleTask, handleResult
handlers_operator.go — handleResults, handleExpiry, handleClients, handleEnqueue
handlers_pages.go — handleRoot, handleDashboard, handleClickFix, handleVue, embed directives
registry.go — in-memory client registry with expiry check
taskqueue.go — per-client FIFO task queue
results.go — task result storage
store.go — SQLite persistence
static/ — embedded HTML pages + Vue.js bundle
client/
client.go — shared client logic (register, http, config)
poll.go — Poll loop, jitter, task dispatch
persist.go — binary copy, persistent path, command reconstruction
proxy.go — Kerberos Negotiate proxy dialer & round tripper
proxy_detect_default.go — Linux env-var proxy detection
proxy_detect_windows.go — Windows WinINet API proxy detection
token_linux.go — Linux gokrb5 token acquisition
token_windows.go — Windows SSPI token acquisition
obfuscate.go — XOR string obfuscation
audit.go — audit log to file
taskresult.go — shared result() helper
tasks_linux.go — Linux persistence (cron), system info, uninstall
tasks_windows.go — Windows persistence (registry Run key), system info, uninstall
Dependencies
github.com/BurntSushi/toml— config file parsinggithub.com/jcmturner/gokrb5/v8— Kerberos client (Linux)golang.org/x/sys/windows— Windows SSPI bindingsmodernc.org/sqlite— SQLite storage (no CGO)
License
GPLv3