In 2022 a researcher publishing as port22 characterised the SSH botnet that implants an authorized_keys entry commented mdrfckr, and gave defenders a transport-layer fingerprint for it: the HASSH value 51cba57125523ce4b9db67714a90bf6e, corresponding to a client announcing SSH-2.0-libssh-0.6.3. They reported it identified the campaign with 99.1% confidence across 12,913 unique source addresses over October and November 2022.

Four years later I have 632 implants of the same key in my own honeypot logs. That is a rare opportunity: a published indicator, a documented confidence level, and an independent corpus to test it against. So I tested it.

The fingerprint matched nothing. Not a reduced hit rate - zero of 632 sessions. Meanwhile the payload those sessions delivered had not changed by a single byte in four years. This article is about that asymmetry, because it is the practical part: some indicators rot in months and some do not rot at all, and the difference is predictable.

[INFO]
All figures below come from 1,251,496 Cowrie events captured on a Hetzner VPS in Helsinki between 12 August and 10 September 2026, analysed from the raw JSON logs. Method and limitations are at the end. The 2022 figures are port22's, not mine.

//The Test

I extracted every cowrie.command.input event whose command contained authorized_keys, parsed the base64 key blob out of each one, and grouped by key. 644 implant events across five distinct public keys, from 514 distinct source addresses. One key accounts for 632 of the 644, implanted from 511 addresses. That key is the mdrfckr key.

For each of those 632 sessions I then pulled the hassh value Cowrie recorded at key exchange, and compared it to the published one.

[TECHNICAL NOTE]
Result: 0 of 632 sessions matched HASSH 51cba57125523ce4b9db67714a90bf6e. Across the whole 1.25M-event corpus, that HASSH appears zero times from any source, implanting or otherwise.

This is not a case of a fingerprint becoming noisy or losing precision. The 2022 indicator has no presence in 2026 traffic at all. Anyone still running it as a detection rule is running a rule that cannot fire.

//What Replaced It

The 632 sessions carry three principal HASSH values, each pairing cleanly with a client version string:

f555226df1963d1d3c09daf865abdc9a - 587 sessions (92.9%) - SSH-2.0-libssh_0.9.6
03a80b21afa810682a776a7d42e5e6fb - 35 sessions (5.5%) - SSH-2.0-libssh_0.11.1
af8223ac9914f509afdadfaf5f7ee94e - 7 sessions (1.1%) - SSH-2.0-libssh_0.12.0

Three further sessions announce libssh_0.9.6 but hash to 671ac49b8bd65b9e8ff02a3e690f0fd3 (2 sessions) and 3cb24313ef7969100a7527f11b569cd4 (1 session). That matters more than the counts suggest: it means the version banner and the algorithm set disagree in a small number of cases, so the banner alone is not a substitute for the hash.

The newest builds negotiate post-quantum key exchange

The seven libssh_0.12.0 sessions offer this KEX list:

mlkem768x25519-sha256, mlkem768nistp256-sha256, sntrup761x25519-sha512, [email protected], curve25519-sha256, [email protected]

libssh 0.12.0 was released on 10 February 2026 and made those hybrid post-quantum exchanges its preferred options. By August 2026 the botnet was running it. Nobody wrote post-quantum cryptography into this malware - the operators bumped a dependency and inherited it, the same way any other software does. It is a useful reminder that commodity malware tracks library releases on roughly the timeline of the distributions it runs on, not on some separate adversary schedule.

◈ interactive artifact
HASSH Explorer: Why the 2022 Fingerprint Died
Compare the algorithm lists behind each observed libssh build. Only configurations actually captured are shown.

//The Payload Did Not Move

Against three transport fingerprints across four years, the delivered payload is static to a degree that is genuinely striking. All 632 implants used one command string, byte for byte identical, with zero variation across 511 source addresses and 30 days:

cd ~ && rm -rf .ssh && mkdir .ssh && echo "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEArDp4cun2lhr4... mdrfckr">>.ssh/authorized_keys && chmod -R go= ~/.ssh && cd ~

It is the same command string port22 published in 2022 and the same one Michael Edie documented in April 2023. The key itself is also unchanged, and it has an unusual property worth recording:

[IOC]
IOC - implanted RSA public key (stable 2022 to 2026):
MD5 13:47:1e:8f:5a:18:fc:8e:35:0a:51:cc:7d:b4:06:61
SHA256 SHA256:MkYY9qiVsFGBC5WkjoClCkwEFW5iSjcGQF7m4n4H7Cw
2048-bit modulus, public exponent 37, comment mdrfckr

Public exponent 37 is not what any standard tool produces. ssh-keygen, OpenSSL and every mainstream library default to 65537. A 2048-bit RSA key with exponent 37 is a distinguishing feature on its own, and unlike a HASSH it cannot drift: changing it means generating a new key, which means abandoning access to every host already carrying the old one. The operators have four years of accumulated persistence tied to this exact modulus. That is precisely why it has not changed.

Credentials are the wrong place to look

For completeness I checked whether the credential used on the implanting session was itself an indicator. It is not. Across 632 implants the most frequent username and password pair occurs three times (gmbh:gmbh), followed by a long tail of pairs appearing twice or once. The implant follows whatever credential happened to work, so the credential carries no campaign signal at all.

//Automation, Measured

Median time from TCP connect to the implant command firing was 2.13 seconds, mean 2.11, 95th percentile 3.56, minimum 0.10 and maximum 13.13. Every one of the 632 sessions completed the implant inside 14 seconds of the connection opening.

For context, SANS ISC published a walkthrough in May 2026 of an actor reaching persistence 22 seconds after login, and framed that as fast. It is, for a session that also performed reconnaissance. The distribution here is a narrower measurement - connect to key implant, nothing else - and it shows the persistence step alone as a sub-three-second automated reflex. There is no interactive phase to interrupt.

//Source Distribution

The 511 addresses spread across 494 distinct /24 networks. 413 implanted exactly once, 82 twice, 10 three times, 5 four times, and one address five times. There is effectively no network clustering to block on, which is the expected shape for a botnet drawing from a pool of previously compromised hosts rather than operating its own infrastructure.

This is also why the shared key is the useful indicator and the source address is not. Blocking 511 addresses defends against 511 already-compromised machines and nothing else; the pool is replaced continuously.

//What This Means For Detection

The general lesson is that indicators have predictable decay rates, and the rate is set by how much the operator loses when the indicator changes.

A HASSH costs nothing to change. It is a hash of the algorithm lists a client offers, so it moves whenever the underlying library is rebuilt - no intent, no evasion, no decision. The mdrfckroperators almost certainly did not set out to break port22's fingerprint; they updated from libssh 0.6.3 to 0.9.6 to 0.11.1 to 0.12.0 over four years like anyone else, and the fingerprint died as a side effect. Any indicator derived from a dependency inherits that dependency's release cadence as its own expiry date.

The implanted key costs a great deal to change, because it is the access. Rotating it orphans every host already backdoored. So it has survived four years, three libssh generations, and a migration to post-quantum key exchange without a single byte moving.

Practically: rank indicators by what rotating them costs the adversary, and set review intervals accordingly. Transport fingerprints are worth having - they are cheap to compute and they work now - but they need an expiry date attached and a scheduled retest. Payload artefacts tied to the adversary's own access are the ones worth building durable detection on.

[IOC]
IOC - current mdrfckr transport fingerprints (valid as of September 2026, expect decay):
HASSH f555226df1963d1d3c09daf865abdc9a - libssh_0.9.6
HASSH 03a80b21afa810682a776a7d42e5e6fb - libssh_0.11.1
HASSH af8223ac9914f509afdadfaf5f7ee94e - libssh_0.12.0
HASSH 671ac49b8bd65b9e8ff02a3e690f0fd3 and 3cb24313ef7969100a7527f11b569cd4 - low volume, banner says libssh_0.9.6
Superseded: 51cba57125523ce4b9db67714a90bf6e (libssh-0.6.3, published 2022) - zero hits in 2026

//Retest, 18 September

The argument above is that transport fingerprints decay and therefore need a scheduled retest. It would be poor form to publish that and not do it, so here is the same test run against 11 to 17 September, a week of logs that did not exist when this was first published.

110 implants of the same key, from 104 distinct addresses. The distribution is almost unchanged:

f555226df1963d1d3c09daf865abdc9a - 101 sessions (91.8%, was 92.9%)
03a80b21afa810682a776a7d42e5e6fb - 6 sessions (5.5%, was 5.5%)
af8223ac9914f509afdadfaf5f7ee94e - 1 session (0.9%, was 1.1%)
671ac49b8bd65b9e8ff02a3e690f0fd3 - 1 session (previously listed as low volume)

The published set covers 109 of 110 implants, or 99.1%. port22's 2022 fingerprint scored zero again. So over a one-week horizon these indicators hold, which is the useful half of the answer: they are worth deploying, they are not worth deploying and forgetting.

One new value, and it makes the earlier point

The single implant not covered is 713bd9cc935561939c02dad25af2d3de, from 102.88.137.80. Its banner reads SSH-2.0-libssh_0.11.1 - the same version as 03a80b21 - but it offers a different cipher and MAC list, so it hashes differently.

That is the banner-and-hash disagreement described earlier, appearing again in fresh data. Same library version, different build or configuration, different fingerprint. It is also a reminder that the drift here is continuous rather than episodic: one week produced one new value at roughly 1% of volume. Add that to your set, and plan on repeating this in another month.

//Method, and What This Does Not Show

One Cowrie sensor, one IP address, port 22 exposed directly, no announcement and no obfuscation, 12 August to 10 September 2026. Events parsed from the raw cowrie.json daily files rather than from the aggregated API. Implants identified by parsing the base64 key blob from command input, so the count is of implant commands observed, and the honeypot accepts all credentials by design.

Three things this deliberately does not claim:

It is not a rate comparison. port22 saw 12,913 unique addresses in two months in 2022; I saw 511 in one month in 2026. Those numbers are not comparable. Different sensor, different exposure, different address space, different collection period. Nothing here supports a claim about whether the campaign has grown or shrunk, and treating a 25-fold gap between two unrelated sensors as a trend would be exactly the sort of unsourced inference this site tries not to publish.

HASSH is not attribution. It fingerprints an SSH client build, not an actor. The three values above identify libssh versions that this campaign happens to use; other software using the same libssh builds will collide with them. The pairing of a HASSH with the implant payload is what makes it useful here, not the hash alone.

The version bump is the parsimonious explanation, not a proven one.I cannot see the operators' build process. Deliberate evasion would produce the same observable. I am claiming the simpler reading - routine dependency updates - because the timing tracks libssh releases and because a campaign deliberately evading fingerprints would have had little reason to leave the payload byte-identical.

Reproducing this

The test is cheap and worth repeating against any corpus that contains the key. Group cowrie.command.input events by parsed key blob, join to the hassh and version fields on the same session, and compare against the published value. If you run a honeypot and get a different HASSH distribution, that is a more interesting result than this article and I would like to hear about it.

//References

port22, mdrfckrs - part one (2022 characterisation, HASSH and campaign figures): blog.port22.dk/mdrfckrs-part-one/
Michael Edie, Honeypot Diaries: SSH Authorized Keys, April 2023 (independent capture of the same command string): blog.edie.io/2023/04/16/honeypot-diaries-ssh-authorized-keys/
SANS ISC, 22 Seconds to Compromise, May 2026 (login-to-persistence timing): isc.sans.edu/diary/33220
libssh, libssh 0.12.0 and 0.11.4 security releases, 10 February 2026 (post-quantum KEX defaults): libssh.org/2026/02/10/libssh-0-12-0-and-0-11-4-security-releases/