Two identical bots, one invisible
Two files landed in the honeypot five days apart, from two different IP addresses. Both were exactly 29,427 bytes. Both were the same Perl IRC bot.
One of them, dropped as /duba, is flagged by 29 of 60 engines on VirusTotal as trojan.perl/shellbot. It has been submitted, catalogued, and signatured.
The other, dropped as /dodu, has no VirusTotal record at all. Not a clean verdict — no record. Nobody has ever uploaded it.
That pair is the most useful thing in this capture, and it is a good argument for running your own honeypot rather than only consuming other people's feeds.
The capture
Twenty-five samples, collected between 28 July and 7 August 2026, sorted into seven families:
| Family | What it is |
|---|---|
| MIRAI_OHSHIT | Multi-arch IoT botnet, 16 architectures |
| MIRAI_TELNETCURL | Telnet-propagated Mirai variant, 5 architectures |
| PERLBOT_SHELLBOT | Perl IRC shellbot, the twins above |
| GSOCKET_SSHIT | Abuse of a legitimate security tool for persistence |
| MIRAI_LOADER | Unobfuscated Mirai loader |
| BOTKILL_PROCWIPE | Competitor removal — not a bot at all |
| WEBROOT_PROBE | Mass RCE verification, 224 sightings |
Nineteen of the twenty-five arrived over telnet. In 2026.
The twins, properly
/duba and /dodu are the same size but not the same file — their MD5, SHA-1 and SHA-256 all differ. They are two builds of one bot, and the difference is the config block:
/duba: my $server = '213.139.77.150'; my $port = '6667';
/dodu: my $server = '213.177.179.11'; my $port = '6667';
Different C2 servers, different /16. A third sample, /gots, points at the same server as /dodu and also has no VT record.
So blocking the well-known IP accomplishes about a third of the job. This is the ordinary shape of the problem: the sample everybody has is the one that stopped being useful to the operator.
There is a further wrinkle. All three bots contain this line:
$server = "$ARGV[0]" if $ARGV[0];
The C2 is overridable at launch. Any IP-based block is defeated by restarting the bot with an argument. The control that actually holds is an egress block on tcp/6667 — and outbound cleartext IRC from a server or IoT subnet is close to nonexistent on a modern network, so it costs almost nothing in false positives.
A turf war in the loot
Two samples arrived as /home/.k, written straight over telnet. Neither is a bot. Both are short shell scripts that kill things.
The first walks /proc and kills any process whose executable has been deleted from disk:
result=$(ls -l "/proc/$pid/exe" 2> /dev/null)
if [ "$result" != "${result%(deleted)}" ]; then
kill -9 "$pid"
fi
Self-deleting after execution is standard IoT-botnet hygiene, so this reliably kills other people's bots while leaving normal daemons running.
The second is more targeted. It reads each process's command line and kills anything containing the string dvrHelper.
dvrHelper is the output filename used by MIRAI_LOADER — another family in this same capture, fetching mirai.<arch> from 77.90.185.66. One operator is actively hunting another's payload on the same boxes.
The practical consequence: a host with /home/.k on it has been compromised by at least two separate actors. Reimage it. Don't clean it.
C2 that dresses as infrastructure
The seven MIRAI_OHSHIT payloads carry an identical, compiled-in domain set:
api-relay-3.metrics-collector.io
cdn-edge-updates.hostcloud-eu.net
mgmt-panel.serverstats-daemon.com
sync.softwaremirror.workers.dev
glibc.malloc.top
control.tor2web-relay-fast.onion
A metrics collector. CDN edge updates. A server stats daemon. A software mirror. And glibc.malloc — a hostname built to survive a tired glance at a DNS log.
Because the set is byte-identical across ARM, ARM7, SH4, MIPS, PowerPC, i686 and x86-64, it is compiled in rather than per-build. That means a string-based rule covers the nine architectures the loader fetches that we never captured.
Those payloads also embed a full SSH client — ssh-ed25519, curve25519, chacha20. The loader chain is telnet-only, so anyone scoping containment from the dropper alone will miss the SSH vector entirely.
The most-seen sample is the least interesting file
By sighting count, the two clear winners are these, at 168 and 56 hits over nine days:
#!/bin/sh
echo "xxxxxx"
Twenty-four bytes. Written to /var/www/html/filter over SSH.
It is a capability probe. The operator writes a trivial script into the webroot, requests it, and looks for xxxxxx in the response. A hit confirms both webroot write access and script execution — after which they come back with something real. The absence of a payload is timing, not luck.
Writing a YARA rule for this would be malpractice; echo "xxxxxx" in a two-line shell script will match test fixtures and scaffolding across any estate. The value is entirely in the 18 source addresses, which rotate about two per day inside five /24s:
2.57.122.0/24 92.118.39.0/24 80.94.92.0/24
195.178.110.0/24 193.32.162.0/24
Per-host blocking will always lag that rotation. Block the ranges.
A mistake worth publishing
Partway through, I searched the ELF payloads for domains and concluded there weren't any interesting ones. I had anchored the pattern like this:
[^a-z0-9.-][a-z0-9-]{2,20}\.top\b
The anchor requires a non-label character before the domain. Every real domain in those binaries is multi-label, so the character before metrics-collector.io is a dot — which that class explicitly excludes.
The anchor didn't remove noise. It removed the signal, and it would have suppressed five live C2 domains.
Both failure modes are real. An unanchored pattern run over raw bytes invents domains that don't exist. An over-anchored one silently drops the ones that do, and a false negative doesn't announce itself. Match against extracted strings, not raw bytes, and allow multiple labels.
What is published
Everything above is in the repo, TLP:WHITE:
blocklist.txt— 41 IPs and 5 domains, plain newline-delimited- Annotated firewall entries with family, role and confidence
- Port and egress rules, including the IRC block a target list can't express
- YARA, Suricata and Sigma rules, validated against YARA 4.5.5 with zero cross-family false positives
- A written analysis per family, and all 25 samples AES-256 encrypted
Deliberately not in the blocklist: GitHub Pages (185.199.108.153) and Cloudflare (104.21.234.17), both of which appear inside these binaries. Also gsocket.io and thc.org — one payload abuses THC gsocket, a legitimate published security tool. Attribute the abuse, not the tool.
Every exclusion is written down with its reasoning, so you can check the work rather than trust it.