Tengu is a modern Mirai-derived IoT malware family that shows how today’s botnets are evolving beyond simple distributed denial-of-service tooling. We selected tengu for deeper analysis because it stood out from the many Mirai-derived samples we track, and because it was surfaced by our machine-learning system for identifying previously unknown malware families. It combines a custom encrypted command-and-control protocol, proxy functionality, payload updates, system and network discovery, and a broad set of denial-of-service capabilities targeting multiple protocols and services. It also includes multiple persistence and self-defense mechanisms designed to keep the malware running on compromised Linux-based devices and make recovery more difficult.
For defenders, the key takeaway is that exposed and poorly maintained IoT and embedded Linux systems remain attractive footholds for attackers. Once compromised, these devices can be used not only to participate in large-scale DDoS campaigns, but also to proxy traffic, collect host and network information, download additional payloads, and resist removal. This makes timely patching, removal of default credentials, network segmentation and continuous monitoring of unusual device behavior essential for reducing exposure.
Technical Deep-Dive on Tengu
The Tengu samples we analyzed share several traits with Mirai, including plaintext registration packets, attack-vector registration, encrypted string initialization, and portions of the DoS attack code. However, tengu also adds more modern capabilities, including AEAD encryption for C2 commands, multiple anti-analysis measures, proxy functionality, update support, and additional attack methods, some of which target game protocols.

The dropper observed in our honeypots arrived via Telnet brute force. It was a simple shell script that downloaded and executed architecture-specific samples over HTTP from the same host used as the C2 server.
C2 communication

Once the malware runs, it deobfuscates the C2 address at runtime using XOR with 0x22. In this sample, the configured C2 address is 64[.]89.163.8 and the hardcoded port is 9931. The sample also contains logic associated with DGA-style domain generation based on the current time and randomly selected TLDs, although we did not observe this capability being used in practice.

The protocol sends the initial registration message, heartbeat messages, and command output in plaintext. Server-to-bot commands and update messages, however, are authenticated and encrypted using a ChaCha20/Poly1305-like encryption scheme. The encryption key is embedded in the sample and can be recovered by XORing two 32-byte values. In the 097522a52986982b9eefc29f95efdd9d3b6032e7 sample, the recovered key is c2a1b84d9f73512e8a6c15f0b4d9e73b114a66895dc328927e34a5b148ce6103.

The following commands can be sent from the server to the infected system:
- Proxy start: Starts a proxy based on the provided option. The PID is written to
/tmp/.proxy.pid.Default protocol is socks5. Port and authentication credentials can be passed as parameters. - Proxy stop: Kills the proxy based on the stored PID and then deletes the PID file.
- Network info: Exfiltrates information about the network configuration, such as the network interfaces, local IP/MAC addresses, default gateway, configured DNS server.
- Stop Attack: Terminates all running processes performing DoS attacks.
- System info: Exfiltrates system information back to the server. Includes kernel version, CPU, RAM, free memory, uptime, processes, load average.
- Execute command: Executes a command sent by the server and sends the output to the server.
- cron persistence: Attempts to modify cron-related files for persistence, but the implementation appears unfinished or broken. The appended entry references /proc/self/exe, which would be resolved by the process executing the cron command rather than reliably pointing back to the installed malware binary.
- systemd persistence: Adds a fake systemd service to achieve persistence.

- initd persistence: Adds init.d service to ensure persistence.
- Launch DoS attack: Starts DDoS workers using a broad set of Mirai-style and application-layer methods. 25 attack methods are registered in total. Supported traffic includes UDP floods with spoofed source addresses; TCP SYN, ACK, PSH, and payload floods; ICMP echo floods; mixed TCP worker modes; and protocol-specific probes for HTTP, DNS, NTP, SNMP, SIP, SSH, SMTP, FTP, Source Engine/Quake-style services, Minecraft, and custom UDP payloads. This gives the botnet coverage for both generic volumetric attacks and targeted disruption of specific services, including game-server infrastructure.

- Download IPFS payload: Retrieves a C2-supplied CID from the hard-coded IPFS gateway at 64[.]89.163.8:8080, saves the response to a temporary hidden file, validates whether the result is an ELF or APK, and either executes the ELF directly or attempts to install and start the APK before deleting the temporary file. APK support likely targets poorly secured Android TV boxes or similar Android-based devices.
An additional capability is the update mechanism, which does not use the same command message format. When the bot receives a message encrypted with the same key used for commands, a payload beginning with 0xDEAFBEEF triggers the update routine. The bot writes the remaining payload bytes to /tmp/.up and then calls execve on the downloaded payload.

After analyzing the AEAD encryption routines, identifying differences from standard ChaCha20 and Poly1305 behavior and extracting the C2 key, we were able to redirect the bot to a locally hosted fake C2 server so we could interact with the malware in a controlled environment.

Self-defense
Most Mirai variants implement few, if any, of these self-defense capabilities, which is why this part of tengu immediately caught our attention.
The malware forks a detached guardian that polls the main process every 60 seconds and relaunches the installed binary whenever the monitored instance terminates, providing process-level self-healing persistence. Additionally, it employs several methods to maintain its foothold on the infected system.
Watchdog

The watchdog routine first disables SysRq, disables any active hardware watchdog, and closes the device cleanly. It then forks a background worker that masquerades as [kworker/0:0], reopens the watchdog device if available on the system, and arms it with an approximately 30-second timeout. The worker sends keepalive signals only while the main malware process remains alive; if the malware is killed, the worker is reparented to init, stops servicing the watchdog, and allows the system to reboot. This turns the watchdog into an anti-remediation mechanism, using forced reboots to give the malware’s persistence mechanisms an opportunity to relaunch it.
Binary bricking

The malware also contains a list of reboot- and shutdown-related binary paths. By overwriting each file header with ELFOOD, it corrupts these ELF binaries and can interfere with normal reboot or shutdown attempts. This may complicate recovery on systems where defenders rely on those utilities to restart or safely power down the infected device.
Competitor killing

Because many independent actors compete for access to the same poorly secured IoT devices, Tengu attempts to remove rival malware to gain and maintain control. This function implements a continuous competitor-killing loop. It records the malware’s executable path and start time, then repeatedly scans /proc for running processes. Processes are ignored if they belong to the same malware instance set or match an internal allowlist that includes common Linux processes. All other processes are checked by executable path, process name, and command line against known rival-malware patterns. Matching processes are terminated with SIGKILL, including related processes discovered through a process-tree walk.
To react faster than periodic scanning alone, the malware also monitors process creation through the Linux process connector and an inotify watch on /proc. The loop runs approximately every 500 milliseconds and closes its monitoring descriptors when stopped.

Anti-analysis and Evasion
String encryption

Like Mirai, the malware stores some of its strings in encrypted form and decrypts them at runtime. Here, the strings are protected with a custom XOR-based stream cipher that generates its keystream from separate 64-bit and 32-bit linear congruential generators, combined with a per-entry incrementing value. The decrypted strings support several behaviors described throughout this analysis, including host and network discovery, watchdog handling, anti-analysis checks, competitor killing, download tooling and persistence-related paths and masquerade names.
Fileless execution

During conventional disk execution, the sample resolves /proc/self/exe to determine whether it is running from an anonymous memory mapping or from disk. Based on the result, it attempts to use memfd_create to create an anonymous RAM-backed file named systemd-journal. If memfd_create is unavailable, it creates /dev/shm/.journal and unlinks the file while keeping the file descriptor open. It then copies its executable image from /proc/self/exe to the newly created file and re-executes it with execve, setting argv[0] to /usr/lib/systemd/systemd-journald. This changes the displayed command line, so tools that rely primarily on argv[0], including some ps output and basic process-monitoring scripts, may present the malware as the legitimate systemd journal daemon.
Daemon hardening
The process installs SIG_IGN handlers for common termination, hangup, pipe, and terminal-control signals, making it resistant to ordinary shell-based interruption or suspension. The malware then calls prctl(PR_SET_DUMPABLE, 0) to disable core dumps and restrict some forms of process inspection and writes -1000 to /proc/self/oom_score_adj so the kernel strongly avoids selecting it for termination by the OOM killer.
Debugger checks

The malware uses the TracerPid value in /proc/self/status to determine whether another process is tracing it. If the value is non-zero, indicating that a debugger or tracer is attached, the process terminates. It also inspects /proc/self/environ for LD_PRELOAD and LD_LIBRARY_PATH, which may indicate hooking or an analysis environment. Two back-to-back rdtsc instructions measure execution delay; if the delta exceeds 500,000 cycles, the process terminates because the delay may indicate single-stepping or emulation. The malware also parses /proc/self/maps to identify its first r-xp mapping, computes a SHA-256 baseline hash over part of that code region, and periodically recomputes the hash to detect modification. A final periodic check looks for RW mappings in /proc/self/maps.
Mitigation and Recommendations
- Reduce internet exposure: Prioritize IoT and embedded Linux systems that expose Telnet or other administrative services, especially when they are internet-facing.
- Harden credentials and access: Remove default credentials, enforce unique passwords, and disable unnecessary remote access wherever possible.
- Patch and segment: Keep device firmware updated and separate IoT networks from critical enterprise assets to limit lateral movement and operational impact.
- Monitor suspicious behavior: Watch for unexpected outbound connections, proxy-like behavior, unusual process names, and services masquerading as legitimate system components.
- Validate persistence during response: When compromise is suspected, review systemd services, init scripts, shell startup files, and cron-related paths before returning the device to service.
To help organizations promptly identify whether the vulnerable device is present in their environment—and to detect and alert on exploitation attempts before they lead to operational disruption, compromise, or further attack progression – asset owners can rely on the advanced capabilities of Nozomi Networks OT/IoT Security Platform. The platform provides deep visibility into network traffic and device behavior enabling effective vulnerability and threat detection across OT and IoT networks.


This proactive monitoring empowers security teams to respond to vulnerabilities and attacks swiftly and effectively, minimizing the impact of attacks targeting critical networks. To learn more about Nozomi Networks OT/IoT Security Platform and see it in action, request a demo today.
Conclusion
Malware families like tengu illustrate how Mirai-derived malware continues to evolve by combining familiar IoT botnet behavior with stronger C2 protection, broader attack functionality, anti-analysis logic, and multiple persistence and self-defense mechanisms. Although some capabilities appear incomplete or were not observed in use, the sample shows that exposed embedded Linux devices remain valuable to attackers as DDoS nodes, proxies, and resilient footholds. Organizations operating IoT or edge devices should treat these systems as part of their attack surface and monitor them with the same discipline applied to traditional servers and endpoints.
MITRE ATT&CK Mapping
- Execution
- T1059.004 – Unix Shell: Uses popen for shell command execution and persistence scripts.
- T1106 – Native API: Uses memfd_create, raw sockets, and ioctl.
- Persistence
- T1543.002 – systemd Service: Creates /etc/systemd/system/<name>.service.
- T1037.004 – RC Scripts: Modifies init.d, procd, rc.local, and rc*.d.
- T1053.003 – Cron: Contains cron-related persistence logic.
- T1546.004 – Shell Configuration Modification: Infects .bashrc, .profile, or /etc/profile.
- Privilege Escalation / Defense Evasion
- T1222.002 – Linux File Permissions Modification: Applies chattr +i to make the installed binary immutable.
- Defense Evasion
- T1036.004 / T1036.005 – Masquerading: Uses names such as [kworker], systemd-journald, and daemon-like install names such as kworker-helper.
- T1497 – Virtualization / Sandbox Evasion: Checks LD_PRELOAD, LD_LIBRARY_PATH, and timing with rdtsc.
- T1622 – Debugger Evasion: Checks TracerPid.
- T1027 – Obfuscated Files or Information: Obfuscates C2 configuration and path tables with XOR and runtime-derived keys.
- T1562.001 – Impair Defenses: Disrupts normal SysRq/watchdog handling.
- Discovery
- T1082 / T1016 – System and Network Configuration Discovery: Collects and exfiltrates host and network information.
- T1057 – Process Discovery: Enumerates /proc and uses the netlink process connector.
- Command and Control
- T1573 – Encrypted Channel: Uses a custom AEAD-based C2 protocol.
- T1568.002 – Dynamic Resolution: Domain Generation Algorithms: Contains DGA-style generation logic, although this capability was not observed being used in practice.
- T1090 – Proxy: Implements SOCKS5 proxy functionality.
- Impact
- T1498 / T1498.001 – Network Denial of Service: Supports a broad set of volumetric and protocol-specific DDoS methods.
IOC
- 64[.]89.163.8 (C2)
- caef4358921486cea54333bdcde3b61c845deb9c(dropper)
- 097522a52986982b9eefc29f95efdd9d3b6032e7 (i386)
- b6d406992411dad0ef80f2b7b61427448bd05540(amd64)
- 144521ad3baf1fc28ceb4ad26d6fe490ab1b31f4 (mips)
- 0243692ce6ca522bc1359a3d89d70a229cf76587 (arm)
- 01c3326ce5beb78a6c106960a3a0868682b97bfa (arm)
- 197652174622cda52435249bc96a2d82b3613194 (arm)
- da040700e8c0852eaa848fb01138e5b820c6c765 (arm)
- b249800066433c0a8bf23edae719133465247abc (ppc)
- 0750489645d263efde56189be97c045cfc8ca890 (m68k)
YARA:
rule IOT_DDoS_tengu_sample
{
meta:
description = "Mirai-derived Linux DDoS botnet: DGA+AEAD C2, proxy, Android/IPFS dropper, watchdog/reboot bricking"
sha256 = "897226af37990fa60f25fea00b0509faa0e78d8bee10875c23b9b6ab0b8faed9"
author = "Nozomi Networks Labs"
date = "2026-07-07"
strings:
$masq1 = "[kworker/%d:%d]" ascii
$masq2 = "/usr/lib/systemd/systemd-journald" ascii
$masq3 = "/dev/shm/.journal" ascii
$brick = "ELFOOD" ascii
$svc1 = "chud-daemon" ascii
$svc2 = "chud-watchdog" ascii
$svc3 = "chud-scheduler" ascii
$tengu = "/etc/init.d/tengu" ascii
$upd = "/tmp/.up" ascii
$prox = "/tmp/.proxy.pid" ascii
$ipfs = "GET /ipfs/%s HTTP/1.0" ascii
$apk1 = "aapt dump badging '%s' 2>/dev/null" ascii
$apk2 = "am start -n '%s/.MainActivity' 2>/dev/null" ascii
$cron = "* * * * * root [ -x /proc/self/exe ] && /proc/self/exe" ascii
$wd = "/dev/watchdog0" ascii
$tsrc = "TSource Engine Query" ascii
condition:
uint32(0) == 0x464c457f and 4 of them
}





.webp)
