LSN โ€” Local Sovereign Network

One Binary, Many Masks: The Go Toolkit Behind the Honeypot's Miners and Backdoors

The Toolkit โ€” Part 1

Classification: HIGH ยท Confidence: HIGH (first-party sample analysis)

This investigation opened as a study of the honeypot's mining problem. The estate's single largest malware family, by the classifier's count, is XMRig โ€” thirty-three retained samples, more than any other, the multi-megabyte Monero miners that Part 6 of the companion Raspberry Worm series named as the dominant product of the compromised-Linux market. The intent was to profile that mining campaign: its pools, its wallets, its scale. Pulling the samples apart produced a different and larger finding, one that reorganises the whole picture of what is actually operating on this honeypot.

The "XMRig miners" are not miners. They are thirty-megabyte statically-linked Go binaries that carry XMRig as one configurable feature among several โ€” and they are compiled from the same source tree as the PAM credential-backdoor toolkit that the Raspberry Worm series, in its eighth letter, catalogued as a separate operation. The build hash proves it. What the classifier filed under "XMRig" and what it filed under "PAM Backdoor" are one modular implant, one operator's Swiss-army tool that mines, backdoors, spreads, and clears rivals from a single executable. The honeypot's biggest family and its most sophisticated persistence toolkit are the same thing, wearing two labels. This series is about that toolkit, and this first letter is about discovering it was one thing all along.

The family that isn't a miner

Start with what the thirty-three "XMRig" samples actually are. They are not the compact, purpose-built XMRig binary an operator would drop to mine a host. They are enormous โ€” a consistent 8-megabyte on-disk footprint unpacking to roughly thirty megabytes โ€” and their internals are unmistakably Go: the strings are thick with Go runtime diagnostics (gopark: bad g status, runtime: newstack, chansend: spurious wakeup), the Go HTTP/2 stack (http2: Framer, WINDOW_UPDATE, MAX_HEADER_LIST_SIZE), TLS and x509 machinery, and an SSH client (channelOpenConfirmMsg, keyboard-interactive, ssh: packet too large). A raw XMRig miner is a C++ program a few megabytes in size; a thirty-megabyte Go binary with a full HTTP/2 client, a TLS stack, and an SSH implementation is not a miner. It is an agent.

XMRig appears inside it not as the program but as a configuration preset. The binaries carry the field names of a settings structure โ€” current_preset_xmrig_poolAddr, current_preset_xmrig_poolUser, current_preset_xmrig_poolPass, current_preset_xmrig_algo, current_preset_xmrig_enabled, current_preset_xmrig_nicehash โ€” the JSON-tagged fields of a Go struct that configures an XMRig deployment. This is the signature of a management agent that can turn mining on, point it at a pool, and set its parameters, not of the miner itself. The classifier saw the string xmrig throughout and labelled the family XMRig, exactly as, in the worm series, it saw miner-killing strings and mislabelled a worm as XMRig four times. The lesson repeats: a family name derived from content is a hypothesis, and here the hypothesis mistook the tool that manages the miner for the miner.

Thirty-three of these agents, the largest single family on the estate, dropped across four months โ€” 2026-03-26 to 2026-07-20 โ€” with the primary sample delivered thirteen times from thirteen distinct hosts. Whatever this toolkit is, it is the honeypot's most-seen serious malware.

The preset architecture is worth naming as such, because it is the design that makes one binary into many tools. The current_preset_xmrig_* fields are not standalone settings; the naming implies a presets system โ€” a configuration layer in which "xmrig" is one named preset among presumably several, each a bundle of settings that switches a whole capability on and points it somewhere. An operator deploying the toolkit does not compile a miner or a backdoor; they ship one agent and hand it a preset โ€” xmrig for this host, credential-harvest for that one โ€” and the same binary becomes whichever tool the target warrants. This is why the family fractured across classifier labels: a build with the mining preset active surfaces xmrig strings and is called XMRig; a build with the PAM preset active surfaces libpam strings and is called a PAM backdoor; both are the identical executable configured differently. Modern malware, like modern software, is increasingly configuration over code โ€” and a presets-driven Go agent is the malware-author's version of the same shift, one artifact whose behaviour is set by data rather than recompiled per purpose.

The hash that joins two families

The proof that these agents are more than miners โ€” and the central finding of this letter โ€” is a build artifact. Every one of the Go binaries examined carries, stamped through its cgo-wrapper symbols, the package hash eba3282b571c. That string is not decorative: a cgo build hash is generated from the specific Go source package a binary was compiled from, and two binaries carrying the same one were built from the same code.

eba3282b571c is the exact hash the companion series' eighth letter found in the PAM backdoor toolkit โ€” the Go binaries that hook libpam to harvest credentials and accept a magic password. That letter, examining those PAM samples in isolation, correctly identified them as a modular Go toolkit and correctly declined to link them to the bash Raspberry Worm. What it could not see, looking only at the samples the classifier had filed under "PAM," was that the same hash runs through the samples filed under "XMRig." The credential-backdoor toolkit and the mining agent are the same codebase. The persistence tool that Part 8 called "the other tenant" and the mining family that dominates the corpus are one operator's single, modular implant, compiled with different features foregrounded and scattered by the classifier across two unrelated-looking labels.

This is the durable-correlator lesson of the worm series' fourth letter, arriving on a completely different operator. There, a per-drop-mutating bash worm was unified across thirteen file hashes by one thing its author could not cheaply change โ€” an RSA signing key. Here, a Go toolkit is unified across two classifier families by one thing its author could not cheaply change โ€” a cgo package hash baked in at compile time. Two operators, two eras, two languages, and the same forensic truth: the family label fragments a campaign, and a durable build artifact reassembles it. eba3282b571c is this operator's MIGfโ€ฆ key.

What the one binary does

Once the two families are seen as one toolkit, the capabilities scattered across them assemble into a single, coherent, alarming feature set. From the binaries' own strings, one executable is built to do all of the following:

Mine, backdoor, spread, evict, command, conceal โ€” in one Go binary, configurable by preset. This is not a miner that also does a few things. It is a general-purpose host-takeover platform with mining as one selectable payload, credential theft as another, and self-propagation and competitor-eviction built into the frame. The thirty-three "XMRig" samples are that platform with the mining preset prominent; the PAM samples of Part 8 are the same platform with the credential preset prominent. It was always one tool.

The cleaner: stealth and murder in one script

The competitor-eviction the toolkit ships deserves a closer look, because the retained cleaner script is a compact masterclass in doing two jobs at once โ€” clearing rivals and covering tracks โ€” and it names its enemy explicitly. Its routine, read from the bytes:

chattr -ia /var/spool/cron/crontabs        # unlock immutable cron
crontab -l | grep -vE 'wget|curl|/dev/tcp|/tmp|\.sh|nc|bash -i|...' | crontab -
for dir in /etc/cron.hourly /etc/cron.daily .../cron.d; do clean_file ...; done
pkill -9 systemtd; pkill -9 "/usr/bin/.sh"; pkill -9 -f "/bin/-bash"
systemctl disable c3pool_miner; systemctl stop c3pool_miner
kill -9 $(lsof -t -i:<port>)
for dir in /tmp /var/tmp /dev/shm; do find "$dir" -mindepth 1 -delete; done
echo >/bin/systemtd; echo >/bin/-bash; echo >/usr/bin/.sh
clean_file ~/.bashrc; clean_file ~/.profile; clean_file ~/.bash_profile

Read it as two overlapping intentions. The eviction half hunts other malware: it strips any cron entry that looks like a downloader (wget, curl, /dev/tcp, base64), truncates the disguised competitor binaries systemtd, -bash, and .sh to empty files, kills whatever process holds a mining port with lsof, and โ€” the specific tell โ€” stops and disables c3pool_miner, the systemd service of a widely-used one-click Monero-mining installer. This operator has decided C3Pool is a common enough rival on freshly-compromised hosts to name it in the eviction routine. The anti-forensics half hides the toolkit's own arrival: chattr -ia unlocks files a defender might have locked, the ~/.bashrc/~/.profile scrubbing removes shell traces, and the wholesale wipe of /tmp, /var/tmp, and /dev/shm clears the scratch space where evidence and rivals alike accumulate.

The overlap of the two intentions is the sophistication. A crude worm kills competitors or cleans up; this toolkit's cleaner does both in one pass, because to the operator they are the same task โ€” a host is only fully held when it carries no rival malware and no trace of how the toolkit got in. The same chattr that unlocks a rival's persistence unlocks the defender's hardening; the same cron scrub that removes a competitor's downloader removes the evidence trail. Eviction and stealth are the two faces of exclusive, quiet possession, and the cleaner is built to deliver both at once.

How a Go worm spreads โ€” by stealing trust

The toolkit's propagation is where its sophistication most sharply outclasses the bash Raspberry Worm, and the mechanism is visible in the strings. Where the worm spreads by guessing โ€” blindly trying pi:raspberry against the whole address space via sshpass โ€” the Go agent spreads by stealing trust. Its embedded SSH client, together with its references to id_rsa, known_hosts, and /etc/ssh/ssh_host_rsa_key, describes a fundamentally smarter lateral-movement model: on each host it takes, it can read the host's own SSH private keys and its known_hosts file โ€” the record of every other machine this host has legitimately connected to โ€” and use those stolen keys to log into exactly the hosts that already trust the compromised one.

This is the difference between a burglar trying the same key on every door in the city and a burglar who, having entered one house, takes its keyring and walks straight into the specific houses those keys open. Blind credential-guessing finds only the hosts with weak default passwords; trust-theft finds the hosts an administrator's own workstation can reach โ€” the servers, the internal infrastructure, the machines that a default-password worm can never touch because they were never exposed to the open internet with pi:raspberry. A worm that harvests id_rsa and known_hosts propagates inward, along the network's own trust relationships, from a compromised edge device toward the valuable interior it connects to. That is initial-access-broker propagation of a far higher order than the worm's, and it is exactly what you would build if the host was never the target so much as the doorway to everything it trusts.

The market had fewer players than it looked

This finding corrects a picture the companion series drew, and the correction matters. Part 6 of the worm series described a "three-cornered market" over each compromised host โ€” miners after the CPU, DDoS fleets after the bandwidth, and access-brokers after the host itself โ€” and treated the corners as distinct operators. Part 8 added a fourth, the PAM wiretap, as yet another separate tenant. But the eba3282b571c hash collapses two of those supposedly-separate operations into one. The "miner" (the CPU corner) and the "PAM backdoor" (a persistence tenant) are not two operators competing for the same host; they are one operator's toolkit doing two jobs. The mining agent and the credential wiretap were never rivals. They were features.

So the market at the honeypot's door has fewer independent players than the label-count suggested, and one of them is markedly more capable than the rest. Where the bash Raspberry Worm is a crude single-purpose script and the Whisper and Nexus fleets are focused DDoS loaders, this Go operator runs a unified platform that can extract whatever a given host is worth โ€” its cycles, its credentials, its position for spreading โ€” from one implant, deciding per-target which feature to foreground. That is a different and more serious adversary than a miner: it is an operator who does not commit to a monetisation model at infection time but keeps all of them available in a single tool and chooses later, per host, exactly the flexibility the worm series' access-broker analysis identified as the modern direction. The honeypot's biggest "mining problem" is, on inspection, its most sophisticated general-purpose intrusion toolkit โ€” and it had been hiding, all along, behind the least alarming label the classifier could have given it.

What holds, and what is bounded

What holds, first-party: the thirty-three "XMRig" samples are ~30 MB statically-linked Go binaries carrying an XMRig configuration preset (xmrig_poolAddr/User/Pass/algo/nicehash), a Go HTTP/2 + TLS stack, and an SSH client; every one examined carries the cgo build hash eba3282b571c, the same hash present in the Part 8 PAM-backdoor binaries; and the family's cleaner script performs competitor eviction including the named termination of c3pool_miner. All read directly from the honeypot's retained samples.

What is bounded: the shared-hash link between the "XMRig" and "PAM" families is confirmed on the samples examined in depth, and inferred across the full ~40-plus binaries of the two label-groups from that consistency; a complete enumeration would confirm every member, which this letter did not exhaustively do. And crucially, no mining pool or wallet was extracted. The xmrig_poolAddr field is a configuration slot, populated at deploy time โ€” likely from the remote configuration the HTTP/2 channel and the bucket.* references imply โ€” not a value hardcoded in the static binary. The toolkit's mining is confirmed by the preset machinery; the specific pool and wallet it points at are runtime configuration this static analysis cannot see, and are an honest gap.

What is not claimed: the operator's identity, and any link to the bash worm's operator or to the Whisper/Nexus fleets. This toolkit is a distinct, sophisticated Go operator; the eba3282b571c hash correlates its own builds across the miner and backdoor labels, and nothing further. Whether it, too, distributes from the documented bulletproof network โ€” as the worm's spreaders and the Whisper/Nexus servers did โ€” is a thread for the next letter, not a claim in this one.

Core IOCs

Cross-references

The investigation set out to profile a mining campaign and found instead that the honeypot's largest family was never really about mining at all. Mining is one switch on a Go-built platform that can also steal every password on a host, spread itself to the next, and murder the competition โ€” a general-purpose takeover toolkit that the classifier, seeing the least dangerous of its features, filed under the least dangerous of names. One binary, many masks, and a single build hash under all of them. The following letters take the masks off one at a time.

โš  Personal capacity. Research published independently โ€” not reflecting employer views. Derived from passive observation of attacks against personal infrastructure. Full disclaimer โ†’
โ† Previous The Toolkit โ€” 1 / 4 Next โ†’