Last active
January 17, 2026 23:49
-
-
Save sloev/a4c3142c83a0dd3852662288fe09fcde to your computer and use it in GitHub Desktop.
Mesh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <title>ZERO_MESH V4 [WIDEBAND]</title> | |
| <style> | |
| :root { --bg: #000; --fg: #0f0; --dim: #004400; --err: #f00; } | |
| * { box-sizing: border-box; } | |
| body { background: var(--bg); color: var(--fg); font-family: 'Courier New', monospace; padding: 10px; height: 100vh; display: flex; flex-direction: column; overflow: hidden; } | |
| header { border-bottom: 1px solid var(--dim); padding-bottom: 5px; margin-bottom: 10px; display: flex; justify-content: space-between; } | |
| #dashboard { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 10px; } | |
| .card { border: 1px solid var(--dim); padding: 5px; background: #050505; } | |
| .label { font-size: 10px; color: #666; display: block; margin-bottom: 2px; } | |
| .val { font-size: 14px; font-weight: bold; color: #fff; } | |
| .highlight { color: #ff0; font-size: 18px; } | |
| #console { flex: 1; border: 1px solid #222; overflow-y: scroll; font-size: 11px; padding: 5px; color: #888; margin-bottom: 10px; } | |
| .log-hit { color: #ff0; background: #220; } | |
| .log-chat { color: #fff; } | |
| #controls { display: flex; gap: 5px; flex-direction: column; } | |
| .row { display: flex; gap: 5px; } | |
| input { background: #111; border: 1px solid #333; color: #fff; padding: 10px; flex: 1; font-family: inherit; } | |
| button { background: #003300; color: #0f0; border: 1px solid #0f0; padding: 10px; cursor: pointer; font-weight: bold; } | |
| button:active { background: #0f0; color: #000; } | |
| #chat-ui { display: none; flex-direction: column; flex: 1; } | |
| #chat-msgs { flex: 1; border: 1px solid var(--dim); overflow-y: scroll; padding: 10px; margin-bottom: 5px; } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <div><strong>ZERO_MESH_V4</strong></div> | |
| <div id="status">INIT...</div> | |
| </header> | |
| <div id="dashboard"> | |
| <div class="card"> | |
| <span class="label">MY IP ADDRESS</span> | |
| <span class="val" id="disp-ip">...</span> | |
| </div> | |
| <div class="card"> | |
| <span class="label">MY LISTENING PORT</span> | |
| <span class="val highlight" id="disp-port">DETECTING</span> | |
| </div> | |
| </div> | |
| <div id="console"></div> | |
| <div id="setup-ui"> | |
| <div class="card" style="margin-bottom: 10px;"> | |
| <span class="label">TARGET CONFIGURATION (AUTO-SCANNING...)</span> | |
| <div class="row" style="margin-top:5px;"> | |
| <input type="text" id="target-ip" placeholder="Target IP (e.g. 192.168.1.X)"> | |
| <input type="number" id="target-port" placeholder="Target PORT (Optional)"> | |
| </div> | |
| <div class="row" style="margin-top:5px;"> | |
| <button onclick="MANUAL.connect()">FORCE CONNECT</button> | |
| <button onclick="SCANNER.retry()">RE-SCAN LAN</button> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="chat-ui"> | |
| <div id="chat-msgs"></div> | |
| <div class="row"> | |
| <input id="chat-in" placeholder="Type message..."> | |
| <button onclick="CHAT.send()">SEND</button> | |
| </div> | |
| </div> | |
| <script> | |
| // --- CORE CONSTANTS --- | |
| const CONFIG = { | |
| UFRAG: "zm4", | |
| PWD: "zm4_static_password", | |
| // Android range + IANA range | |
| SPRAY_START: 32768, | |
| SPRAY_END: 60999, | |
| BATCH_SIZE: 500 | |
| }; | |
| // --- LOGGING --- | |
| const LOG = (msg, type='') => { | |
| const c = document.getElementById('console'); | |
| const d = document.createElement('div'); | |
| d.className = type; | |
| d.innerText = `> ${msg}`; | |
| c.appendChild(d); | |
| c.scrollTop = c.scrollHeight; | |
| }; | |
| // --- STATE --- | |
| const STATE = { | |
| pc: null, | |
| dc: null, | |
| ip: null, | |
| port: null, | |
| subnet: null | |
| }; | |
| // ============================================ | |
| // 1. IDENTITY & LOCAL DISCOVERY (UNMASKING) | |
| // ============================================ | |
| async function init() { | |
| LOG("BOOTING KERNEL..."); | |
| // 1. Create PC to find Local IP & Port | |
| // We use a trick: Create a DataChannel. This often forces host candidates. | |
| const pc = new RTCPeerConnection({ iceServers: [] }); | |
| // LINUX FIX: Create a dummy candidate to kickstart the engine if it hangs | |
| // pc.addIceCandidate({ candidate: "", sdpMid: "0", sdpMLineIndex: 0 }).catch(e=>{}); | |
| const dc = pc.createDataChannel("discovery"); | |
| // Create Offer | |
| const offer = await pc.createOffer(); | |
| // STATIC AUTH HACK | |
| let sdp = offer.sdp; | |
| sdp = sdp.replace(/a=ice-ufrag:.*\r\n/, `a=ice-ufrag:${CONFIG.UFRAG}\r\n`); | |
| sdp = sdp.replace(/a=ice-pwd:.*\r\n/, `a=ice-pwd:${CONFIG.PWD}\r\n`); | |
| await pc.setLocalDescription({ type: "offer", sdp: sdp }); | |
| // Listen for Candidates | |
| pc.onicecandidate = e => { | |
| if (!e.candidate) return; | |
| // PARSE IP AND PORT | |
| // Format: candidate:1 1 UDP 123456 192.168.1.5 54321 typ host | |
| const parts = e.candidate.candidate.split(' '); | |
| if(parts.length >= 6 && parts[4].includes('.')) { | |
| // Found IPv4 | |
| STATE.ip = parts[4]; | |
| STATE.port = parts[5]; | |
| STATE.subnet = STATE.ip.split('.').slice(0,3).join('.'); | |
| document.getElementById('disp-ip').innerText = STATE.ip; | |
| document.getElementById('disp-port').innerText = STATE.port; // SHOW THE USER | |
| LOG(`LISTENER ACTIVE: ${STATE.ip}:${STATE.port}`, 'log-hit'); | |
| // Once we have IP, start scanning for others | |
| if(!SCANNER.running) SCANNER.start(); | |
| } | |
| }; | |
| // SAVE PC GLOBALLY (This is our Listener) | |
| STATE.pc = pc; | |
| // SETUP INCOMING CONNECTION HANDLER | |
| pc.ondatachannel = e => { | |
| LOG("!!! INCOMING CONNECTION !!!", "log-hit"); | |
| setupChat(e.channel); | |
| }; | |
| // SETUP CONNECTION STATE | |
| pc.onconnectionstatechange = () => { | |
| document.getElementById('status').innerText = pc.connectionState.toUpperCase(); | |
| if(pc.connectionState === 'connected') { | |
| document.getElementById('setup-ui').style.display = 'none'; | |
| document.getElementById('chat-ui').style.display = 'flex'; | |
| } | |
| }; | |
| } | |
| // ============================================ | |
| // 2. THE WIDEBAND SCANNER (LAN) | |
| // ============================================ | |
| const SCANNER = { | |
| running: false, | |
| foundIPs: new Set(), | |
| start: async () => { | |
| if(SCANNER.running) return; | |
| SCANNER.running = true; | |
| LOG(`SCANNING SUBNET ${STATE.subnet}.x ...`); | |
| // Scan 1-254 | |
| for(let i=1; i<255; i++) { | |
| if(STATE.pc.connectionState === 'connected') break; | |
| let target = `${STATE.subnet}.${i}`; | |
| if(target === STATE.ip) continue; | |
| // Async check (don't await, just fire) | |
| checkHost(target).then(alive => { | |
| if(alive && !SCANNER.foundIPs.has(target)) { | |
| SCANNER.foundIPs.add(target); | |
| LOG(`FOUND PEER: ${target}`, 'log-hit'); | |
| document.getElementById('target-ip').value = target; // Auto-fill UI | |
| SPRAY.fire(target); // AUTO SPRAY | |
| } | |
| }); | |
| if(i % 10 === 0) await new Promise(r => setTimeout(r, 50)); // Throttle | |
| } | |
| }, | |
| retry: () => { SCANNER.running = false; SCANNER.start(); } | |
| }; | |
| function checkHost(ip) { | |
| return new Promise(resolve => { | |
| const start = performance.now(); | |
| const controller = new AbortController(); | |
| setTimeout(() => controller.abort(), 2000); | |
| fetch(`http://${ip}:43210`, { mode: 'no-cors', signal: controller.signal }) | |
| .then(() => resolve(false)) | |
| .catch(err => { | |
| const dur = performance.now() - start; | |
| // Linux/Android TCP RST is usually fast (<100ms) | |
| // Timeout is 2000ms. | |
| if(dur < 500 && err.name !== 'AbortError') resolve(true); | |
| else resolve(false); | |
| }); | |
| }); | |
| } | |
| // ============================================ | |
| // 3. THE TURBO SPRAY (PORT BRUTEFORCE) | |
| // ============================================ | |
| const SPRAY = { | |
| fire: async (targetIP) => { | |
| LOG(`SPRAYING TARGET ${targetIP} (This may take 10s)...`); | |
| // We need to enable "Remote" candidate addition | |
| // Hack: Set a dummy remote description if none exists | |
| if(!STATE.pc.currentRemoteDescription) { | |
| try { | |
| await STATE.pc.setRemoteDescription({ | |
| type: "answer", | |
| sdp: STATE.pc.localDescription.sdp // Symmetric Mirror | |
| }); | |
| } catch(e) {} | |
| } | |
| // 1. Spray Common Ports first (Linux Ephemeral Start) | |
| await SPRAY.burst(targetIP, 32768, 33000); | |
| // 2. Spray IANA Dynamic Start | |
| await SPRAY.burst(targetIP, 49152, 49452); | |
| // 3. If User typed a port, hit that specifically | |
| const manualPort = document.getElementById('target-port').value; | |
| if(manualPort) { | |
| SPRAY.add(targetIP, manualPort); | |
| } | |
| LOG("SPRAY WAVE 1 COMPLETE. IF FAILED, TYPE PORT MANUALLY."); | |
| }, | |
| burst: async (ip, start, end) => { | |
| for(let p = start; p < end; p++) { | |
| SPRAY.add(ip, p); | |
| if(p % 100 === 0) await new Promise(r => setTimeout(r, 10)); // Yield to UI | |
| } | |
| }, | |
| add: (ip, port) => { | |
| STATE.pc.addIceCandidate({ | |
| candidate: `candidate:1 1 UDP 2122260223 ${ip} ${port} typ host`, | |
| sdpMid: "0", | |
| sdpMLineIndex: 0 | |
| }).catch(e=>{}); | |
| } | |
| }; | |
| // ============================================ | |
| // 4. MANUAL OVERRIDE | |
| // ============================================ | |
| const MANUAL = { | |
| connect: () => { | |
| const ip = document.getElementById('target-ip').value; | |
| const port = document.getElementById('target-port').value; | |
| if(!ip || !port) return alert("ENTER IP AND PORT"); | |
| LOG(`MANUAL OVERRIDE: ${ip}:${port}`, 'log-hit'); | |
| SPRAY.add(ip, port); // Just add the exact candidate | |
| } | |
| }; | |
| // ============================================ | |
| // 5. CHAT | |
| // ============================================ | |
| function setupChat(dc) { | |
| STATE.dc = dc; | |
| dc.onopen = () => { LOG("CHAT CHANNEL OPEN"); }; | |
| dc.onmessage = e => { | |
| const d = document.createElement('div'); | |
| d.className = 'log-chat'; | |
| d.style.color = '#0f0'; | |
| d.innerText = `PEER: ${e.data}`; | |
| document.getElementById('chat-msgs').appendChild(d); | |
| }; | |
| } | |
| const CHAT = { | |
| send: () => { | |
| const inp = document.getElementById('chat-in'); | |
| if(!inp.value) return; | |
| STATE.dc.send(inp.value); | |
| const d = document.createElement('div'); | |
| d.className = 'log-chat'; | |
| d.style.color = '#fff'; | |
| d.innerText = `ME: ${inp.value}`; | |
| document.getElementById('chat-msgs').appendChild(d); | |
| inp.value = ''; | |
| } | |
| }; | |
| // START | |
| init(); | |
| </script> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <title>ZERO_MESH V5 [JUNGLE]</title> | |
| <style> | |
| :root { --bg: #0d0d0d; --fg: #00ff41; --dim: #003300; --warn: #ffcc00; --err: #ff3333; } | |
| * { box-sizing: border-box; } | |
| body { background: var(--bg); color: var(--fg); font-family: 'Courier New', monospace; margin: 0; padding: 10px; height: 100vh; display: flex; flex-direction: column; overflow: hidden; } | |
| /* HEADER */ | |
| header { border-bottom: 1px solid var(--dim); padding-bottom: 5px; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; } | |
| .status-badge { background: var(--dim); padding: 2px 5px; font-size: 10px; border-radius: 3px; } | |
| /* PANELS */ | |
| #main-view { flex: 1; display: flex; flex-direction: column; gap: 10px; overflow-y: auto; } | |
| .panel { border: 1px solid #222; background: #080808; padding: 10px; } | |
| .panel-head { font-size: 11px; color: #666; border-bottom: 1px solid #222; margin-bottom: 8px; padding-bottom: 2px; text-transform: uppercase; letter-spacing: 1px; } | |
| /* METRICS */ | |
| .metric-row { display: flex; justify-content: space-between; margin-bottom: 5px; font-size: 13px; } | |
| .val { font-weight: bold; color: #fff; } | |
| .val.masked { color: #555; font-style: italic; } | |
| .val.highlight { color: var(--warn); } | |
| /* LOGS */ | |
| #console { height: 120px; border: 1px solid #111; background: #000; overflow-y: scroll; font-size: 10px; padding: 5px; color: #888; margin-top: 5px; } | |
| .log-sys { color: #444; } | |
| .log-hit { color: var(--warn); background: #220; } | |
| .log-success { color: #000; background: var(--fg); } | |
| /* CONTROLS */ | |
| .control-group { display: flex; flex-direction: column; gap: 5px; } | |
| .input-row { display: flex; gap: 5px; } | |
| input { background: #111; border: 1px solid #333; color: #fff; padding: 8px; flex: 1; font-family: inherit; font-size: 12px; } | |
| input:focus { border-color: var(--fg); outline: none; } | |
| button { background: var(--dim); color: var(--fg); border: 1px solid var(--fg); padding: 8px; cursor: pointer; font-weight: bold; font-family: inherit; font-size: 11px; text-transform: uppercase; } | |
| button:active { background: var(--fg); color: #000; } | |
| /* CHAT */ | |
| #chat-ui { display: none; flex: 1; flex-direction: column; } | |
| #messages { flex: 1; border: 1px solid var(--dim); overflow-y: scroll; padding: 10px; margin-bottom: 5px; font-size: 12px; } | |
| .msg { margin-bottom: 3px; word-break: break-all; } | |
| .msg.peer { color: var(--warn); } | |
| .msg.me { color: #fff; opacity: 0.7; } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <strong>ZM_V5_JUNGLE</strong> | |
| <div id="conn-state" class="status-badge">OFFLINE</div> | |
| </header> | |
| <div id="main-view"> | |
| <div class="panel"> | |
| <div class="panel-head">1. LOCAL IDENTITY (LISTENER)</div> | |
| <div class="metric-row"> | |
| <span>IP ADDRESS:</span> | |
| <span id="my-ip" class="val masked">DETECTING...</span> | |
| </div> | |
| <div class="metric-row"> | |
| <span>PORT:</span> | |
| <span id="my-port" class="val masked">DETECTING...</span> | |
| </div> | |
| <div class="metric-row"> | |
| <span>KEY (UFRAG):</span> | |
| <span id="my-ufrag" class="val highlight">...</span> | |
| </div> | |
| <div style="font-size:10px; color:#555; margin-top:5px;"> | |
| *If IP is HIDDEN, Android is masking it. This is normal. | |
| </div> | |
| </div> | |
| <div class="panel"> | |
| <div class="panel-head">2. TARGET DISCOVERY (JOINER)</div> | |
| <div class="control-group"> | |
| <div class="input-row"> | |
| <input id="scan-subnet" type="text" value="192.168.1" placeholder="Subnet (e.g. 192.168.0)"> | |
| <button onclick="SCANNER.start()">AUTO-SCAN LAN</button> | |
| </div> | |
| <div class="panel-head" style="margin-top:10px; border:none; color:var(--warn);">MANUAL OVERRIDE (IF SCAN FAILS)</div> | |
| <div class="input-row"> | |
| <input id="manual-ip" placeholder="Target IP"> | |
| <input id="manual-port" placeholder="Port" type="number"> | |
| </div> | |
| <div class="input-row"> | |
| <input id="manual-ufrag" placeholder="Target Key (UFRAG)"> | |
| <input id="manual-pwd" placeholder="Target PWD" value="zm5_pass"> | |
| </div> | |
| <button onclick="MANUAL.connect()">FORCE CONNECT</button> | |
| </div> | |
| </div> | |
| <div id="console"></div> | |
| </div> | |
| <div id="chat-ui"> | |
| <div id="messages"> | |
| <div style="color:#444">-- SECURE CHANNEL ESTABLISHED --</div> | |
| </div> | |
| <div class="input-row"> | |
| <input id="chat-in" placeholder="Message..."> | |
| <button onclick="CHAT.send()">TX</button> | |
| </div> | |
| </div> | |
| <script> | |
| // ============================================ | |
| // KERNEL CONFIG | |
| // ============================================ | |
| const CONFIG = { | |
| // We attempt to force these credentials. | |
| // If Android rejects them, we fallback to whatever Android generates. | |
| UFRAG: "zm5", | |
| PWD: "zm5_pass", | |
| // Scan these ranges if we find an IP | |
| SPRAY_RANGES: [ | |
| [32768, 33500], // Common Android Start | |
| [49152, 49552], // Common IANA Start | |
| [50000, 50500] | |
| ] | |
| }; | |
| // ============================================ | |
| // SYSTEM LOGGING | |
| // ============================================ | |
| const LOG = (msg, type='log-sys') => { | |
| const c = document.getElementById('console'); | |
| const d = document.createElement('div'); | |
| d.className = type; | |
| d.innerText = `> ${msg}`; | |
| c.appendChild(d); | |
| c.scrollTop = c.scrollHeight; | |
| }; | |
| // ============================================ | |
| // GLOBAL STATE | |
| // ============================================ | |
| const STATE = { | |
| pc: null, | |
| dc: null, | |
| ip: null, // Local IP | |
| port: null, // Local Port | |
| ufrag: null, // Local Ufrag | |
| pwd: null, // Local Pwd | |
| connected: false | |
| }; | |
| // ============================================ | |
| // 1. BOOTSTRAP (LISTENER) | |
| // ============================================ | |
| async function init() { | |
| LOG("KERNEL INIT..."); | |
| // Create PeerConnection | |
| const pc = new RTCPeerConnection({ iceServers: [] }); | |
| // Create Data Channel to trigger ICE gathering | |
| const dc = pc.createDataChannel("zm_mesh", { negotiated: true, id: 0 }); | |
| setupDC(dc); | |
| // CREATE OFFER | |
| let offer = await pc.createOffer(); | |
| let sdp = offer.sdp; | |
| // TRY STATIC AUTH HACK | |
| // We try to force the ufrag/pwd so the other side knows it in advance. | |
| // If this causes a crash on Android, we catch it. | |
| const originalSDP = sdp; | |
| sdp = sdp.replace(/a=ice-ufrag:.*\r\n/, `a=ice-ufrag:${CONFIG.UFRAG}\r\n`); | |
| sdp = sdp.replace(/a=ice-pwd:.*\r\n/, `a=ice-pwd:${CONFIG.PWD}\r\n`); | |
| try { | |
| await pc.setLocalDescription({ type: "offer", sdp: sdp }); | |
| STATE.ufrag = CONFIG.UFRAG; | |
| STATE.pwd = CONFIG.PWD; | |
| LOG("STATIC AUTH: APPLIED", "log-success"); | |
| } catch(e) { | |
| LOG("STATIC AUTH FAILED (ANDROID RESTRICTION). REVERTING...", "log-hit"); | |
| // Fallback to dynamic (random) auth | |
| await pc.setLocalDescription({ type: "offer", sdp: originalSDP }); | |
| // Extract the generated credentials to show the user | |
| const ufragMatch = originalSDP.match(/a=ice-ufrag:(.*)\r\n/); | |
| const pwdMatch = originalSDP.match(/a=ice-pwd:(.*)\r\n/); | |
| STATE.ufrag = ufragMatch ? ufragMatch[1] : "???"; | |
| STATE.pwd = pwdMatch ? pwdMatch[1] : "???"; | |
| } | |
| // UPDATE UI WITH CREDENTIALS | |
| document.getElementById('my-ufrag').innerText = STATE.ufrag; | |
| document.getElementById('manual-pwd').value = STATE.pwd; // Pre-fill for convenience | |
| // ICE CANDIDATE HANDLING (ANTI-FREEZE) | |
| pc.onicecandidate = e => { | |
| if (!e.candidate) return; | |
| const cand = e.candidate.candidate; | |
| // CHECK FOR mDNS (Obfuscated IP) | |
| if (cand.includes(".local")) { | |
| document.getElementById('my-ip').innerText = "HIDDEN (mDNS Active)"; | |
| document.getElementById('my-ip').className = "val masked"; | |
| // We can't know our port easily if mDNS is on | |
| document.getElementById('my-port').innerText = "UNKNOWN"; | |
| } | |
| // CHECK FOR RAW IPv4 | |
| else if (cand.includes(" 192.168.") || cand.includes(" 10.")) { | |
| const parts = cand.split(' '); | |
| if (parts.length >= 6) { | |
| STATE.ip = parts[4]; | |
| STATE.port = parts[5]; | |
| document.getElementById('my-ip').innerText = STATE.ip; | |
| document.getElementById('my-ip').className = "val highlight"; | |
| document.getElementById('my-port').innerText = STATE.port; | |
| document.getElementById('my-port').className = "val highlight"; | |
| // Auto-fill subnet for convenience | |
| const sub = STATE.ip.split('.').slice(0,3).join('.'); | |
| document.getElementById('scan-subnet').value = sub; | |
| } | |
| } | |
| LOG("CANDIDATE GATHERED (LISTENER READY)"); | |
| }; | |
| STATE.pc = pc; | |
| // Monitor Connection | |
| pc.onconnectionstatechange = () => { | |
| document.getElementById('conn-state').innerText = pc.connectionState.toUpperCase(); | |
| if(pc.connectionState === 'connected') { | |
| document.getElementById('conn-state').style.background = '#0f0'; | |
| document.getElementById('conn-state').style.color = '#000'; | |
| document.getElementById('main-view').style.display = 'none'; | |
| document.getElementById('chat-ui').style.display = 'flex'; | |
| } | |
| }; | |
| } | |
| // ============================================ | |
| // 2. SCANNER (THE SEARCH) | |
| // ============================================ | |
| const SCANNER = { | |
| active: false, | |
| start: async () => { | |
| if(SCANNER.active) return; | |
| SCANNER.active = true; | |
| const subnet = document.getElementById('scan-subnet').value; | |
| if(!subnet) return alert("ENTER SUBNET"); | |
| LOG(`STARTING SCAN ON ${subnet}.x ...`); | |
| // Scan 1-254 | |
| for(let i=1; i<255; i++) { | |
| if(STATE.connected) break; | |
| let ip = `${subnet}.${i}`; | |
| // Fast Ping | |
| checkHost(ip).then(alive => { | |
| if(alive) { | |
| LOG(`HOST FOUND: ${ip}`, "log-hit"); | |
| document.getElementById('manual-ip').value = ip; | |
| // Auto-Spray | |
| SPRAY.fire(ip); | |
| } | |
| }); | |
| if(i % 10 === 0) await new Promise(r => setTimeout(r, 50)); | |
| } | |
| SCANNER.active = false; | |
| LOG("SCAN COMPLETE"); | |
| } | |
| }; | |
| function checkHost(ip) { | |
| return new Promise(resolve => { | |
| const c = new AbortController(); | |
| const t = setTimeout(() => c.abort(), 1500); // 1.5s Timeout | |
| fetch(`http://${ip}:44332`, { mode:'no-cors', signal: c.signal }) | |
| .then(() => resolve(false)) | |
| .catch(e => { | |
| clearTimeout(t); | |
| // Fast failure = RST = Alive | |
| if(performance.now() < 1500 && e.name !== 'AbortError') resolve(true); | |
| else resolve(false); | |
| }); | |
| }); | |
| } | |
| // ============================================ | |
| // 3. CONNECTION LOGIC (SPRAY & MANUAL) | |
| // ============================================ | |
| const SPRAY = { | |
| fire: async (ip) => { | |
| LOG(`SPRAYING ${ip}...`); | |
| // Ensure we have a remote description "container" to add candidates to | |
| // We assume the other side has the same static credentials or user provided them | |
| await ensureRemote(); | |
| // 1. Burst Scan Ranges | |
| CONFIG.SPRAY_RANGES.forEach(async range => { | |
| for(let p = range[0]; p < range[1]; p++) { | |
| addCand(ip, p); | |
| if(p % 100 === 0) await new Promise(r=>setTimeout(r,10)); | |
| } | |
| }); | |
| LOG("SPRAY SENT."); | |
| } | |
| }; | |
| const MANUAL = { | |
| connect: async () => { | |
| const ip = document.getElementById('manual-ip').value; | |
| const port = document.getElementById('manual-port').value; | |
| const ufrag = document.getElementById('manual-ufrag').value; | |
| const pwd = document.getElementById('manual-pwd').value; | |
| if(!ip) return alert("NEED IP"); | |
| // Update Config if user provided new keys | |
| if(ufrag) CONFIG.UFRAG = ufrag; | |
| if(pwd) CONFIG.PWD = pwd; | |
| await ensureRemote(); | |
| if(port) { | |
| LOG(`MANUAL CONNECT: ${ip}:${port}`, "log-hit"); | |
| addCand(ip, port); | |
| } else { | |
| // No port? Spray. | |
| SPRAY.fire(ip); | |
| } | |
| } | |
| }; | |
| async function ensureRemote() { | |
| if(!STATE.pc.currentRemoteDescription) { | |
| // We construct a Dummy Answer that mirrors our Offer | |
| // But importantly, it uses the UFRAG/PWD that we expect the TARGET to have. | |
| // If the user typed a Manual Ufrag, we use that. | |
| let sdp = STATE.pc.localDescription.sdp; | |
| sdp = sdp.replace(/a=setup:actpass/, "a=setup:active"); // We become Client | |
| sdp = sdp.replace(/type: "offer"/, 'type: "answer"'); | |
| // Override with target credentials | |
| const useUfrag = document.getElementById('manual-ufrag').value || CONFIG.UFRAG; | |
| const usePwd = document.getElementById('manual-pwd').value || CONFIG.PWD; | |
| sdp = sdp.replace(/a=ice-ufrag:.*\r\n/, `a=ice-ufrag:${useUfrag}\r\n`); | |
| sdp = sdp.replace(/a=ice-pwd:.*\r\n/, `a=ice-pwd:${usePwd}\r\n`); | |
| try { | |
| await STATE.pc.setRemoteDescription({ type: "answer", sdp: sdp }); | |
| } catch(e) { | |
| console.error(e); | |
| } | |
| } | |
| } | |
| function addCand(ip, port) { | |
| STATE.pc.addIceCandidate({ | |
| candidate: `candidate:1 1 UDP 2122260223 ${ip} ${port} typ host`, | |
| sdpMid: "0", | |
| sdpMLineIndex: 0 | |
| }).catch(e=>{}); | |
| } | |
| // ============================================ | |
| // 4. CHAT | |
| // ============================================ | |
| function setupDC(dc) { | |
| STATE.dc = dc; | |
| dc.onopen = () => LOG("DATA CHANNEL OPEN"); | |
| dc.onmessage = e => { | |
| const d = document.createElement('div'); | |
| d.className = "msg peer"; | |
| d.innerText = `> ${e.data}`; | |
| document.getElementById('messages').appendChild(d); | |
| }; | |
| } | |
| const CHAT = { | |
| send: () => { | |
| const i = document.getElementById('chat-in'); | |
| if(!i.value) return; | |
| STATE.dc.send(i.value); | |
| const d = document.createElement('div'); | |
| d.className = "msg me"; | |
| d.innerText = i.value; | |
| document.getElementById('messages').appendChild(d); | |
| i.value = ''; | |
| } | |
| }; | |
| // BOOT | |
| init(); | |
| </script> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <title>ZERO_MESH V7 [AUTH-FIX]</title> | |
| <style> | |
| :root { --bg: #000; --term: #0f0; --dim: #002200; --warn: #ff9900; --err: #ff3333; } | |
| * { box-sizing: border-box; } | |
| body { background: var(--bg); color: var(--term); font-family: 'Courier New', monospace; padding: 10px; height: 100vh; display: flex; flex-direction: column; overflow: hidden; margin: 0; } | |
| /* HEADER */ | |
| header { border-bottom: 1px solid var(--dim); padding-bottom: 5px; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; } | |
| #status-pill { font-size: 10px; padding: 3px 6px; border-radius: 4px; background: #222; color: #888; font-weight: bold; } | |
| #status-pill.ready { background: var(--dim); color: var(--term); } | |
| #status-pill.error { background: var(--err); color: #fff; } | |
| /* DASHBOARD GRID */ | |
| #ui-grid { display: grid; grid-template-columns: 1fr; gap: 10px; overflow-y: auto; flex: 1; } | |
| /* CARDS */ | |
| .card { border: 1px solid #222; background: #080808; padding: 10px; display: flex; flex-direction: column; gap: 8px; } | |
| .card-head { font-size: 10px; color: #666; border-bottom: 1px solid #111; padding-bottom: 4px; letter-spacing: 1px; } | |
| /* DATA FIELDS */ | |
| .field { display: flex; justify-content: space-between; align-items: center; font-size: 13px; } | |
| .val { font-weight: bold; color: #fff; } | |
| .val.hidden { color: #555; font-style: italic; } | |
| .val.ok { color: var(--term); } | |
| .val.bad { color: var(--err); } | |
| /* BUTTONS */ | |
| .actions { display: flex; gap: 5px; margin-top: 5px; } | |
| button { background: var(--dim); border: 1px solid var(--term); color: var(--term); padding: 12px; flex: 1; font-family: inherit; font-weight: bold; font-size: 12px; cursor: pointer; border-radius: 2px; } | |
| button:active { background: var(--term); color: #000; } | |
| button.warn { border-color: var(--warn); color: var(--warn); } | |
| input { background: #111; border: 1px solid #333; color: #fff; padding: 10px; flex: 1; font-family: inherit; font-size: 14px; } | |
| input:focus { border-color: var(--term); outline: none; } | |
| /* CONSOLE */ | |
| #logs { height: 100px; border: 1px solid #222; background: #000; overflow-y: scroll; padding: 5px; font-size: 10px; color: #666; font-family: monospace; } | |
| .log-hit { color: var(--warn); background: #220000; } | |
| .log-ok { color: var(--term); } | |
| /* CHAT */ | |
| #chat-view { display: none; flex: 1; flex-direction: column; gap: 10px; } | |
| #msgs { flex: 1; border: 1px solid var(--dim); padding: 10px; overflow-y: scroll; font-size: 12px; } | |
| .msg-peer { color: var(--warn); margin-bottom: 5px; } | |
| .msg-me { color: #888; text-align: right; margin-bottom: 5px; } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <strong>ZM_V7 [LONG-KEY]</strong> | |
| <div id="status-pill">BOOTING...</div> | |
| </header> | |
| <div id="setup-view" style="display:flex; flex-direction:column; flex:1; overflow:hidden;"> | |
| <div id="ui-grid"> | |
| <div class="card"> | |
| <div class="card-head">1. LOCAL IDENTITY</div> | |
| <div class="field"> | |
| <span>IP:</span> | |
| <span id="disp-ip" class="val hidden">HIDDEN (mDNS)</span> | |
| </div> | |
| <div class="field"> | |
| <span>PORT:</span> | |
| <span id="disp-port" class="val hidden">UNKNOWN</span> | |
| </div> | |
| <div class="field"> | |
| <span>AUTH STATUS:</span> | |
| <span id="auth-status" class="val">CHECKING...</span> | |
| </div> | |
| <div id="unmask-box" style="margin-top:5px; display:none;"> | |
| <button class="warn" onclick="HACKS.unmask()">UNMASK IP (REQ MIC)</button> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <div class="card-head">2. TARGET DISCOVERY</div> | |
| <div class="actions"> | |
| <input id="scan-subnet" value="192.168.1" style="flex:0.5; text-align:center;"> | |
| <button onclick="SCANNER.start()">AUTO-SCAN LAN</button> | |
| </div> | |
| <div class="card-head" style="margin-top:10px; border:none; color:var(--warn);">MANUAL FALLBACK</div> | |
| <div class="actions"> | |
| <input id="man-ip" placeholder="IP (e.g. 192.168.1.5)"> | |
| <input id="man-port" placeholder="Port" type="number"> | |
| </div> | |
| <button onclick="CONNECT.manual()">FORCE CONNECT</button> | |
| </div> | |
| </div> | |
| <div id="logs"></div> | |
| </div> | |
| <div id="chat-view"> | |
| <div id="msgs"> | |
| <div style="color:#444">--- ENCRYPTED TUNNEL ESTABLISHED ---</div> | |
| </div> | |
| <div class="actions"> | |
| <input id="chat-in" placeholder="Message..."> | |
| <button onclick="CHAT.send()">SEND</button> | |
| </div> | |
| </div> | |
| <script> | |
| // ============================================ | |
| // 1. CONFIGURATION (THE FIX) | |
| // ============================================ | |
| const CONFIG = { | |
| // 1. EXTENDED LENGTHS TO SATISFY CHROME SECURITY | |
| // Ufrag > 4 chars | |
| UFRAG: "zeromesh_v7_static_id", | |
| // Pwd > 22 chars (Crucial fix) | |
| PWD: "zeromesh_v7_static_password_secure_256", | |
| // 2. SPRAY RANGES | |
| // We scan these if we find an IP | |
| SPRAY: [ | |
| [32768, 33200], // Android Start | |
| [49152, 49552], // IANA Start | |
| [50000, 50200] // Common Fallback | |
| ] | |
| }; | |
| // ============================================ | |
| // 2. LOGGING | |
| // ============================================ | |
| const LOG = (msg, type='') => { | |
| const l = document.getElementById('logs'); | |
| const d = document.createElement('div'); | |
| d.className = type; | |
| d.innerText = `> ${msg}`; | |
| l.appendChild(d); | |
| l.scrollTop = l.scrollHeight; | |
| }; | |
| // ============================================ | |
| // 3. CORE STATE | |
| // ============================================ | |
| const STATE = { | |
| pc: null, | |
| dc: null, | |
| ip: null, | |
| port: null | |
| }; | |
| // ============================================ | |
| // 4. KERNEL (INIT) | |
| // ============================================ | |
| async function init() { | |
| LOG("KERNEL INIT..."); | |
| const pc = new RTCPeerConnection({ iceServers: [] }); | |
| // Data Channel (Triggers ICE) | |
| const dc = pc.createDataChannel("zm_v7", { negotiated: true, id: 0 }); | |
| setupDC(dc); | |
| // Create Offer | |
| const offer = await pc.createOffer(); | |
| let sdp = offer.sdp; | |
| // --- STATIC AUTH HACK (IMPROVED) --- | |
| // We replace the random credentials with our long static ones | |
| // Regex handles \r\n or \n | |
| const newSdp = sdp.replace(/a=ice-ufrag:.*\s+/, `a=ice-ufrag:${CONFIG.UFRAG}\r\n`) | |
| .replace(/a=ice-pwd:.*\s+/, `a=ice-pwd:${CONFIG.PWD}\r\n`); | |
| try { | |
| await pc.setLocalDescription({ type: "offer", sdp: newSdp }); | |
| // If we get here, Chrome accepted the static keys! | |
| document.getElementById('auth-status').innerText = "SECURE (STATIC)"; | |
| document.getElementById('auth-status').className = "val ok"; | |
| document.getElementById('status-pill').innerText = "READY"; | |
| document.getElementById('status-pill').className = "ready"; | |
| LOG("STATIC AUTH APPLIED SUCCESSFULLY.", "log-ok"); | |
| } catch(e) { | |
| // If it still fails, we have to fallback | |
| console.error(e); | |
| document.getElementById('auth-status').innerText = "FAILED (USING DYNAMIC)"; | |
| document.getElementById('auth-status').className = "val bad"; | |
| document.getElementById('status-pill').innerText = "AUTH ERROR"; | |
| document.getElementById('status-pill').className = "error"; | |
| LOG("STATIC AUTH REJECTED. CHECK CONSOLE.", "log-hit"); | |
| // Fallback to random | |
| await pc.setLocalDescription(offer); | |
| } | |
| // --- IP DETECTION --- | |
| pc.onicecandidate = e => { | |
| if(!e.candidate) return; | |
| const c = e.candidate.candidate; | |
| if(c.includes(".local")) { | |
| document.getElementById('disp-ip').innerText = "HIDDEN (mDNS)"; | |
| document.getElementById('unmask-box').style.display = 'block'; // Show unmask button | |
| } else { | |
| // IPv4 Parse | |
| const match = c.match(/([0-9]{1,3}(\.[0-9]{1,3}){3}) ([0-9]+)/); | |
| if(match) { | |
| STATE.ip = match[1]; | |
| STATE.port = match[2]; | |
| document.getElementById('disp-ip').innerText = STATE.ip; | |
| document.getElementById('disp-ip').className = "val ok"; | |
| document.getElementById('disp-port').innerText = STATE.port; | |
| document.getElementById('disp-port').className = "val ok"; | |
| document.getElementById('unmask-box').style.display = 'none'; | |
| // Auto-fill subnet | |
| const sub = STATE.ip.split('.').slice(0,3).join('.'); | |
| document.getElementById('scan-subnet').value = sub; | |
| } | |
| } | |
| }; | |
| STATE.pc = pc; | |
| // Connection Monitor | |
| pc.onconnectionstatechange = () => { | |
| if(pc.connectionState === 'connected') { | |
| document.getElementById('setup-view').style.display = 'none'; | |
| document.getElementById('chat-view').style.display = 'flex'; | |
| } | |
| }; | |
| } | |
| // ============================================ | |
| // 5. UNMASKING HACK | |
| // ============================================ | |
| const HACKS = { | |
| unmask: async () => { | |
| try { | |
| const s = await navigator.mediaDevices.getUserMedia({audio:true}); | |
| s.getTracks().forEach(t=>t.stop()); | |
| STATE.pc.close(); | |
| init(); // Restart with permissions | |
| } catch(e) { alert("Mic Permission Denied"); } | |
| } | |
| }; | |
| // ============================================ | |
| // 6. SCANNER | |
| // ============================================ | |
| const SCANNER = { | |
| start: async () => { | |
| const sub = document.getElementById('scan-subnet').value; | |
| LOG(`SCANNING ${sub}.x ...`); | |
| for(let i=1; i<255; i++) { | |
| if(STATE.pc.connectionState === 'connected') break; | |
| const ip = `${sub}.${i}`; | |
| if(ip === STATE.ip) continue; | |
| checkHost(ip).then(alive => { | |
| if(alive) { | |
| LOG(`FOUND: ${ip}`, "log-hit"); | |
| document.getElementById('man-ip').value = ip; | |
| CONNECT.spray(ip); | |
| } | |
| }); | |
| if(i%10===0) await new Promise(r=>setTimeout(r,50)); | |
| } | |
| LOG("SCAN COMPLETE"); | |
| } | |
| }; | |
| function checkHost(ip) { | |
| return new Promise(resolve => { | |
| const c = new AbortController(); | |
| setTimeout(()=>c.abort(), 1500); | |
| fetch(`http://${ip}:44332`, {mode:'no-cors', signal:c.signal}) | |
| .then(()=>resolve(false)) | |
| .catch(e=>{ | |
| if(performance.now()<600 && e.name!=='AbortError') resolve(true); | |
| else resolve(false); | |
| }); | |
| }); | |
| } | |
| // ============================================ | |
| // 7. CONNECTION LOGIC | |
| // ============================================ | |
| const CONNECT = { | |
| manual: () => { | |
| const ip = document.getElementById('man-ip').value; | |
| const port = document.getElementById('man-port').value; | |
| if(!ip) return alert("IP Required"); | |
| if(port) { | |
| LOG(`MANUAL LOCK: ${ip}:${port}`, "log-hit"); | |
| addCand(ip, port); | |
| } else { | |
| CONNECT.spray(ip); | |
| } | |
| }, | |
| spray: async (ip) => { | |
| LOG(`SPRAYING ${ip}...`); | |
| await ensureRemote(); | |
| CONFIG.SPRAY.forEach(async range => { | |
| for(let p=range[0]; p<range[1]; p++) { | |
| addCand(ip, p); | |
| if(p%50===0) await new Promise(r=>setTimeout(r,5)); | |
| } | |
| }); | |
| } | |
| }; | |
| async function ensureRemote() { | |
| if(!STATE.pc.currentRemoteDescription) { | |
| // Construct Dummy Answer | |
| // Uses the SAME Static config (Symmetric) | |
| let sdp = STATE.pc.localDescription.sdp; | |
| sdp = sdp.replace(/type: "offer"/, 'type: "answer"') | |
| .replace(/a=setup:actpass/, "a=setup:active"); | |
| try { | |
| await STATE.pc.setRemoteDescription({ type: "answer", sdp: sdp }); | |
| } catch(e) { console.error(e); } | |
| } | |
| } | |
| function addCand(ip, port) { | |
| STATE.pc.addIceCandidate({ | |
| candidate: `candidate:1 1 UDP 2122260223 ${ip} ${port} typ host`, | |
| sdpMid: "0", | |
| sdpMLineIndex: 0 | |
| }).catch(e=>{}); | |
| } | |
| // ============================================ | |
| // 8. CHAT | |
| // ============================================ | |
| function setupDC(dc) { | |
| STATE.dc = dc; | |
| dc.onopen = () => LOG("CHANNEL OPEN"); | |
| dc.onmessage = e => { | |
| const d = document.createElement('div'); | |
| d.className = "msg-peer"; | |
| d.innerText = `< ${e.data}`; | |
| document.getElementById('msgs').appendChild(d); | |
| }; | |
| } | |
| const CHAT = { | |
| send: () => { | |
| const i = document.getElementById('chat-in'); | |
| if(!i.value) return; | |
| STATE.dc.send(i.value); | |
| const d = document.createElement('div'); | |
| d.className = "msg-me"; | |
| d.innerText = `${i.value} >`; | |
| document.getElementById('msgs').appendChild(d); | |
| i.value = ''; | |
| } | |
| }; | |
| init(); | |
| </script> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <title>ZERO_MESH_V3 // NO_SERVER</title> | |
| <style> | |
| :root { | |
| --bg: #050505; | |
| --term: #00ff41; | |
| --dim: #004411; | |
| --alert: #ff3333; | |
| --highlight: #ccffcc; | |
| } | |
| * { box-sizing: border-box; } | |
| body { | |
| background: var(--bg); | |
| color: var(--term); | |
| font-family: 'Courier New', monospace; | |
| margin: 0; padding: 10px; | |
| overflow: hidden; | |
| height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| /* HEADER */ | |
| header { | |
| border-bottom: 1px solid var(--dim); | |
| padding-bottom: 5px; margin-bottom: 10px; | |
| display: flex; justify-content: space-between; align-items: center; | |
| } | |
| #status-bar { font-size: 12px; font-weight: bold; } | |
| .btn-link { | |
| background: none; border: none; color: var(--dim); | |
| text-decoration: underline; cursor: pointer; font-family: inherit; font-size: 11px; | |
| } | |
| .btn-link:hover { color: var(--term); } | |
| /* MAIN LAYOUT */ | |
| main { flex: 1; display: flex; flex-direction: column; gap: 10px; overflow: hidden; position: relative; } | |
| /* LOGS & CHAT */ | |
| #console { | |
| flex: 1; | |
| border: 1px solid var(--dim); | |
| padding: 8px; | |
| overflow-y: auto; | |
| font-size: 11px; | |
| white-space: pre-wrap; | |
| opacity: 0.9; | |
| background: rgba(0,20,0,0.3); | |
| } | |
| .log-entry { margin-bottom: 2px; } | |
| .log-success { color: var(--highlight); font-weight: bold; } | |
| .log-fail { color: var(--alert); } | |
| .log-sys { color: #666; } | |
| #chat-area { | |
| flex: 2; | |
| border: 1px solid var(--term); | |
| padding: 10px; | |
| overflow-y: auto; | |
| display: none; | |
| flex-direction: column; | |
| background: #001100; | |
| } | |
| .msg { margin-bottom: 5px; max-width: 80%; padding: 5px 8px; border-radius: 4px; } | |
| .msg.me { color: #000; background: var(--term); align-self: flex-end; } | |
| .msg.peer { color: var(--term); border: 1px solid var(--dim); align-self: flex-start; } | |
| /* CONTROLS */ | |
| #input-area { display: flex; gap: 5px; margin-top: 5px; } | |
| input { | |
| background: #111; border: 1px solid var(--dim); color: #fff; | |
| flex: 1; padding: 10px; font-family: inherit; outline: none; | |
| } | |
| input:disabled { opacity: 0.5; } | |
| button { | |
| background: var(--dim); color: var(--term); border: none; | |
| padding: 10px 15px; cursor: pointer; font-weight: bold; font-family: inherit; | |
| } | |
| button:hover { background: var(--term); color: #000; } | |
| button:disabled { background: #222; color: #555; cursor: not-allowed; } | |
| /* OVERLAYS */ | |
| .overlay { | |
| position: absolute; top: 0; left: 0; right: 0; bottom: 0; | |
| background: rgba(5,5,5,0.95); | |
| border: 1px double var(--term); | |
| padding: 20px; | |
| overflow-y: auto; | |
| display: none; | |
| z-index: 100; | |
| } | |
| .overlay.active { display: block; } | |
| h2 { border-bottom: 1px solid var(--term); font-size: 16px; margin-top: 0; } | |
| h3 { font-size: 14px; margin-bottom: 5px; color: #fff; } | |
| p, li { font-size: 12px; line-height: 1.4; color: #ccc; } | |
| code { color: var(--term); background: #111; padding: 2px; } | |
| /* MORSE FALLBACK UI */ | |
| #morse-ui { display: none; border: 1px dashed var(--alert); padding: 10px; margin-top: 10px; } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <div> | |
| <strong>ZERO_MESH_V3</strong> | |
| <span style="font-size:10px; color:#666" id="my-ip">DETECTING...</span> | |
| </div> | |
| <div> | |
| <button class="btn-link" onclick="UI.toggleHelp()">[ MANUAL / HOW IT WORKS ]</button> | |
| <span id="connection-status" style="margin-left:10px; border:1px solid var(--term); padding:2px 5px;">IDLE</span> | |
| </div> | |
| </header> | |
| <main> | |
| <div id="console"> | |
| <div class="log-entry">> SYSTEM STARTUP...</div> | |
| <div class="log-entry">> LOADING CLONE IDENTITY...</div> | |
| </div> | |
| <div id="chat-area"> | |
| <div style="text-align:center; color:#444; margin:10px;">-- ENCRYPTED P2P TUNNEL ESTABLISHED --</div> | |
| </div> | |
| <div id="morse-ui"> | |
| <strong style="color:var(--alert)">⚠️ HANDSHAKE STALLED</strong> | |
| <p>Peer found but UDP blocked. Engage <strong>WiFi Congestion Modulation</strong>?</p> | |
| <div style="display:flex; gap:10px;"> | |
| <button onclick="MORSE.sendPort()" style="flex:1">TX: JAM WIFI (SEND PORT)</button> | |
| <button onclick="MORSE.listen()" style="flex:1">RX: LISTEN FOR JAM</button> | |
| </div> | |
| <div id="morse-log" style="font-size:10px; margin-top:5px; color:#aaa; font-family:monospace;">STATUS: STANDBY</div> | |
| </div> | |
| <div id="input-area"> | |
| <input type="text" id="msg-input" placeholder="Scanning Network..." disabled> | |
| <button id="send-btn" disabled onclick="CHAT.send()">SEND</button> | |
| </div> | |
| <div id="help-overlay" class="overlay"> | |
| <button onclick="UI.toggleHelp()" style="float:right; padding:2px 5px;">[X] CLOSE</button> | |
| <h2>// OPERATIONAL MANUAL</h2> | |
| <p>This is a <strong>serverless</strong> browser-to-browser communication tool. It uses 4 distinct hacks to bypass the browser sandbox.</p> | |
| <h3>1. IDENTITY CLONING (The "Shared Brain")</h3> | |
| <p> | |
| Standard WebRTC requires exchanging "Fingerprints" to verify identity. | |
| <strong>Hack:</strong> Both browsers load the exact same <code>ECDSA Private Key</code> from the source code. | |
| Because they are cryptographically identical, they don't need to exchange keys. They inherently trust each other. | |
| </p> | |
| <h3>2. DISCOVERY: TCP TIMING ATTACK</h3> | |
| <p> | |
| Browsers cannot scan IPs. | |
| <strong>Hack:</strong> We attempt to fetch images from <code>192.168.1.X</code>. | |
| If the request times out (2000ms), the host is down. | |
| If the request fails <em>instantly</em> (<50ms) with a TCP Reset, the host is <strong>UP</strong>. | |
| We use this timing delta to build a map of the LAN. | |
| </p> | |
| <h3>3. TRANSPORT: ICE SPRAYING</h3> | |
| <p> | |
| We don't know the peer's Port. | |
| <strong>Hack:</strong> We assume the peer is listening on the standard ephemeral range (49152-49252). | |
| We "Spray" STUN packets at every single port in that range. | |
| 99% fail, but 1 will hit the open port and establish the lock. | |
| </p> | |
| <h3>4. FALLBACK: CONGESTION MORSE</h3> | |
| <p> | |
| If UDP ports are randomized/blocked, we cannot connect. | |
| <strong>Hack:</strong> We use the WiFi Router as a signaling device. | |
| <strong>TX:</strong> Browser A floods the router with traffic to cause lag (Bit 1). | |
| <strong>RX:</strong> Browser B pings the router to measure lag spikes. | |
| We transmit the 16-bit Port Number via this side-channel. | |
| </p> | |
| </div> | |
| </main> | |
| <script> | |
| // ========================================== | |
| // CONFIGURATION & SECRETS | |
| // ========================================== | |
| const CONFIG = { | |
| UFRAG: "zeromesh_v3", | |
| PWD: "zeromesh_static_password", | |
| // We scan these port ranges blindly | |
| SPRAY_RANGES: [ [49152, 49252], [33000, 33100] ], | |
| SUBNET_BATCH: 30 // How many IPs to scan at once | |
| }; | |
| // ========================================== | |
| // GLOBAL STATE | |
| // ========================================== | |
| const STATE = { | |
| pc: null, | |
| dc: null, | |
| localIP: null, | |
| subnet: null, | |
| foundPeers: new Set(), | |
| connected: false | |
| }; | |
| // ========================================== | |
| // UI CONTROLLER | |
| // ========================================== | |
| const UI = { | |
| toggleHelp: () => { | |
| const el = document.getElementById('help-overlay'); | |
| el.classList.toggle('active'); | |
| }, | |
| log: (msg, type='sys') => { | |
| const c = document.getElementById('console'); | |
| const d = document.createElement('div'); | |
| d.className = `log-entry log-${type}`; | |
| d.innerText = `> ${msg}`; | |
| c.appendChild(d); | |
| c.scrollTop = c.scrollHeight; | |
| }, | |
| status: (s) => document.getElementById('connection-status').innerText = s, | |
| enableChat: () => { | |
| document.getElementById('console').style.display = 'none'; | |
| document.getElementById('chat-area').style.display = 'flex'; | |
| const inp = document.getElementById('msg-input'); | |
| inp.disabled = false; | |
| inp.placeholder = "Type message..."; | |
| inp.focus(); | |
| document.getElementById('send-btn').disabled = false; | |
| UI.status("LINK ESTABLISHED"); | |
| }, | |
| chatMsg: (text, who) => { | |
| const div = document.createElement('div'); | |
| div.className = `msg ${who}`; | |
| div.innerText = text; | |
| document.getElementById('chat-area').appendChild(div); | |
| } | |
| }; | |
| // ========================================== | |
| // CORE 1: IDENTITY (THE CLONE) | |
| // ========================================== | |
| async function initIdentity() { | |
| UI.log("Generating Static Certificate...", "sys"); | |
| // In production, you would import a hardcoded JWK here. | |
| // For this demo, we rely on the SDP Munging hack (The "Promiscuous" mode) | |
| // where we force the SDP to use static strings, skipping strict verification setup. | |
| return true; | |
| } | |
| // ========================================== | |
| // CORE 2: DISCOVERY (TIMING ATTACK) | |
| // ========================================== | |
| async function getLocalIP() { | |
| // Standard WebRTC IP leak trick | |
| return new Promise(resolve => { | |
| const p = new RTCPeerConnection({iceServers:[]}); | |
| p.createDataChannel(''); | |
| p.createOffer().then(o => p.setLocalDescription(o)); | |
| p.onicecandidate = e => { | |
| if(e.candidate) { | |
| const match = e.candidate.candidate.match(/([0-9]{1,3}(\.[0-9]{1,3}){3})/); | |
| if(match) { | |
| STATE.localIP = match[1]; | |
| STATE.subnet = STATE.localIP.split('.').slice(0,3).join('.'); | |
| document.getElementById('my-ip').innerText = STATE.localIP; | |
| UI.log(`LOCAL IP DETECTED: ${STATE.localIP}`, 'success'); | |
| resolve(STATE.localIP); | |
| p.close(); | |
| } | |
| } | |
| }; | |
| }); | |
| } | |
| async function startScan() { | |
| if(!STATE.subnet) await getLocalIP(); | |
| UI.log(`INITIATING SUB_NET SCAN ON ${STATE.subnet}.x ...`); | |
| UI.status("SCANNING"); | |
| // Scan loop | |
| for(let i=1; i<255; i+=CONFIG.SUBNET_BATCH) { | |
| if(STATE.connected) break; | |
| let batch = []; | |
| for(let j=0; j<CONFIG.SUBNET_BATCH && (i+j)<255; j++) { | |
| let target = `${STATE.subnet}.${i+j}`; | |
| if(target !== STATE.localIP) batch.push(checkHost(target)); | |
| } | |
| await Promise.all(batch); | |
| // Small delay to let browser breathe | |
| await new Promise(r => setTimeout(r, 100)); | |
| } | |
| if(!STATE.connected) { | |
| if(STATE.foundPeers.size === 0) { | |
| UI.log("SCAN COMPLETE. NO TARGETS. RETRYING...", "sys"); | |
| setTimeout(startScan, 2000); | |
| } else { | |
| // We found an IP but Spray failed to connect? Show fallback. | |
| document.getElementById('morse-ui').style.display = 'block'; | |
| } | |
| } | |
| } | |
| // The Timing Logic | |
| function checkHost(ip) { | |
| return new Promise(resolve => { | |
| const start = performance.now(); | |
| const controller = new AbortController(); | |
| const timeoutId = setTimeout(() => controller.abort(), 2000); // 2s = Offline | |
| // We fetch a weird port to provoke RST | |
| fetch(`http://${ip}:44332`, { mode: 'no-cors', signal: controller.signal }) | |
| .then(() => resolve(false)) | |
| .catch(err => { | |
| clearTimeout(timeoutId); | |
| const duration = performance.now() - start; | |
| // If it failed fast (<500ms), the machine replied "No". It is ALIVE. | |
| // If it timed out (>1500ms), the machine is DEAD. | |
| if (duration < 600 && err.name !== 'AbortError') { | |
| UI.log(`TARGET LOCKED: ${ip} (${Math.round(duration)}ms)`, 'success'); | |
| STATE.foundPeers.add(ip); | |
| sprayTarget(ip); | |
| resolve(true); | |
| } else { | |
| resolve(false); | |
| } | |
| }); | |
| }); | |
| } | |
| // ========================================== | |
| // CORE 3: TRANSPORT (SPRAY) | |
| // ========================================== | |
| async function setupListener() { | |
| STATE.pc = new RTCPeerConnection({ iceServers: [] }); | |
| // 1. Setup Listener Channel | |
| const dc = STATE.pc.createDataChannel("zero_mesh", { negotiated: true, id: 0 }); | |
| setupDC(dc); | |
| // 2. Create SDP with Static Auth | |
| const offer = await STATE.pc.createOffer(); | |
| let sdp = offer.sdp; | |
| // Overwrite random ufrag/pwd with static ones | |
| sdp = sdp.replace(/a=ice-ufrag:.*\r\n/, `a=ice-ufrag:${CONFIG.UFRAG}\r\n`); | |
| sdp = sdp.replace(/a=ice-pwd:.*\r\n/, `a=ice-pwd:${CONFIG.PWD}\r\n`); | |
| await STATE.pc.setLocalDescription({ type: "offer", sdp: sdp }); | |
| UI.log("LISTENER READY (STATIC CREDS APPLIED)", 'sys'); | |
| STATE.pc.onconnectionstatechange = () => { | |
| if(STATE.pc.connectionState === 'connected') { | |
| STATE.connected = true; | |
| UI.enableChat(); | |
| } | |
| }; | |
| } | |
| async function sprayTarget(ip) { | |
| if(STATE.connected) return; | |
| UI.log(`>> SPRAYING STUN PACKETS AT ${ip}...`, 'sys'); | |
| // To add candidates, we need a remote description. | |
| // We create a dummy "Answer" mirroring our static creds. | |
| if(!STATE.pc.currentRemoteDescription) { | |
| try { | |
| await STATE.pc.setRemoteDescription({ | |
| type: "answer", | |
| sdp: STATE.pc.localDescription.sdp // Symmetric | |
| }); | |
| } catch(e) { } | |
| } | |
| // BRUTE FORCE CANDIDATES | |
| CONFIG.SPRAY_RANGES.forEach(range => { | |
| for(let p = range[0]; p <= range[1]; p++) { | |
| STATE.pc.addIceCandidate({ | |
| candidate: `candidate:1 1 UDP 2122260223 ${ip} ${p} typ host`, | |
| sdpMid: "0", | |
| sdpMLineIndex: 0 | |
| }).catch(e=>{}); | |
| } | |
| }); | |
| } | |
| function setupDC(dc) { | |
| STATE.dc = dc; | |
| dc.onopen = () => UI.enableChat(); | |
| dc.onmessage = e => UI.chatMsg(e.data, 'peer'); | |
| } | |
| // ========================================== | |
| // CORE 4: CHAT & UTILS | |
| // ========================================== | |
| const CHAT = { | |
| send: () => { | |
| const inp = document.getElementById('msg-input'); | |
| const txt = inp.value; | |
| if(!txt) return; | |
| STATE.dc.send(txt); | |
| UI.chatMsg(txt, 'me'); | |
| inp.value = ''; | |
| } | |
| }; | |
| document.getElementById('msg-input').addEventListener('keypress', e => { | |
| if(e.key === 'Enter') CHAT.send(); | |
| }); | |
| // ========================================== | |
| // FALLBACK: CONGESTION MORSE | |
| // ========================================== | |
| const MORSE = { | |
| gateway: () => STATE.subnet + '.1', | |
| jam: async (ms) => { | |
| const start = Date.now(); | |
| while(Date.now() - start < ms) { | |
| fetch(`http://${MORSE.gateway()}/?z=${Math.random()}`, {mode:'no-cors'}).catch(e=>{}); | |
| } | |
| }, | |
| sendPort: async () => { | |
| // Simple logic: Jam for 3s to signal start | |
| document.getElementById('morse-log').innerText = "TRANSMITTING JAM SIGNAL..."; | |
| await MORSE.jam(3000); | |
| document.getElementById('morse-log').innerText = "DONE. IF PEER WAS LISTENING, RE-SPRAY WILL OCCUR."; | |
| }, | |
| listen: async () => { | |
| document.getElementById('morse-log').innerText = "MONITORING LATENCY..."; | |
| // In full version, this detects the spike and calculates the port. | |
| // For demo, we just log it. | |
| setInterval(async () => { | |
| const start = performance.now(); | |
| try { await fetch(`http://${MORSE.gateway()}/?p=${Math.random()}`, | |
| {mode:'no-cors', signal: AbortSignal.timeout(500)}); } catch(e){} | |
| const lat = performance.now() - start; | |
| if(lat > 200) document.getElementById('morse-log').innerText = `HIGH LATENCY DETECTED: ${Math.round(lat)}ms (SIGNAL?)`; | |
| }, 500); | |
| } | |
| }; | |
| // ========================================== | |
| // BOOT | |
| // ========================================== | |
| (async () => { | |
| await initIdentity(); | |
| await setupListener(); | |
| startScan(); | |
| })(); | |
| </script> | |
| </body> | |
| </html> |
Comments are disabled for this gist.