๐Ÿคฒ๐Ÿผ NEW | abuse.ch Community Hub! Earn recognition ๐Ÿ… for the malware intelligence you share, climb the leaderboards ๐Ÿ“ˆ, and connect with like-minded contributors who share your hunting focus ๐Ÿค. Ready to unlock your profile? Go to the Community Hub โ†’

MalwareBazaar Database

You are currently viewing the MalwareBazaar entry for SHA256 7c0b59171dfdaab72f18ef5325a508f2813f0477958167e53fb78cd716386937. While MalwareBazaar tries to identify whether the sample provided is malicious or not, there is no guarantee that a sample in MalwareBazaar is malicious.

Database Entry



Threat unknown


Vendor detections: 3


Intelligence 3 IOCs YARA File information Comments

SHA256 hash: 7c0b59171dfdaab72f18ef5325a508f2813f0477958167e53fb78cd716386937
SHA3-384 hash: f4509da08df16381377ab057c2ab05bbdc166ba0e8453b18038013a4e79a4e8767a8be2fcb5242efda2db70c9a0f8d2c
SHA1 hash: abf90b65dd8801e5d1f90accf713dabc3746638a
MD5 hash: f38fd9a636106f82e751a89d48cfbcf0
humanhash: shade-washington-hawaii-oklahoma
File name:server.jar
Download: download sample
File size:3'643'157 bytes
First seen:2026-08-23 05:51:20 UTC
Last seen:Never
File type:Java file jar
MIME type:application/zip
ssdeep 49152:+HR2JKn3GqtqR1fVypfX/9epQI+4TfOkLUVs66GXwX04wMy8GGzPKzMRAGmZ7FWp:FJK3GqsXfkx9eprrZThoPqPKIRR
TLSH T124F5021AEAD82876E1BB927512970123BE3E4BCDF54E806428F435D1E8F7D855FA438C
TrID 77.1% (.JAR) Java Archive (13500/1/2)
22.8% (.ZIP) ZIP compressed archive (4000/1)
Magika jar
Reporter maximealamahost
Tags:binary dropper elf jar proxy


Avatar
maximealamahost
# One week, two proxy-node abuses, one operator

**ยง1-ยง3** โ€” the sample attached to this report: a trojanised **NanoLimbo**
`server.jar`, one class out of 95 replaced, standing up a **sing-box** node
behind a Cloudflare Tunnel (2026-08-23).
**ยง4** โ€” the same operator's first attempt six days earlier: an obfuscated
Node.js dropper running **Xray-core** behind the *same* tunnel hostname
(2026-08-17). No sample retained, analysis done on the live files.

**Reported by:** Alama Hosting (small French game/bot hosting provider)
**Date of analysis:** 2026-08-23 ยท **Method:** static only โ€” the file was *never* executed
**Short version:** an unmodified build of the open-source Minecraft limbo server
**NanoLimbo** in which **exactly one class out of 95** has been replaced. The
replaced class downloads a native ELF binary, runs it, and exposes a
**sing-box** multi-protocol proxy through a **Cloudflare Tunnel**, then wipes the
panel console so the operator's node URIs are not left on screen. The real
Minecraft server starts afterwards, so the server looks perfectly healthy.

**Second incident by the same operator in one week**, against the same platform.
The first one (2026-08-17, obfuscated Node.js + Xray-core) is written up in full
in ยง4 โ€” same tunnel hostname, same TLS front, character for character.

---

## 1. Sample

| | |
|---|---|
| Filename | `server.jar` (uploaded by the customer to a free Minecraft plan) |
| Size | 3 643 568 bytes ยท 2 781 zip entries |
| SHA-256 | `7c0b59171dfdaab72f18ef5325a508f2813f0477958167e53fb78cd716386937` |
| MD5 | `f38fd9a636106f82e751a89d48cfbcf0` |
| Zip entry timestamps | **2026-08-19 23:01** โ€” the same day the account was created |
| Main-Class | `ua.nanit.limbo.NanoLimbo` |
| Upstream project | **NanoLimbo** by Nan1t, `LIMBO_VERSION = 1.21.1` |

## 2. The single modified class

Upstream `NanoLimbo.java` is **31 lines**; its `main()` does nothing but
`new LimboServer().start()` inside a try/catch.

In this build `NanoLimbo.class` is **9 284 bytes** and carries six added
methods: `runSbxBinary()`, `getBinaryPath()`, `loadEnvVars(Map)`,
`stopServices()`, `clearConsole()`, plus a shutdown hook.

**It is the only modified class in the archive.** The other 94 project classes
and every bundled library (netty 4.1.101, logback 1.5.6, gson 2.10.1,
snakeyaml 1.28โ€ฆ) are clean: no other class references `ProcessBuilder`,
`URL.openStream` or `setExecutable`, and no binary is embedded beyond netty's
legitimate epoll natives. The bundled `settings.yml` is byte-for-byte the
upstream one (`bind: localhost:65535`, `dimension: THE_END`, `gameMode: 3`,
`infoForwarding: NONE`).

### Execution order in `main()`

1. **Java version gate** โ€” if `java.class.version < 54.0` (Java 10) it prints,
in red, `ERROR: Your Java version is too lower, please switch the version in
startup menu!` and exits. "startup menu" is **game-panel vocabulary**: this
was built for a Pterodactyl-like host, not for a generic box.
2. `runSbxBinary()` โ€” the payload (ยง3).
3. `Runtime.addShutdownHook(...)` โ†’ kills the proxy process when the server stops.
4. `Thread.sleep(15s)`, then prints `Server is running!`,
`Thank you for using this script,Enjoy!`,
`Logs will be deleted in 20 seconds, you can copy the above nodes`.
5. `Thread.sleep(15s)` then **`clearConsole()`** โ€” ANSI erase sequences,
`tput reset`, `clear`. It wipes exactly the place where the payload had just
printed the node subscription URIs.
6. **Only then** `new LimboServer().start()` โ€” the genuine Minecraft server
comes up, giving the customer a perfectly credible "my server works".

## 3. Payload

### `getBinaryPath()` โ€” the downloader

| `os.arch` | URL |
|---|---|
| `amd64` / `x86_64` | `https://amd64.31888.xyz/sbsh` |
| `aarch64` / `arm64` | `https://arm64.31888.xyz/sbsh` |
| `s390x` | `https://s390x.31888.xyz/sbsh` |

Written to `${java.io.tmpdir}/sbx` (reused if already present), then
`File.setExecutable(true)`. Note the **`s390x`** branch: IBM mainframe, an
architecture nobody hosts Minecraft on, but which is standard in free-hosting
proxy-node kits.

### `runSbxBinary()` โ€” execution

`ProcessBuilder(sbx)` with `redirectErrorStream(true)` and
`redirectOutput(INHERIT)` โ€” the payload's output goes to the panel console,
which is why step 5 exists.

### `loadEnvVars()` โ€” configuration

Precedence: **hard-coded values โ†’ environment variables โ†’ a `.env` file in the
working directory** (the `.env` wins). The parser handles `export `, `#` and
`//` comments, and quotes. **The operator can therefore reconfigure the node by
dropping a `.env` next to the jar, without re-uploading anything.**

| Variable | Hard-coded value | Meaning |
|---|---|---|
| `UUID` | `10cc9e96-cee6-4751-805c-88be93402c9d` | sing-box inbound identifier |
| `FILE_PATH` | `./world` | **payload files hide in the Minecraft world folder** |
| `ARGO_PORT` | `8001` | local port exposed by the tunnel |
| `ARGO_DOMAIN` | **`alamahost.bbk.qzz.io`** | tunnel hostname โ€” **our brand name, hard-coded** |
| `ARGO_AUTH` | JWT (below) | **Cloudflare Tunnel credentials** |
| `CFIP` | `visa.com.tw` | clean domain behind Cloudflare used as TLS/SNI front |
| `CFPORT` | `443` | |
| `DISABLE_ARGO` | `false` | the tunnel is active |
| `NEZHA_SERVER` / `NEZHA_PORT` / `NEZHA_KEY` | empty | Nezha monitoring probe (inert here) |
| `S5_PORT`, `HY2_PORT`, `TUIC_PORT`, `ANYTLS_PORT`, `REALITY_PORT`, `ANYREALITY_PORT` | empty | SOCKS5, Hysteria2, TUIC, AnyTLS, Reality |
| `UPLOAD_URL`, `CHAT_ID`, `BOT_TOKEN` | empty | config exfiltration channels (Telegram / aggregator), inert |
| `PORT`, `NAME` | empty | `PORT` is taken from the environment โ‡’ **the container's allocated port also serves the subscription** |

None of `HY2`, `TUIC`, `REALITY`, `ANYTLS`, `S5`, `ARGO`, `NEZHA`, `CFIP`,
`CFPORT` exists anywhere in the Minecraft ecosystem. This is the variable set of
the **`eooce/Sing-box`** / **`yonggekkk/argosbx`** node scripts; `sbsh` is a
self-hosted repackaging of them on `31888.xyz`, which removes the dependency on
GitHub โ€” blocking `raw.githubusercontent.com` would achieve nothing.

### Decoded tunnel token

```json
{
"a": "4e9d6fa7b790d685390f7a382264c2e6", // operator's Cloudflare account tag
"t": "94ed92b4-3677-49f6-a4ee-c3b376c6e1e8", // tunnel ID
"s": "โ€ฆ" // secret -> d728b664-2575-439b-b325-30b7fe453988
}
```

### Passive DNS (2026-08-23)

- `amd64.31888.xyz` / `arm64.31888.xyz` โ†’ `188.114.96.2`, `188.114.97.2` (Cloudflare, NS `john/becky.ns.cloudflare.com`)
- `alamahost.bbk.qzz.io` โ†’ `172.67.172.7`, `104.21.79.243` (Cloudflare โ€” tunnel alive)
- `visa.com.tw` โ†’ `162.159.152.2`, `162.159.153.2` (Cloudflare)
- `qzz.io` โ†’ NS `ns1/ns2/ns3.qzz.io` = **DigitalPlat FreeDomain**, free domain provider

## 4. The first incident, six days earlier (2026-08-17)

Same operator, no sample kept in this folder โ€” the analysis below was done on
the live files before the container was destroyed. Recorded here because the
pair is more interesting than either half.

**Entry point.** A free *Discord NodeJS bot* plan on a Pterodactyl-style egg.
Invented identity, disposable mailbox (`0mail.art`), source IP `3.14.152.148`
(**AWS us-east-2**). Account created, service provisioned, script deployed and
proxy node published **within the same hour**. No payment, so nothing
attributable.

**What was uploaded.** An obfuscated `.js` (obfuscator.io) plus a decoy
`index.html`: a fake low-code platform landing page, served on `/`, so that
anyone glancing at the server sees a website. If no `index.html` is found the
script serves `Hello world!` instead.

**What it actually did.** It downloaded **Xray-core** and **cloudflared** under
random 6-letter filenames, brought up VLESS / VMess / Trojan inbounds over
WebSocket on `127.0.0.1:3001-3004`, and exposed them through an **outbound
Cloudflare Tunnel** whose token was hard-coded in the file. Paths
`/vless-argo`, `/vmess-argo`, `/trojan-argo`.

**Anti-forensics.** At T+90 s it `rm -rf`s its own binaries and keeps running
off the deleted inodes โ€” the tell is a process whose `/proc/<pid>/exe` resolves
to **`(deleted)`**. Its cleanup list covers `list.txt`, `config.json`,
`boot.log`, the certificate and the binaries, but **not `sub.txt`**, a base64
blob of the node subscription. That oversight is what exposed the whole thing,
and the presence of a populated `sub.txt` proved the script had **completed**,
not merely been uploaded.

**Upstream.** A stripped, obfuscated fork of **`eooce/nodejs-argo`** (author
*eooce* / ่€็Ž‹, the Chinese free-hosting proxy-node ecosystem โ€” serv00, CT8,
PaaS). The fork removes the project's Nezha probe, changes the default UUID
(`9afd1229-โ€ฆ` โ†’ `961a54b1-โ€ฆ`) and **hard-wires the Cloudflare Tunnel**. The
script also registers with `oooo.serv00.net` via `POST /add-url` โ€” the same
author's keep-alive panel, which pings free instances so they are not recycled
for inactivity.

**Exfiltration channels are inert by default** (`UPLOAD_URL`, `PROJECT_URL` +
`AUTO_ACCESS`, `BOT_TOKEN` + `CHAT_ID` all empty/false). They do not need to
work: the operator sees the connector appear in **their own Cloudflare
dashboard**, with the origin IP and the traffic volume. The tunnel is the
channel.

**Why it is a pivot problem and not a stealer problem.** The generated Xray
config has **no `routing` block** and a single `freedom` outbound โ€” zero
destination restriction. Whoever holds the UUID reaches, from inside the
hosting network, `127.0.0.1`, sibling containers, RFC1918 ranges and
`169.254.169.254`. DNS resolution goes out over DoH to `8.8.8.8`, i.e. outside
the host's DNS logs.

**Stable detection markers** (the domain and the UUID rotate, these do not):
a process whose `exe` is `(deleted)`; a leftover base64 `sub.txt`; the cleartext
strings that survive obfuscator.io's unencrypted string table โ€”
`tunnel --edge-ip-version auto`, `--no-autoupdate --protocol http2`,
`XTLS/Xray-core`, `cloudflared-linux-`, `/vless-argo`, `/vmess-argo`,
`/trojan-argo`; and an account whose entire content is one static landing page.

**One open question.** The node label produced by `getMetaInfo()` (which queries
`api.ip.sb/geoip` from the host) read **`FR-Bouygues_Telecom`**. Either the
node's egress really is that consumer line, or the operator generated the
subscription on their own machine before uploading. Not resolved.

## 4 bis. Same operator, both times

| | 2026-08-17 (free *Discord NodeJS bot* plan) | 2026-08-19โ†’23 (free *Minecraft* plan) |
|---|---|---|
| Vector | obfuscated `.js` (obfuscator.io) + decoy `index.html` | **Java `.jar`, grafted `main` class** |
| Proxy core | Xray-core + cloudflared | **sing-box** (`eooce` / ArgoSB family) |
| Tunnel hostname | **`alamahost.bbk.qzz.io`** | **`alamahost.bbk.qzz.io`** โ† *identical* |
| `CFIP` front | `visa.com.tw` | `visa.com.tw` โ† *identical* |
| UUID | `961a54b1-โ€ฆ` | `10cc9e96-โ€ฆ` (rotated) |
| Cover story | fake "CodeFlow" low-code platform front page | **the real limbo server actually starts** |

The brand name is still hard-coded in the tunnel hostname, i.e. the build is
tailored to the platform rather than sprayed. More uploads on other free plans
should be expected.

## 5. Notes for defenders

- This is **not** data theft: it is pivot and IP reputation. The node has no
destination restriction โ€” whoever holds the UUID exits through the host's IP
and can reach `127.0.0.1`, sibling containers, RFC1918 ranges.
- **Ingress filtering is useless**: the tunnel is *outbound*. `cloudflared`
leaves on 7844 TCP/UDP and falls back to HTTP/2 on 443. Only an **egress
allowlist** bites.
- **Second door**: `PORT` is inherited from the environment, so the container's
published port serves the subscription in the clear โ€” killing the tunnel or
the domain does not close it.
- **The `.env` overrides everything**, so a dropped `.env` re-points the node
without touching the jar.
- Practical order of what actually works on free plans: egress allowlist >
refusing customer-uploaded `.jar` in favour of a catalogue of known-hash jars
> identity or 0 โ‚ฌ payment fingerprint at signup.

## 6. Indicators

### 2026-08-23 (the attached sample)

```
sha256 7c0b59171dfdaab72f18ef5325a508f2813f0477958167e53fb78cd716386937 server.jar
md5 f38fd9a636106f82e751a89d48cfbcf0 server.jar
url https://amd64.31888.xyz/sbsh
url https://arm64.31888.xyz/sbsh
url https://s390x.31888.xyz/sbsh
domain 31888.xyz
host alamahost.bbk.qzz.io
cf-acct 4e9d6fa7b790d685390f7a382264c2e6
cf-tun 94ed92b4-3677-49f6-a4ee-c3b376c6e1e8
uuid 10cc9e96-cee6-4751-805c-88be93402c9d
front visa.com.tw:443
path ${java.io.tmpdir}/sbx ยท ./world (FILE_PATH) ยท ./.env
string "Thank you for using this script,Enjoy!"
string "Logs will be deleted in 20 seconds, you can copy the above nodes"
string "ERROR: Your Java version is too lower, please switch the version in startup menu!"
```

### 2026-08-17 (no sample retained)

```
host alamahost.bbk.qzz.io (identical to 08-23)
front visa.com.tw:443 (identical to 08-23)
uuid 961a54b1-โ€ฆ (rotated between the two)
url oooo.serv00.net POST /add-url (eooce keep-alive panel)
path /vless-argo ยท /vmess-argo ยท /trojan-argo
listen 127.0.0.1:3001-3004 (WebSocket inbounds)
file sub.txt (base64, NOT in the script's cleanup list)
proc /proc/<pid>/exe -> (deleted) (binaries rm -rf'd at T+90s)
string "tunnel --edge-ip-version auto"
string "--no-autoupdate --protocol http2"
string "XTLS/Xray-core" ยท "cloudflared-linux-"
signup 3.14.152.148 (AWS us-east-2) ยท disposable mailbox at 0mail.art
```

## 7. What we do not have

**2026-08-23:** the Pterodactyl volume was deleted before it was searched, so
there is no evidence of whether the payload actually ran, and no `.env` to
compare against the hard-coded values. The jar alone is conclusive on intent.
Signup metadata (account, contact address, source IP โ€” a rented German VPS
range, AS47447, no rDNS across the whole /24) is available on request.

**2026-08-17:** no copy of the obfuscated `.js` or of the decoy `index.html`
was kept โ€” the container was destroyed during containment. What survives is the
analysis in ยง4, done on the live files, and the recovered `sub.txt`. If the
upstream `eooce/nodejs-argo` project is of interest, the fork differed from it
in three ways only: Nezha probe removed, default UUID changed, tunnel token
hard-coded.

Intelligence


File Origin
# of uploads :
1
# of downloads :
44
Origin country :
FR FR
Vendor Threat Intelligence
No detections
Verdict:
Suspicious
Threat level:
  5/10
Confidence:
100%
Tags:
anti-debug macros-on-close obfuscated
Gathering data
Please note that we are no longer able to provide a coverage score for Virus Total.

File information


The table below shows additional information about this malware sample such as delivery method and external references.

Comments