The Malware That Puts Itself Back: Inside a Self-Healing Infection
You find the malicious file. You delete it. You refresh the page, and it's back. Not the next day, not after the next attack: forty-five seconds later, sitting in the same folder with the same name.
If that has happened to you, you weren't careless and you didn't miss a step. You ran into a category of infection built to survive exactly what you just did. Most WordPress malware is passive: it sits in a file waiting to be executed, and when you remove the file it's gone. A smaller and much nastier category is active. It plants copies of itself in several places, and each copy watches the others and rebuilds any that disappear.
This guide describes how that architecture works, the five tells that identify a self-repairing infection on your site, and the mistake that makes people declare victory hours before the site is actually clean. You won't need to read any PHP.
Why deleting the file doesn't work
Picture the infection not as a file but as a small crew, each member carrying a copy of the blueprint.
The version we've taken apart most often keeps seven separate footholds. One lives in a configuration file that PHP reads on every request, before WordPress even starts. Another disguises itself as a WordPress "drop-in", a file WordPress loads before any plugin. Another appends itself to a file you legitimately need, like your active theme's functions.php, so the malicious part is thirty lines glued onto three hundred lines of code you actually want. Another hides in your cache folder, which most scans skip on the reasonable assumption that it's disposable.
Every one of these can rewrite the others.
That's the whole trick, and it's why the normal method fails. Find a bad file, delete it, look for the next one: by the time you're deleting the third, the first is back. You can do this for hours and make no progress, and the natural conclusion, that your deletions "aren't taking", is wrong. They're taking. Something is undoing them.
Five tells you're dealing with a self-healing infection
1. It comes back bigger
This is the clearest signal, and the one to check first. Note the file size before you delete, then check again after it returns. On one site the same file grew through five cycles: 221 KB, then 297 KB, then 508 KB, then 851 KB, and finally 1.88 MB. Each regeneration bundled a bit more of the infection into itself.
A file that returns identical was probably re-uploaded by an attacker who still has your password. A file that returns larger was rebuilt on the spot by code already running on your server. Different problems, different fixes, and the file size tells you which one you have.
2. The timestamps are lying
Sort by date modified and the malicious files look old and boring, which is the point. This family backdates what it writes.
The giveaway is that a file has two timestamps and the malware can only forge one. The "modified" date is easy to fake and it will say last March. The "changed" date, which your file manager usually hides but your host's SSH access shows, records when the file actually appeared, and it will say four minutes ago. If those two disagree wildly, you're looking at forged evidence.
3. It lives where WordPress looks before it looks at plugins
Ordinary malware hides among your plugins. This kind goes earlier in the boot order, into the files WordPress and PHP read before anything else: a .user.ini in your site root, a db.php or advanced-cache.php in wp-content, a file in wp-content/mu-plugins. Deactivating plugins does nothing to any of these, and neither, usually, does switching themes.
4. Your plugin list is lying too
On one site, the infection injected JavaScript into the WordPress admin that deleted its own row from the plugin screen and decremented the "Must-Use" counter above the list, so the number still matched what was visible. An owner reviewing their plugins would have seen a clean, internally consistent list.
Anything that hides from a dashboard can still be found on disk. Review the actual folders over FTP or your host's file manager, and never trust the plugin screen of a site you already believe is compromised. If you're not sure what belongs there, our field guide to fake plugins walks through the structural tells.
5. There's no obvious "hacker code" in it
People expect malware to contain the telltale functions scanners look for. This family contains none of them. It ships an array of roughly 1,200 harmless-looking text fragments plus a small routine that rebuilds real instructions from them using a letter-substitution scheme, the same idea as a childhood decoder ring. Nothing looks alarming to a pattern matcher, and it sails through signature-based scanning.
The trap: containment feels exactly like a cure
Here is the mistake, and it's easy to make because everything about it looks like success.
You can stop the infection rewriting a file by making that path impossible to write to. Do this across all seven footholds and the site goes quiet immediately. Nothing regenerates, scans come back clean, and on one cleanup the site stayed spotless for ten straight minutes, which felt conclusive.
It wasn't. Removing the blocks brought everything back in forty-five seconds, because the component doing the rebuilding was still alive and running on every page load, just temporarily unable to write. Blocking is a tourniquet, not surgery.
The rule: a site is only clean if it stays clean after you remove your own containment. Undo every block, then watch for several minutes. Whatever comes back is what you still haven't found.
Half of it isn't in your files at all
Even a perfect file cleanup can leave this infection running, because significant parts of it live elsewhere.
Roughly thirty settings get written into your WordPress database, including a full compressed copy of the payload, so it can rebuild itself from the database even if every file is gone. Scheduled tasks wake it up on a timer. In one case the spam being injected into pages wasn't in a file at all: it sat in the theme's "custom JavaScript" settings field and was served on every page load exactly as the theme intended.
Two pieces reach beyond the site entirely. The malware registers a service worker, a script browsers keep and keep running even after the site is fixed, so some visitors stay affected after your cleanup succeeds. And it serves a Google site-verification file straight out of the database, with no file on disk, letting the attacker keep ownership of your property in Google's tools no matter how carefully you scrub your folders.
Its instruction feed is equally awkward to shut down. Rather than a server that can be seized, this family reads its orders from a smart contract on a public blockchain, falling back through roughly twenty access points if any are blocked. There's no host to report it to and no domain anyone can take away.
What actually works
The method that works inverts the usual order. Instead of cleaning as you go, take a complete inventory first, touching nothing, and write down every hit, including copies with different names in different folders. On one site the same fake plugin existed twice, once in mu-plugins and once as a deactivated plugin, and cleaning only the first would have guaranteed the reinfection.
Then remove everything in a single pass: all file components, the database settings, and the scheduled tasks. Anything left behind is enough to rebuild the rest. Then take down your own containment and watch the site with nothing propping it up.
Two details save a lot of pain. When the infection is appended to a legitimate file, cut only the malicious block instead of deleting a functions.php your site needs. And on shared hosting, check the neighboring sites: an infection with this much persistence rarely settles for one.
The honest takeaway
If your site was cleaned once and came back, the likely explanation isn't that whoever cleaned it did a bad job. It's that they cleaned everything they could see, and something they couldn't see rebuilt it. Self-repairing infections punish partial cleanups specifically, and they're designed so a partial cleanup feels complete.
That's the problem Kornet is built around. Our scanner reads every file and the entire WordPress database in one pass, so components that would otherwise rebuild each other are found and removed together rather than one at a time, and the report shows you everything it touched. The scan is free; you only pay if we actually find malware.
Kornet Labs publishes field notes from real WordPress malware cleanups. The behavior described here was documented across four separate infected sites on four different hosting providers, all running the same version of the same malware family.
