Web shell persistence in BadIIS loaders
BadIIS sits in the class of commodity malware sold and reused across multiple Chinese-speaking threat groups. It has shown up in activity across Asia-Pacific, with cases also seen in South Africa, Europe, and North America. The main uses are SEO fraud, content injection, and proxy-based traffic manipulation, all of which depend on keeping control of the IIS server long enough to matter.
The loader survives because it is built for persistence, not elegance. Once installed, it can keep working after IIS restarts, which gives it a better chance of staying in place on a host that sees regular maintenance or service recycling. That makes it more than a one-off web shell drop. It behaves like a foothold with a job.
How BadIIS keeps a foothold inside IIS
The persistence model is blunt. BadIIS uses service-based installers and droppers to get code onto the server, then relies on the web server itself to keep serving traffic through the compromised path. The loader can also reverse proxy requests, which lets it inspect and redirect selected traffic without needing to break the whole site at once.
That split is useful for attackers. Public-facing content can keep loading while crawler traffic, language-based requests, or other selected sessions are diverted elsewhere. In practical terms, the host looks partially normal until someone starts comparing search results, crawl behaviour, or service logs against expected traffic patterns.
Service installs and restart survival
A service install is enough to make the compromise annoyingly sticky. Once the malware is running as a service or through a service-backed mechanism, a simple process restart does not clear it. That matters on IIS boxes, where service restarts are common enough that an operator may assume a clean reboot has fixed the issue.
The persistence also interacts badly with incident response. If the loader is tied into the service lifecycle, it can come back after routine recovery steps unless the underlying service entry, payload location, and supporting files are removed together. Leaving one piece behind is enough to make the server misbehave again later.
Where the web shell sits in the request path
BadIIS does not need to own every request. It only needs to sit where it can intercept the right ones. That makes request-path placement more important than noisier forms of compromise. If the loader can handle crawler requests separately, or steer traffic by browser language or environment, it can keep the site usable for ordinary visitors while feeding search engines or redirected users something else.
That behaviour is ugly in a very specific way. It is not a brute-force outage. It is selective interference, which makes detection slower because the site still answers and the damage hides inside the response logic. A crawler sees one thing, a user sees another, and the proxy does the sorting.
The artefacts that give the loader away
The family leaves more traces than it should. Cisco Talos identified embedded demo.pdb strings and a stable build pattern that points to a development environment rather than a clean release process. PDB paths such as C:\Users\Administrator\Desktop\...\Release\demo.pdb, along with x64\Release and Release variants, are the sort of thing that survives when the builder has been reused across iterations and customer-specific builds.
That matters because the artefacts show a long-running development line. The earliest explicit PDB timestamp seen was 2021-09-30, with later builds continuing into 2026-01-06. The same family also appears with directories and branches such as dll0217, dll0301, dll0315, dll-no503, dll(cur), J3, 2024-05-05-tcp, and customer-specific labels that include browser-language redirects and Baidu-related hijacking.
demo.pdb, build branches, and customer-specific paths
demo.pdb is a gift to defenders. It does not prove identity by itself, but it gives away a development habit that is hard to fake consistently across a long campaign. When the same build tree keeps leaking into binaries, the loader becomes easier to cluster with related samples, even when the operational payloads change.
The customer-specific paths are just as useful. Branches tied to Norton bypasses, Baidu browser compatibility, robots.txt hijacking, and browser-language redirects show a commercial model rather than a single-purpose implant. Someone is building variants for different clients or use cases, then pushing them through the same rough pipeline.
What the builder tooling changes before deployment
The recovered tooling does more than pack a payload. It generates configuration files, injects parameters into BadIIS binaries, customises payloads, and supports service-based installers and persistence mechanisms. That is a proper builder, not a loose collection of scripts.
It also includes evasion changes. Custom Base64 encoding, obfuscation, and Norton-specific bypass branches show active reaction to detection pressure. Once security products start catching a build, the next version changes shape rather than stopping. That is the boring advantage of commodity malware: it can be revised quickly and sold again.
Closing the gap with detection and hardening
The most useful signals are the awkward ones. IIS 503 Service Unavailable errors can expose a bad loader, especially when they appear after compromise or coincide with service instability. Odd proxy behaviour, crawler redirection, and language-based branching are harder to excuse as normal site drift. If the site answers differently for search crawlers, browsers in different languages, or requests that should land on the same content, something is already off.
A practical control is to watch the service state and the request path together. If IIS keeps serving but selected traffic starts disappearing into a proxy or getting rewritten, treat that as a compromise pattern rather than a web content issue. The same goes for unexplained changes in robots.txt handling or crawl responses.
Watch for 503 errors, proxy abuse, and odd language-based redirects
503 Service Unavailable is not just a nuisance here. It can be the visible failure mode when the malware trips over service handling or mismanages the request path. If those errors appear alongside unusual redirects or crawler-only interference, the server should be treated as suspect.
Language-based redirection is a cleaner tell than it first looks. Normal sites can route by locale, but they rarely do it in a way that sends search traffic or specific browsers to different infrastructure while the original content still looks intact. That sort of split is what turns a compromised IIS box into a traffic broker.
Test the dump path, crawler handling, and IIS service behaviour
Check what the server does under service restart, not just whether the site loads once. A loader that survives restarts needs a full removal path, not a surface-level clean-up. If the compromise touches the dump path or the service install path, look for leftover files, service entries, and any binary that still matches the strange build artefacts.
Crawler handling deserves the same treatment. Request the site as a crawler, compare the response path, then compare it again through normal browser traffic and different language settings. BadIIS relies on that split. If the paths diverge, the compromise is already doing its job.



