APEX2: Reversing a Custom Golang Botnet with TLS-Spoofing and Cloudflare WAF Bypass
Quick Reference
| Category | Field | Value |
|---|---|---|
| REPORT | Title | APEX2: Reversing a Custom Golang Botnet with TLS-Spoofing and Cloudflare WAF Bypass |
| Date | 2026-03-09 | |
| Author | msdbg | |
| Org | Independent Research | |
| TLP | TLP:CLEAR (Public Release) | |
| SAMPLE | SHA-256 | 21b19d07a414ad1ff7443c21c6530d1164c6c1eae56d3619a422d3f311b580b7 |
| File Type | PE32 executable (Console) Intel 80386 | |
| Size | 10,378,240 bytes (9.90 MB) | |
| Compiler | Go (go1.24.0) - windows/386 | |
| Subsystem | Windows CUI (Console) | |
| Anti-Analysis | Aggressive process/window enumeration (x64dbg, Procmon), Syscall hook detection (NtQuerySystemInformation), Debugger check evasion, Time distortion checks | |
| THREAT CONTEXT | Actor GPS | Romania (Botmaster tracking as "Apex") |
| Type | L4/L7 DDoS Botnet (Discord/Game/TLS/PPS Floods) | |
| Platform | Cross-compiled (Windows analyzed, Linux/IoT suspected) | |
| Frameworks | github.com/refraction-networking/utls (TLS Spoofing) | |
| C2 Server | 45.128.118.140 (Hardcoded via Go -ldflags) | |
Table of Contents
-
Threat Landscape: The Shift to Golang Botnets
1.1 The Appeal of Go: Concurrency & Cross-Compilation
1.2 Defeating Cloudflare: The uTLS Spoofing Vector
-
2.1 Abstract
2.2 Sample Corpus (Target Identification)
-
Defeating Anti-Analysis (The "Evasion Module")
3.1 Tooling Enumeration (x64dbg, Procmon, Wireshark)
-
Core Functionality — Analyzing the Go Build Artifacts
4.1 Extracting the Build Configuration & C2 (LDFLAGS)
4.2 Reversing the Flood Methods
4.2.1 [DiscordFlood & GameFlood](#421-discordflood--gameflood) 4.2.2 [TLSFlood & TLSPlusBypassFlood](#422-tlsflood--tlsplusbypassflood) -
Network Protocol & Infrastructure
Section 1 — Threat Landscape: The Shift to Golang Botnets
1.1 The Appeal of Go: Concurrency & Cross-Compilation
Since 2019 we've seen wide adoption of Golang by Maldevs. Today I bring you a fresh Golang botnet with some interesting checks. In the end, you'll know why Golang is perfect for Botnet development.
- Goroutines: Go's lightweight concurrency model allows a single infected machine to spawn tens of thousands of simultaneous network threads (goroutines) with minimal CPU and memory overhead, maximizing the volume of a packet flood.
- Cross-Compilation: With a single codebase, the botmaster can execute
GOOS=windows GOARCH=386orGOOS=linux GOARCH=amd64to instantly generate payloads for Windows desktops, Linux servers, and IoT devices.
1.2 Defeating Cloudflare: The uTLS Spoofing Vector
Modern DDoS attacks at Layer 7 (Application Layer) struggle against WAFs like Cloudflare. Standard Golang HTTP clients have a highly recognizable TLS Client Hello fingerprint (JA3/JA4).
To bypass this, modern botnets statically compile the github.com/refraction-networking/utls library. This library allows the malware to spoof its cryptographic fingerprint, mimicking a legitimate Google Chrome, Firefox, or iOS Safari browser during the TLS handshake, effortlessly bypassing standard WAF DDoS protections.
1.3 The "Apex" Lineage: From P2P to Centralized Floods
The analysis of this sample (apex2/Bot) reveals a centralized C2, with a hardcoded IP (45.128.118.140) injected directly into the binary at compile time via Go's -ldflags. The presence of methods like DiscordFlood and GameFlood indicates the actor targets gaming infrastructure and VOIP communities alongside traditional enterprise web servers.

1.4 The Classification: Why Automated Sandboxes Failed
Because Go binaries are natively large (10MB+) and statically linked, they generate significant noise. Apex2 specifically includes an aggressive anti-analysis module. When detonated in commercial sandboxes (which use user-land hooking and hypervisors), Apex2 detects the hooks (HookedNtQuerySystemInformation), identifies the analysis tools (Procmon64.exe, x64dbg.exe), and intentionally stifles its core botnet threads, entering a benign loop. Sandboxes, lacking the capability to analyze the dormant Go functions, relied on incorrect crowd-sourced YARA tags.
Section 2 — Abstract & Initial Triage
2.1 Abstract
This report details the reverse engineering and deobfuscation of a massive, 9.90 MB Golang executable originally misclassified in public threat repositories (such as MalwareBazaar) as Lumma Stealer. Our analysis definitively reclassifies this payload as Apex2, a highly evasive Golang DDoS botnet that executes Layer 7 Application floods.
The Apex2 botnet leverages the github.com/refraction-networking/utls framework to actively spoof cryptographic TLS Client Hello fingerprints (mimicking Chrome, Firefox, and Safari) to bypass modern Web Application Firewalls (WAFs) like Cloudflare. This write-up documents the defeat of its aggressive anti-analysis module—which monitors for user-land API hooks (e.g., HookedNtQuerySystemInformation) and enumerates debugging tools (x64dbg, Procmon)—and details the extraction of its hardcoded Command and Control (C2) infrastructure (45.128.118.140). Furthermore, we reconstruct its complete JSON-based C2 tasking schema and document its array of specialized attack vectors, including DiscordFlood, GameFlood, and TLSPlusBypassFlood.
2.2 Sample Corpus (Target Identification)
Note: The primary sample analyzed in this report was initially tagged by crowd-sourced threat intelligence platforms as LummaStealer. Automated commercial sandboxes failed to properly classify the payload due to its aggressive debugger-evasion routines causing the malware to abort its primary execution threads.
Primary Sample (Apex2 Botnet Payload)
| Attribute | Value |
|---|---|
| File Name | 21b19d07a414ad1ff7443c21c6530d1164c6c1eae56d3619a422d3f311b580b7.exe |
| SHA-256 | 21B19D07A414AD1FF7443C21C6530D1164C6C1EAE56D3619A422D3F311B580B7 |
| SHA-1 | 2AA67CB6142373C7AEC4D7278051D27C6CF3005F |
| MD5 | CC4B92FAE19C44F7115E7C8BDA7CAC70 |
| File Size | 10,378,240 bytes (9.90 MB) |
| File Type | PE32 executable (Intel 80386) |
| Compiler/Linker | Go (go1.24.0) / Microsoft Linker 3.0 |
| Subsystem | Windows CUI (Console) |
| Internal Name | apex2/Bot (Recovered from Go build artifacts) |
| C2 Infrastructure | 45.128.118.140 (Compiled via -ldflags) |
2.3 Infection Chain / Kill Chain Overview
Unlike Information Stealers that prioritize immediate exfiltration and self-deletion, the Apex2 botnet is designed for high-availability persistence and sustained network attacks. Its operational life cycle can be broken down into four distinct phases:

-
Delivery & Execution Apex2 payloads are typically distributed as secondary payloads via opportunistic initial access campaigns (e.g., SSH/RDP brute forcing, malicious spam attachments, or dropped by Initial Access Brokers). Upon execution, the 10MB Go binary initializes a console host but hides the window from the user.
-
Anti-Analysis & Environment Verification Before establishing network communications, Apex2 sweeps the host environment. It enumerates running processes looking for a vast blacklist of reverse-engineering tools (e.g.,
x32dbg.exe,Procmon64.exe,Wireshark.exe). It also inspects loaded DLLs for injected user-land hooks indicative of sandbox monitoring (e.g.,HookedNtCreateThread). If detected, the botnet gracefully aborts its attack threads and enters a benign infinite loop, outputting a decoyConnecting to CNC...message.

-
C2 Registration & Heartbeat If the environment is deemed safe, the bot initiates a TCP connection to its hardcoded C2 server (
45.128.118.140). It transmits a hardware fingerprint and environment profile via theREGISTER windows 386protocol, signaling to the botmaster that a new node is available for tasking. The bot then maintains a persistent listening loop waiting for JSON-formatted operational directives. -
Flood Execution & WAF Evasion Upon receiving a valid JSON task (containing keys such as
"method","target", and"duration"), the bot parses the command and deploys hundreds of concurrent Goroutines. Depending on the method requested, it may:- Download a list of SOCKS4/5 or HTTP proxies.
- Initialize the
refraction-networking/utlslibrary to randomize its TLS Client Hello. - Append modern Chromium/Safari HTTP headers (
sec-ch-ua,sec-fetch-dest) and execute a volumetric Layer 7 flood against the target, successfully blending in with legitimate web traffic to bypass mitigation systems like Cloudflare.
Section 3 — Defeating Anti-Analysis (The "Evasion Module")
A defining characteristic of the Apex2 botnet is its aggressive, multi-layered evasion module. This module is directly responsible for the payload's high failure rate in automated commercial sandboxes, which ultimately led to its misclassification as a generic stealer variant. Apex2 executes these checks immediately after loading into memory, neutralizing its core network threads.
3.1 Tooling Enumeration (x64dbg, Procmon, Wireshark)
Before initiating its C2 heartbeat, the botnet constructs an extensive blacklist of executable names associated with reverse engineering and dynamic analysis.
Static analysis of the unpacked payload within IDA Pro reveals the initialization of this blacklist array. The malware loads string pointers for over two dozen analysis tools, explicitly targeting debuggers, network sniffers, and system monitors:
wireshark.exe,procmon64.exex32dbg.exe,x64dbg.exe,ollydbg.exeidaq64.exe

The malware then enumerates the host's running processes (likely utilizing standard API calls such as CreateToolhelp32Snapshot or EnumProcesses). If any process hash or name matches an entry in this array, Apex2 aborts the execution of its DDoS Goroutines.
3.2 Syscall Hook Detection (NtQueryInformationProcess)
Sandboxes and EDRs monitor malware behavior by injecting a monitoring DLL into the process and placing inline hooks (typically JMP 0xE9 instructions) at the prologue of critical Native APIs (Syscalls) inside ntdll.dll.
Apex2 detects these user-land hooks. Disassembly reveals explicit checks and logging strings tailored to identify tampering on highly specific APIs:
HookedNtQuerySystemInformationHookedNtSetInformationThreadHookedNtQueryObject

By inspecting the first few bytes of these loaded functions in memory, Apex2 determines if its execution is being monitored. The targeting of APIs like NtSetInformationThread (often used to hide threads from debuggers) and NtQuerySystemInformation indicates the malware gets context to act stealthy.
3.3 the Evasion Checks in Memory
During dynamic analysis, these checks required a multi-pronged approach:
Because the Go executable is heavily flattened and relies on complex state machines, manually patching every hook and process check via IDA Pro is inefficient. The optimal way is freezing the process via a hardware breakpoint on kernel32.ResumeThread during the RunPE injection phase, and extracting the raw, unpacked RW memory regions to disk. This allows for static analysis of the unencrypted strings and logic without triggering the runtime protections.
Section 4 — Core Functionality — Analyzing the Go Build Artifacts
Due to the nature of statically compiled Golang binaries, traditional reverse engineering is vastly accelerated by analyzing the leftover build metadata. Memory carving of the apex2/Bot module revealed a complete list of dependencies, compiler flags, and method structures that define the botnet's offensive capabilities.
4.1 Extracting the Build Configuration & C2 (LDFLAGS)
During compilation, Golang allows developers to pass linker flags (-ldflags) to inject variables directly into the binary at build time. Apex2 utilizes this feature to generate unique payloads for specific campaigns without altering the source code.
Extraction of the Go build info block from memory revealed the exact compile command used for this payload:
build -ldflags="-X main.ServerIP=45.128.118.140"

This confirms that the C2 infrastructure (45.128.118.140) is hardcoded into the main.ServerIP variable. Furthermore, the flags CGO_ENABLED=0, GOOS=windows, and GOARCH=386 indicate a deliberate cross-compilation strategy, ensuring the payload can run on legacy 32-bit Windows systems without requiring external C libraries.
4.2 Reversing the Flood Methods
The core objective of Apex2 is volumetric and application-layer Denial of Service. Analysis of the apex2/Methods namespace identified multiple distinct attack vectors, tailored for different target profiles.
4.2.1 DiscordFlood & GameFlood
Disassembly of apex2_Methods_DiscordFlood_func1 reveals a reliance on the net.DialTimeout API rather than standard HTTP clients. This indicates a Layer 4 (Transport Layer) attack methodology.
The bot rapidly opens raw TCP or UDP sockets to the target port, writing raw byte arrays (io.Writer.Write) and closing the connection or holding it open to exhaust the target's connection pool. This method is highly effective against gaming servers and VOIP infrastructure (like Discord voice nodes) that rely on persistent, low-latency socket connections.
4.2.2 TLSFlood & TLSPlusBypassFlood
To attack hardened web infrastructure, Apex2 deploys its Layer 7 HTTP/TLS floods. Static analysis of apex2_Methods_TLSPlusBypassFlood_func1 shows the bot actively bypassing Go's native TLS implementation, routing connections through apex2_Methods_dialUTLS.
This explicitly invokes the refraction-networking/utls library to spoof the JA3/JA4 cryptographic fingerprints of the TLS Client Hello packet. Furthermore, the inclusion of the andybalholm/brotli and klauspost/compress libraries ensures the bot can perfectly mimic a modern browser's Accept-Encoding: gzip, deflate, br headers. By presenting a valid TLS fingerprint and accepting modern compression algorithms, the bot's requests seamlessly bypass JavaScript challenges and rate-limits imposed by services like Cloudflare.
4.3 Concurrency Architecture (Goroutine Deployment)
To maximize attack volume, Apex2 heavily leverages Golang's concurrency model. The presence of functions appended with .func1 and .gowrap1 (e.g., apex2_Methods_GameFlood_func1_deferwrap1) indicates the widespread use of Goroutines.
When the C2 issues an attack command, the main thread parses the "threads" JSON value and dispatches thousands of lightweight Goroutines simultaneously. The extensive use of deferwrap functions ensures that if a single socket crashes or times out during the flood, the panic is caught and recovered without crashing the entire botnet payload.
Section 5 — Network Protocol & Infrastructure
Apex2 departs from traditional HTTP-polling botnets by utilizing a combination of raw TCP sockets for C2 registration and highly customized HTTP/TLS clients for its offensive operations. The botnet's infrastructure is specifically hardened to bypass geographic blocks, IP reputation filters, and Layer 7 caching mechanisms.
5.1 uTLS Client Hello Fingerprinting & Proxy Routing
To ensure its volumetric floods actually reach the target application layer, Apex2 must bypass intermediary Web Application Firewalls (WAFs).
Proxy Ingestion:
To circumvent IP-based rate limiting, the bot routes its malicious traffic through extensive proxy networks. Static analysis reveals the malware utilizes os.Open and bufio.NewScanner to parse proxy lists (e.g., proxy/tlsplusbypass.txt) line-by-line. This memory-efficient ingestion method allows the bot to cycle through thousands of SOCKS4/5 or HTTP proxies during a prolonged flood without crashing the host due to memory exhaustion.
TLS Forgery & Randomization:
When executing a Layer 7 attack (such as TLSPlusBypassFlood), the bot dynamically constructs a net/http.Transport and crypto/tls.Config object. Instead of relying on Go's default cryptographic footprint, it passes this custom transport through the refraction-networking/utls library.
To prevent WAFs from generating a signature based on static attack patterns, the bot implements a randomization engine. Disassembly shows the bot seeding math/rand with time.Now().UnixNano() and utilizing rand.Intn. This is used to dynamically rotate through its hardcoded array of modern browser User-Agents and append randomized query parameters to the target URI, ensuring every HTTP request appears unique and forcing the target server to process the load dynamically rather than serving a cached response.
5.2 C2 Communication Format
Apex2 relies on a centralized, hardcoded C2 server (45.128.118.140). Communication is initiated by the bot, which acts as a persistent listener for operational directives.
-
The Handshake: Upon successful execution and evasion of analysis environments, the bot opens a connection to the C2 and transmits a plaintext registration string:
REGISTER windows 386This informs the botmaster of the available architecture, allowing them to segment their swarm for specific attack types.
-
The JSON Tasking Schema: Commands are issued from the C2 to the infected swarm using a structured JSON payload. The bot receives the byte stream and utilizes
encoding/json.Unmarshalto deserialize the command into an internal Go struct. Memory carving exposed the exact schema expected by the bot:"method": (e.g.,"DiscordFlood","TLSFlood")"target": The victim IP or URL."port": The target port."threads": The number of concurrent Goroutines to spawn."duration": The attack length in seconds."ratelimit": Throttling parameters to avoid immediate upstream disconnection.
Upon completion of the "duration" window, the bot terminates the attack Goroutines and transmits a status message back to the C2 (e.g., [CF] Attack finished), before returning to a dormant listening state.
Section 6 — IoCs & Detection Engineering
The following Indicators of Compromise (IoCs) and YARA logic are provided to accurately detect and hunt for the Apex2 botnet family.
6.1 Network Indicators (C2 & Infrastructure)
| Type | Indicator | Description |
|---|---|---|
| IPv4 | 45.128.118.140 | Hardcoded Apex2 Command & Control Server. |
| Protocol | REGISTER windows 386 | Initial plaintext heartbeat / registration string. |
6.2 Host-Based Indicators (File Hashes)
| Type | Hash | Note |
|---|---|---|
| SHA-256 | 21b19d07a414ad1ff7443c21c6530d1164c6c1eae56d3619a422d3f311b580b7 | Apex2 Go Payload (Analyzed) |
| MD5 | CC4B92FAE19C44F7115E7C8BDA7CAC70 | Apex2 Go Payload (Analyzed) |
6.3 Memory & Artifact Indicators
- Internal Go Build Path:
path apex2/Bot - Internal Module Name:
apex2/Methods - File References:
proxy/tlsplusbypass.txt
6.4 YARA Detection Rule
This rule is designed to scan memory dumps or unpacked payloads, targeting the unique combination of the botnet's internal Go paths, its specific TLS spoofing dependencies, and its bespoke anti-analysis strings.
rule APT_Apex2_Golang_Botnet_Memory {
meta:
author = "Independent Research"
description = "Detects unpacked Apex2 Golang DDoS Botnet in memory, differentiating it from Lumma Stealer misclassifications."
date = "2026-03-09"
threat_type = "DDoS Botnet / WAF Bypass"
tlp = "CLEAR"
strings:
// Go Build Metadata & Packages
$go_build1 = "path\x09apex2/Bot" ascii
$go_build2 = "mod\x09apex2" ascii
$pkg_utls = "github.com/refraction-networking/utls" ascii
// C2 Handshake & Operations
$c2_register = "REGISTER windows 386" ascii
$c2_decoy = "Connecting to CNC..." ascii
$atk_cf = "[CF] Attack finished" ascii
// Bespoke Evasion Module
$evade_sys1 = "HookedNtQuerySystemInformation" ascii
$evade_sys2 = "HookedNtSetInformationThread" ascii
$evade_dbg = "Malware called ResumeThread" ascii
$evade_err = "Failed to find fixed version info signature in ntdll.dll" ascii
condition:
uint16(0) == 0x5A4D // PE Header (MZ)
and (
all of ($go_build*)
or 3 of ($c2_*)
or 3 of ($evade_*)
or ($pkg_utls and 1 of ($go_build*) and 1 of ($evade_*))
)
}
Section 7 — Why Golang is perfect for Botnets
The discovery of the Apex2 and other botnets underscores a definitive trend in the threat landscape: Golang has emerged as a premier ecosystem for botmasters. The language's native architecture, memory management, and compiler design provide a suite of built-in features that perfectly align with the operational requirements of a high-performance, evasive DDoS array.
7.1 Weaponized Concurrency (Goroutines)
A botnet's lethality is dictated by its concurrent throughput—the volume of simultaneous network connections it can sustain against a target. Golang addresses this natively through "Goroutines."
- Lightweight Execution: Goroutines are user-space threads managed entirely by the Go runtime scheduler, starting with an initial stack size of approximately 2KB.
- Multiplexing: The Go scheduler highly efficiently multiplexes thousands of these Goroutines onto a small number of actual OS-level threads.
- Attack Application: In the context of Apex2, this means an infected node can effortlessly spawn 50,000+ concurrent attack loops (as parsed from the
"threads"JSON C2 command) with minimal CPU and memory overhead. This transforms even a low-resource compromised desktop or IoT device into a devastating, high-volume DDoS cannon without crashing the host OS.
7.2 Frictionless Cross-Compilation
Botnets achieve critical mass by infecting diverse, heterogeneous environments, ranging from Windows enterprise endpoints to Linux cloud servers and ARM/MIPS-based edge routers.
- Native Environment Variables: The Go toolchain natively supports cross-compilation out of the box. A bot developer simply defines the target environment via the
GOOS(Operating System) andGOARCH(Architecture) variables during the build process. - Attack Application: As observed in the Apex2 memory artifacts (
GOOS=windows GOARCH=386), the botmaster uses a single, unified codebase to generate highly optimized payloads for virtually any architecture. This enables rapid weaponization across different platforms without needing to manage complex, platform-specific build chains.
7.3 Statically Linked Portability
Malware execution frequently fails if the victim machine lacks a required runtime environment, framework, or shared library.
- The Fat Binary: The Go compiler statically links the entire Go runtime, the garbage collector, and all imported packages directly into a single executable binary.
- Attack Application: While this results in large file sizes, but offers portability. The payload is entirely self-contained and operates completely independent of the host's installed libraries. When an Apex2 payload drops on a target, it guarantees a maximized infection-to-active-node ratio.
7.4 A Modern, Web-Native Standard Library
Botnets are fundamentally high-performance network applications. Go was engineered specifically for modern networking and scalable web infrastructure.
- Robust Networking Packages: The built-in
net,net/http, andcrypto/tlspackages provide enterprise-grade capabilities for manipulating TCP/UDP sockets and establishing secure tunnels. - Ecosystem Integration: The language's module system allows threat actors to seamlessly pull in, specialized networking repositories. As demonstrated by Apex2, implementing state-of-the-art Cloudflare WAF evasion was achieved effortlessly by importing the
refraction-networking/utlsandandybalholm/brotlipackages to forge, cryptographically perfect TLS Client Hello fingerprints.
7.5 Inherent Analysis Friction
While Go was not intentionally designed to obfuscate code, its compilation mechanics naturally generate significant friction for reverse engineers and automated analysis systems.
- Volume and Structure: A standard Go binary contains thousands of runtime and garbage collection functions natively. Locating the malicious main logic requires sifting through an ocean of benign library code.
- Non-Standard Calling Conventions: Stripped Go binaries lack standard stack frames, utilize complex interface types, and manage strings as contiguous memory blobs (pointer + length) rather than null-terminated arrays.
- Attack Application: This architectural complexity breaks many traditional static analysis heuristics. Automated YARA scanners, string extractors, and commercial sandboxes frequently fail to parse Go malware correctly—which directly enabled Apex2 to operate under the radar while misclassified as a generic stealer.