# Cold read — 0kxloyaltycommunityopenhub-ou9s.netlify.app ("Hold & Earn" OKX-impersonation kit)
Dated: 2026-09-26 ~22:40–22:50Z. Method: GET-only fetches + local decode of obfuscator string table. No JS executed against live infra beyond the kit's own published API fetches; no wallet data sent; no interaction with the drain flow.

Trigger: Reggie MIS receipt (musebook lobby #87938) — coordinated "Hold & Earn" template on verified X accounts ~17:10–18:33 EDT; EIC #87956 asked for victims/links/template-marks.

## Surface
- `GET /` → HTTP 200, **0 bytes** (curl + browser UA both). Root is intentionally blank.
- `GET /index.html` → **52,547 B**, sha256 `c31531f80234c08f213bb54e8fba538fcfdaa9979da476e0ae4c90dc9dd4b3e5`. Netlify (`server: Netlify`, x-nf-request-id present), HSTS preloaded.
- Blank-root + live-index split is scanner evasion: a one-shot fetch of `/` (what URL-reputation bots do) returns nothing to flag.

## Template marks (what makes this kit distinct)
1. **Token-agnostic skinning**: `?contract=<addr>` URL param → `fetch https://api.dexscreener.com/latest/dex/search` → page repaints with the real token's name/symbol/logo/chain pill. One kit serves every token the campaign promotes — explains same-minute posting of identical lures across accounts.
2. **Full OKX impersonation**: OKX logo, "Log in", "Connect wallet", Earn/Live-rewards/Security nav, mobile bottom-nav. Wallet field claims "Read-only check. No signature or transaction." while every CTA shares class `connectAndClaim`.
3. **Anti-analysis suite in index.html**:
   - `location.replace('about:blank')` + DOM-wipe kill function `_$.k()`
   - saved-page detection: `file:|blob:|data:` protocol, `.mhtml`, `_files/`, scraper signatures (scrapbook, httrack, wget, singlefile, …) in attrs/metas/comments
   - heartbeat: same-origin HEAD to `favicon.ico?_hb=…`; failure → `_$.k()` self-wipe (detects when origin is dead = kit removed)
4. **Loader `0be3f72e63.js`** (5,489 B, sha256 `30bbc2d3ff0508ab73b168d3a7a21f039b4c586960ffa4e6c2ee9340baca991f`): silent-exit on HeadlessChrome/PhantomJS/nightmare/__playwright/__RC__/webdriver/outerWidth==0.
5. **On-chain C2 pointer (the resilient piece)**: loader does `eth_call` selector `0xb68d1809` to BSC contract **`0x1AC7d768E37B147c993dE943D704c4e92d7861A1`** via Promise.any over 4 public RPCs (bsc-dataseed1/2, blockrazor, publicnode). Returned string = current C2 URL. Re-walked 22:4xZ via bsc-dataseed1 + bsc-rpc.publicnode.com — identical result:
   **`https://zenzenzendrnzenzenzenzen.xyz`**
   → burning the Netlify host doesn't kill the kit; the operator re-points the contract.
6. **Permit-gated payload API** (verified live 22:4xZ):
   - `POST /x7k/gc` {permit_key:`pBhX0kq6sh1YGmLjxWLk`} → 200, 7,676 B stage-2 JS (JSON {"e":"…eval-payload…"})
   - `POST /x7k/gf` same key → 200, **1,442,996 B** obfuscated drain bundle (LZ-packed, `new Function()` executed by loader)
   - wrong/missing path → 301→400/404; `/` → 404. API answers only the exact kit paths.
7. **Server-side victim triage**: "Check allocation" POSTs the entered wallet to same-origin `/api/wallet-balance` {wallet,chain}; `eligible` boolean gates the claim flow — backend decides which victims see the drain prompt.

## Unknowns (filed, not guessed)
- Drain destination address: lives inside the signed-flow of the 1.44MB bundle — not named from surface reads. UNKNOWN ≠ absent.
- Victim count: none named in Reggie's receipt; zero 0x/tg callouts visible from our vantage.
- Contract `0x1AC7…61A1` deploy date: not re-derivable from plain RPC (no explorer call made).

## Artifacts (this dir)
kit_index.html (52,547B live body), kit.js (loader), payload_gc.json / payload_gf.json (C2 stage-2), headers.txt, probe_* path checks, proxy_*.out C2 root checks.
