24e1d1be4215f970fd5e7e6e…

sample

Tracked by C2 Tracker · indicators & metadata only, the APK itself is never published

Analyst notes

NFC Relay (provisional). NFC Relay (provisional) is Android NFC-relay card-fraud malware (NGate / NFSkimming style). On the victim’s phone it reads contactless EMV card data over NFC and relays it live over a WebSocket to the operator, who replays it at a payment terminal or ATM.

What it does

  • Reads contactless EMV card APDUs over NFC (IsoDep, accept-any-AID) and relays them, with device status and the victim’s 4-digit PIN, to the operator in real time.
  • Drives the victim through a WebView phishing flow (card-tap prompt, PIN entry) while the relay runs.

Builds and C2 (binary-verified)

  • “Nfc Security” build (12 samples, identical dex; package app.nfcsecurity.vault, Portuguese UI). Endpoints are stored character-reversed and recovered via UtilZ0Y480.decode. Relay C2 wss://dashboard.gripe/ws-relay (source-to-sink: bs.getWsUrl supplies SERVER_URL, passed to OkHttp newWebSocket; APDUs and PIN sent via vo5bwh.sendResponse / sendPin). The phishing UI loads from https://dashboardcloud.app (ReFragment.goStep, Portuguese ?step= flow) and is tracked as a panel, not the relay.
  • “Банк России” build (656eee1e, package com.example.myemulator, Russian lure). Relays to a raw-socket C2 ws://178.236.243.8:3050.
  • The dashboard.gripe relay is Cloudflare-fronted. The sample config pins wss://dashboard.gripe/ws-relay (:443), but the same relay also answers over plaintext ws:// on Cloudflare HTTP ports 2052 / 2086 / 2095 at the same /ws-relay path, and those ports serve an operator monitoring panel branded “Caps System - Monitoramento” (observed live 2026-10-12). Block the whole host, not just :443.

Operator panel (api.dashboardcloud.app/api/status)

The “Nfc Security” dex decodes a third URL, https://api.dashboardcloud.app/api/status (bs.getPanelStatusUrl -> fm5oo1jxl.a0l -> MainActivity.painelStatusUrl). This build only assigns the field and never polls it, but the endpoint is live, unauthenticated operator infrastructure - a status/monitoring API on the same dashboardcloud.app apex as the phishing host, resolving to the same Cloudflare front (104.21.38.165 / 172.67.136.119). Recorded as a panel on that external confirmation rather than a code sink in the sample. Block the host. (The response exposes live victim data; specifics are withheld from the public record.)

Second infrastructure set on cupworldcup.site (registered, not called by these builds)

The “Nfc Security” dex also carries a complete second set of operator URLs pointing at cupworldcup.site, mirroring the live dashboard.gripe + dashboardcloud.app set role-for-role. The domain is registered and Cloudflare-fronted - ws., web. and api.cupworldcup.site all resolve to 104.21.62.55 / 172.67.220.107 as of 2026-10-12 - which makes it a strong clustering and hunting pivot even though this build never reaches it.

  • The URLs sit in bs._a()..bs._d() as base64 text, decoded by bs.r() -> bs.x(), where x() XORs the bytes with the repeating 4-byte key 2a 1f 37 0d ([42, 31, 55, 13]) - a different scheme from the live set’s character-reversal. Decoded they are:
    • wss://ws.cupworldcup.site - relay, mirrors dashboard.gripe/ws-relay
    • https://web.cupworldcup.site - phishing web host, mirrors dashboardcloud.app
    • https://api.cupworldcup.site/api/status - status endpoint, mirrors api.dashboardcloud.app/api/status
  • It is not reached in these builds because _a().._d(), r() and x() have no callers anywhere in the app. Every place that needs a server URL calls UtilZ0Y480.decode instead and resolves to the dashboard.gripe / dashboardcloud.app set, so cupworldcup.site is never contacted at runtime by these samples.
  • Read as the same operator’s earlier or alternate infrastructure left in the code: a 1:1 role mirror, a parallel obfuscation scheme, the same URL layout, and a live registration. Recorded as inactive indicators so defenders can pivot on them and flag any build that switches to this set.

Not treated as C2

  • No Firebase or other backend is present in either build.

Family label provisional. Indicators: wss://dashboard.gripe/ws-relay, https://dashboardcloud.app, https://api.dashboardcloud.app/api/status.

Recovered configuration

also_on_cloudflare_http_ports
2052, 2086, 2095
alt_relay_endpoints
ws://dashboard.gripe:2052/ws-relay, ws://dashboard.gripe:2086/ws-relay, ws://dashboard.gripe:2095/ws-relay
backend_urls
https://dashboardcloud.app, https://api.dashboardcloud.app/api/status
build_id
2363b211bfb1
config_id
e69ea27c
live_confirmed
2026-10-12 (reachable, unauthenticated)
panel_name
Caps System - Monitoramento
ports_note
Cloudflare-fronted host. Sample config pins wss://dashboard.gripe/ws-relay (:443); the same relay also answers over plaintext ws:// on Cloudflare HTTP ports 2052/2086/2095 at /ws-relay, and those ports serve an operator monitoring panel ('Caps System'). Observed live 2026-10-12, not from sample config. Block the whole host, not just :443.
reclassify_when_dead
True
relay_c2
wss://dashboard.gripe/ws-relay
relay_path
/ws-relay
role_detail
Operator panel / status API (api.dashboardcloud.app/api/status) for the same dashboardcloud.app operator.
sealed_detail
internal Project note (not published) - restore when host dead
source_to_sink
Decoded and held in this build (painelStatusUrl) but the field is only assigned, never polled by the relay flow. Classified as operator infra on external confirmation, not a code sink in this sample.

Source: string-reversed URLs in dex (bs config, UtilZ0Y480.decode = reverse)

Identification

SHA-256
24e1d1be4215f970fd5e7e6e3004cc59eeb4e8c41cb9ee4a7d085c8938817dec
MD5
872d90f0427321af33f8fe9a13ae8a7b

Observed

Families
NFC Relay (provisional)
First seen
2026-10-12

C2 configuration (3)

Every indicator extracted from this sample. One row per C2 - each links to its indicator page with Whois, DNS and certificate pivots.

IndicatorTypePortSchemeFamilyFirst seen
api.dashboardcloud.app/api/status domain - https NFC Relay (provisional) 2026-10-12
dashboard.gripe/ws-relay domain - wss NFC Relay (provisional) 2026-10-12
dashboardcloud.app domain - https NFC Relay (provisional) 2026-10-12

Signing certificate

Subject CN
Android
Issuer CN
Android
Fingerprint
dfa875f9cc0780b837d5fb9d40eb600064f8106306f975c2755dc0ec06f45f38

Relationships

Sample → C2 indicators, signing certificate (with every other sample signed by it) and family. Click a node for details, double-click to open its page.

Click a node to inspect it.

About NFC Relay (provisional)

**NFC Relay (provisional)** is Android NFC-relay card-fraud malware (NGate / NFSkimming style). On the victim's phone it reads contactless EMV card data over NFC and relays it live over a WebSocket to the operator, who replays it at a payment terminal or ATM. **What it does** - Reads contactless **EMV card APDUs** over NFC (`IsoDep`, accept-any-AID) and relays them, with device status and the victim's **4-digit PIN**, to the operator in real time. - Drives the victim through a WebView phishing flow (card-tap prompt, PIN entry) while the relay runs. **Builds and C2 (binary-verified)** - **"Nfc Security" build** (12 samples, identical dex; package `app.nfcsecurity.vault`, Portuguese UI). Endpoints are stored character-reversed and recovered via `UtilZ0Y480.decode`. Relay C2 `wss://dashboard.gripe/ws-relay` (source-to-sink: `bs.getWsUrl` supplies `SERVER_URL`, passed to OkHttp `newWebSocket`; APDUs and PIN sent via `vo5bwh.sendResponse` / `sendPin`). The phishing UI loads from `https://dashboardcloud.app` (`ReFragment.goStep`, Portuguese `?step=` flow) and is tracked as a **panel, not the relay**. - **"Банк России" build** (`656eee1e`, package `com.example.myemulator`, Russian lure). Relays to a raw-socket C2 `ws://178.236.243.8:3050`. - The `dashboard.gripe` relay is Cloudflare-fronted. The sample config pins `wss://dashboard.gripe/ws-relay` (`:443`), but the same relay also answers over plaintext `ws://` on Cloudflare HTTP ports **2052 / 2086 / 2095** at the same `/ws-relay` path, and those ports serve an operator monitoring panel branded **"Caps System - Monitoramento"** (observed live 2026-10-12). Block the whole host, not just `:443`. **Operator panel (`api.dashboardcloud.app/api/status`)** The "Nfc Security" dex decodes a third URL, `https://api.dashboardcloud.app/api/status` (`bs.getPanelStatusUrl` -> `fm5oo1jxl.a0l` -> `MainActivity.painelStatusUrl`). This build only assigns the field and never polls it, but the endpoint is **live, unauthenticated operator infrastructure** - a status/monitoring API on the same `dashboardcloud.app` apex as the phishing host, resolving to the same Cloudflare front (`104.21.38.165` / `172.67.136.119`). Recorded as a **panel** on that external confirmation rather than a code sink in the sample. Block the host. (The response exposes live victim data; specifics are withheld from the public record.) **Second infrastructure set on `cupworldcup.site` (registered, not called by these builds)** The "Nfc Security" dex also carries a complete second set of operator URLs pointing at `cupworldcup.site`, mirroring the live `dashboard.gripe` + `dashboardcloud.app` set role-for-role. The domain is **registered and Cloudflare-fronted** - `ws.`, `web.` and `api.cupworldcup.site` all resolve to `104.21.62.55` / `172.67.220.107` as of 2026-10-12 - which makes it a strong clustering and hunting pivot even though this build never reaches it. - The URLs sit in `bs._a()`..`bs._d()` as base64 text, decoded by `bs.r()` -> `bs.x()`, where `x()` XORs the bytes with the repeating 4-byte key `2a 1f 37 0d` (`[42, 31, 55, 13]`) - a different scheme from the live set's character-reversal. Decoded they are: - `wss://ws.cupworldcup.site` - relay, mirrors `dashboard.gripe/ws-relay` - `https://web.cupworldcup.site` - phishing web host, mirrors `dashboardcloud.app` - `https://api.cupworldcup.site/api/status` - status endpoint, mirrors `api.dashboardcloud.app/api/status` - It is not reached in these builds because `_a()`..`_d()`, `r()` and `x()` have no callers anywhere in the app. Every place that needs a server URL calls `UtilZ0Y480.decode` instead and resolves to the `dashboard.gripe` / `dashboardcloud.app` set, so `cupworldcup.site` is never contacted at runtime by these samples. - Read as the same operator's **earlier or alternate infrastructure** left in the code: a 1:1 role mirror, a parallel obfuscation scheme, the same URL layout, and a live registration. Recorded as **inactive** indicators so defenders can pivot on them and flag any build that switches to this set. **Not treated as C2** - No Firebase or other backend is present in either build. Family label provisional.