mirror of
https://github.com/promptpirate-x/discord-id-bypass-tool.git
synced 2026-06-09 22:43:53 +02:00
Merge pull request #20 from levouinse/pr192026
add skeleton loading, tutorial, and mobile support for head move
This commit is contained in:
@@ -19,6 +19,33 @@
|
||||
</p>
|
||||
|
||||
---
|
||||
# UPDATE 4 - K-ID BYPASS NOW WORKING WITH DUAL MODE!
|
||||
The K-ID Bypass feature now has **TWO verification modes**:
|
||||
|
||||
**🚀 API Mode (Default)** - Fast verification using kibty.town API
|
||||
- ✅ Quick (2-3 seconds)
|
||||
- ⚠️ May be patched by k-ID
|
||||
- Uses external service
|
||||
|
||||
**🔒 Standalone Mode** - Direct verification without external dependencies
|
||||
- ✅ 100% reliable (no external API)
|
||||
- ✅ Works even if kibty.town is down
|
||||
- ⏱️ Slower (5-10 seconds)
|
||||
- Runs entirely in your browser
|
||||
|
||||
**How to use:**
|
||||
1. Start Discord age verification and choose "Face Scan" option
|
||||
2. When Discord shows a QR code, either:
|
||||
- Copy the QR code URL and paste it in the K-ID Bypass panel
|
||||
- Upload/drag the QR code image directly
|
||||
3. **Choose your mode:** Click "API Mode" or "Standalone" button
|
||||
4. Click "✓ Verify Account"
|
||||
5. Wait for confirmation, then return to Discord
|
||||
|
||||
**If API Mode fails, try Standalone Mode!**
|
||||
|
||||
---
|
||||
|
||||
# UPDATE 3
|
||||
If you're having issues with your OBS camera not being recognised, or being recognised and getting pingged, use Discord in firefox while enabling "resistFingerprinting" https://support.mozilla.org/en-US/kb/resist-fingerprinting
|
||||
Working on a new overhauled version of the tool that also blinks, breathes and moves in a way to trick more advanced sensors, as well as a comfyUI workflow thay uses realtime Webcam Video2Video conversion with interpolation that lets you use any face (with a 1-2 second movement delay as a buffer) for a webcam output as a more permanent solution to all face recog systems.
|
||||
|
||||
+750
-44
@@ -26,8 +26,10 @@
|
||||
.model-panel::-webkit-scrollbar{width:5px}.model-panel::-webkit-scrollbar-track{background:transparent}.model-panel::-webkit-scrollbar-thumb{background:rgba(100,220,255,0.2);border-radius:3px}
|
||||
.controls-panel{bottom:180px;left:20px;max-width:320px}
|
||||
.values-panel{bottom:20px;left:20px;min-width:220px;max-width:320px}
|
||||
.kid-panel{top:60px;left:20px;max-width:360px;max-height:calc(100vh - 200px);overflow-y:auto}
|
||||
.kid-panel{top:60px;left:20px;max-width:360px;max-height:20vh;overflow-y:auto}
|
||||
.kid-panel::-webkit-scrollbar{width:5px}.kid-panel::-webkit-scrollbar-track{background:transparent}.kid-panel::-webkit-scrollbar-thumb{background:rgba(100,220,255,0.2);border-radius:3px}
|
||||
.lighting-panel{top:250px;left:20px;max-width:320px;max-height:22vh;overflow-y:auto}
|
||||
.lighting-panel::-webkit-scrollbar{width:5px}.lighting-panel::-webkit-scrollbar-track{background:transparent}.lighting-panel::-webkit-scrollbar-thumb{background:rgba(100,220,255,0.2);border-radius:3px}
|
||||
@media(max-width:768px){
|
||||
.hp{font-size:10px;padding:10px 12px;max-width:calc(100vw - 20px)}
|
||||
.hp.collapsed>*:not(.ht){display:none!important}
|
||||
@@ -96,7 +98,6 @@
|
||||
.hide-ui-btn{position:absolute;top:20px;right:20px;background:rgba(10,10,20,0.85);backdrop-filter:blur(12px);border:1px solid rgba(100,220,255,0.15);border-radius:6px;padding:6px 14px;color:#64dcff;font-family:'JetBrains Mono',monospace;font-size:10px;cursor:pointer;pointer-events:auto;z-index:20}
|
||||
.hide-ui-btn:hover{background:rgba(100,220,255,0.15)}
|
||||
.hud.hidden .hp{display:none!important}
|
||||
.hud.hidden .hide-ui-btn{display:block!important}
|
||||
.kid-input{background:rgba(10,10,20,0.9);border:1px solid rgba(100,220,255,0.2);color:#e0e0e8;padding:6px 10px;border-radius:4px;font-size:11px;font-family:'JetBrains Mono',monospace;width:100%;margin-top:4px}
|
||||
.kid-btn{background:rgba(100,220,255,0.1);border:1px solid rgba(100,220,255,0.3);color:#64dcff;padding:8px 16px;border-radius:6px;cursor:pointer;font-family:'JetBrains Mono',monospace;font-size:11px;width:100%;margin-top:8px}
|
||||
.kid-btn:hover{background:rgba(100,220,255,0.2)}
|
||||
@@ -108,14 +109,194 @@
|
||||
.cr{font-size:9px;gap:6px}
|
||||
.ck{font-size:8px;padding:1px 5px}
|
||||
}
|
||||
.hide-ui-elements{top:60px;left:20px}
|
||||
.hidden{display:none}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════
|
||||
QUICK START TUTORIAL
|
||||
═══════════════════════════════════════════════════════ */
|
||||
.tutorial-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(10,10,15,0.95);backdrop-filter:blur(8px);z-index:10000;display:none;align-items:center;justify-content:center}
|
||||
.tutorial-overlay.active{display:flex}
|
||||
.tutorial-card{background:rgba(10,10,20,0.95);border:2px solid rgba(100,220,255,0.3);border-radius:12px;padding:32px;max-width:500px;text-align:center;box-shadow:0 20px 60px rgba(0,0,0,0.5)}
|
||||
.tutorial-title{font-family:'Space Grotesk',sans-serif;font-size:24px;color:#64dcff;margin-bottom:16px;letter-spacing:1px}
|
||||
.tutorial-text{font-size:14px;color:#c0c0cc;line-height:1.8;margin-bottom:24px}
|
||||
.tutorial-step{font-size:12px;color:#808090;margin-bottom:20px}
|
||||
.tutorial-highlight{color:#64dcff;font-weight:600;background:rgba(100,220,255,0.1);padding:2px 8px;border-radius:4px}
|
||||
.tutorial-btn{background:linear-gradient(135deg,#64dcff,#a78bfa);border:none;color:#0a0a0f;padding:12px 32px;border-radius:6px;font-family:'JetBrains Mono',monospace;font-size:13px;font-weight:600;cursor:pointer;letter-spacing:0.5px;transition:transform 0.2s}
|
||||
.tutorial-btn:hover{transform:scale(1.05)}
|
||||
.tutorial-skip{margin-top:16px;font-size:11px;color:#606070;cursor:pointer;text-decoration:underline}
|
||||
.tutorial-skip:hover{color:#64dcff}
|
||||
.tutorial-progress{display:flex;gap:8px;justify-content:center;margin-top:20px}
|
||||
.tutorial-dot{width:8px;height:8px;border-radius:50%;background:rgba(100,220,255,0.2);transition:all 0.3s}
|
||||
.tutorial-dot.active{background:#64dcff;width:24px;border-radius:4px}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════
|
||||
MOBILE VIRTUAL JOYSTICK
|
||||
═══════════════════════════════════════════════════════ */
|
||||
.mobile-controls{position:fixed;bottom:20px;left:0;right:0;display:none;justify-content:space-between;padding:0 20px;pointer-events:none;z-index:100}
|
||||
@media(max-width:768px){.mobile-controls{display:flex}}
|
||||
.joystick-container{width:120px;height:120px;position:relative;pointer-events:auto}
|
||||
.joystick-base{width:100%;height:100%;border-radius:50%;background:rgba(10,10,20,0.6);backdrop-filter:blur(8px);border:2px solid rgba(100,220,255,0.3);position:relative}
|
||||
.joystick-stick{width:50px;height:50px;border-radius:50%;background:linear-gradient(135deg,#64dcff,#a78bfa);position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);box-shadow:0 4px 12px rgba(100,220,255,0.4);transition:all 0.1s}
|
||||
.joystick-label{position:absolute;top:-25px;left:50%;transform:translateX(-50%);font-size:10px;color:#64dcff;font-family:'JetBrains Mono',monospace;white-space:nowrap}
|
||||
.mobile-btn-group{display:flex;flex-direction:column;gap:12px;pointer-events:auto}
|
||||
.mobile-btn{width:60px;height:60px;border-radius:50%;background:rgba(10,10,20,0.6);backdrop-filter:blur(8px);border:2px solid rgba(100,220,255,0.3);display:flex;align-items:center;justify-content:center;font-size:11px;color:#64dcff;font-family:'JetBrains Mono',monospace;font-weight:600;touch-action:none;user-select:none}
|
||||
.mobile-btn.active{background:rgba(100,220,255,0.3);border-color:#64dcff;box-shadow:0 0 20px rgba(100,220,255,0.5)}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════
|
||||
PHONEME SELECTOR
|
||||
═══════════════════════════════════════════════════════ */
|
||||
.phoneme-panel{position:absolute;bottom:20px;right:20px;background:rgba(10,10,20,0.85);backdrop-filter:blur(12px);border:1px solid rgba(100,220,255,0.15);border-radius:8px;padding:14px;pointer-events:auto;display:none}
|
||||
@media(max-width:768px){.phoneme-panel{bottom:160px;right:10px}}
|
||||
.phoneme-panel.visible{display:block}
|
||||
.phoneme-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
|
||||
.phoneme-btn{width:50px;height:50px;border-radius:8px;background:rgba(167,139,250,0.1);border:1px solid rgba(167,139,250,0.3);color:#a78bfa;font-family:'Space Grotesk',sans-serif;font-size:20px;font-weight:600;cursor:pointer;transition:all 0.2s;display:flex;align-items:center;justify-content:center}
|
||||
.phoneme-btn:hover{background:rgba(167,139,250,0.25);border-color:#a78bfa;transform:scale(1.1)}
|
||||
.phoneme-btn.active{background:rgba(167,139,250,0.3);border-color:#a78bfa;box-shadow:0 0 16px rgba(167,139,250,0.5)}
|
||||
.phoneme-toggle{position:absolute;top:20px;right:380px;background:rgba(10,10,20,0.85);backdrop-filter:blur(12px);border:1px solid rgba(100,220,255,0.15);border-radius:6px;padding:6px 14px;color:#a78bfa;font-family:'JetBrains Mono',monospace;font-size:10px;cursor:pointer;pointer-events:auto;z-index:20}
|
||||
.phoneme-toggle:hover{background:rgba(167,139,250,0.15)}
|
||||
@media(max-width:768px){.phoneme-toggle{top:10px;right:10px}}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════
|
||||
LIGHTING CONTROLS
|
||||
═══════════════════════════════════════════════════════ */
|
||||
.light-row{display:flex;align-items:center;gap:8px;padding:4px 0;font-size:11px}
|
||||
.light-label{min-width:60px;font-weight:600}
|
||||
.light-slider{flex:1;accent-color:#64dcff;height:4px}
|
||||
.light-value{min-width:35px;text-align:right;color:#64dcff;font-weight:600;font-size:10px}
|
||||
.light-color{width:20px;height:20px;border-radius:4px;border:1px solid rgba(100,220,255,0.3);cursor:pointer}
|
||||
.light-toggle{background:rgba(100,220,255,0.1);border:1px solid rgba(100,220,255,0.3);color:#64dcff;padding:4px 10px;border-radius:4px;cursor:pointer;font-size:9px;font-family:'JetBrains Mono',monospace}
|
||||
.light-toggle:hover{background:rgba(100,220,255,0.2)}
|
||||
.light-toggle.active{background:rgba(74,222,128,0.2);border-color:#4ade80;color:#4ade80}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════
|
||||
SKELETON LOADING
|
||||
═══════════════════════════════════════════════════════ */
|
||||
.skeleton-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:#0a0a0f;z-index:9999;display:flex;align-items:center;justify-content:center;opacity:1;transition:opacity 0.4s ease}
|
||||
.skeleton-overlay.fade-out{opacity:0;pointer-events:none}
|
||||
.skeleton-container{width:90%;max-width:1400px;height:90vh;display:grid;grid-template-columns:1fr 2fr 1fr;grid-template-rows:auto 1fr auto;gap:20px;padding:20px}
|
||||
|
||||
/* Skeleton shimmer animation */
|
||||
@keyframes shimmer{0%{background-position:-1000px 0}100%{background-position:1000px 0}}
|
||||
.skeleton-box{background:linear-gradient(90deg,rgba(100,220,255,0.03) 0%,rgba(100,220,255,0.08) 50%,rgba(100,220,255,0.03) 100%);background-size:1000px 100%;animation:shimmer 2s infinite linear;border:1px solid rgba(100,220,255,0.1);border-radius:8px;position:relative;overflow:hidden}
|
||||
.skeleton-box::after{content:'';position:absolute;top:0;left:0;right:0;bottom:0;background:linear-gradient(90deg,transparent 0%,rgba(100,220,255,0.15) 50%,transparent 100%);animation:shimmer 2s infinite linear}
|
||||
|
||||
/* Header skeleton */
|
||||
.skeleton-header{grid-column:1/4;height:60px;display:flex;align-items:center;padding:0 20px;gap:12px}
|
||||
.skeleton-logo{width:24px;height:24px;border-radius:4px;background:rgba(100,220,255,0.15)}
|
||||
.skeleton-title{flex:1;height:20px;max-width:300px;border-radius:4px}
|
||||
|
||||
/* Left panel (controls) */
|
||||
.skeleton-left{grid-column:1;grid-row:2;display:flex;flex-direction:column;gap:20px}
|
||||
.skeleton-panel{padding:18px;display:flex;flex-direction:column;gap:12px}
|
||||
.skeleton-panel-header{height:14px;width:60%;border-radius:3px;background:rgba(100,220,255,0.2);margin-bottom:8px}
|
||||
.skeleton-row{height:28px;border-radius:4px;background:rgba(100,220,255,0.05)}
|
||||
.skeleton-row.tall{height:40px}
|
||||
.skeleton-row.short{height:20px;width:70%}
|
||||
|
||||
/* Center canvas */
|
||||
.skeleton-canvas{grid-column:2;grid-row:1/4;background:radial-gradient(circle at center,rgba(100,220,255,0.05) 0%,transparent 70%);border:1px solid rgba(100,220,255,0.08);border-radius:12px;position:relative}
|
||||
.skeleton-canvas::before{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:120px;height:120px;border:3px solid rgba(100,220,255,0.2);border-top-color:#64dcff;border-radius:50%;animation:spin 1.5s linear infinite}
|
||||
@keyframes spin{to{transform:translate(-50%,-50%) rotate(360deg)}}
|
||||
.skeleton-canvas-text{position:absolute;bottom:30px;left:50%;transform:translateX(-50%);font-size:11px;color:rgba(100,220,255,0.5);font-family:'JetBrains Mono',monospace;letter-spacing:1px}
|
||||
|
||||
/* Right panel (model) */
|
||||
.skeleton-right{grid-column:3;grid-row:2;display:flex;flex-direction:column;gap:20px}
|
||||
.skeleton-button{height:36px;border-radius:6px;background:rgba(100,220,255,0.08);border:1px solid rgba(100,220,255,0.15)}
|
||||
.skeleton-dropzone{height:80px;border:2px dashed rgba(100,220,255,0.15);border-radius:6px;background:rgba(100,220,255,0.02)}
|
||||
|
||||
/* Footer skeleton */
|
||||
.skeleton-footer{grid-column:1/4;height:100px;display:flex;gap:20px}
|
||||
.skeleton-footer-panel{flex:1;padding:18px}
|
||||
|
||||
/* Mobile responsive */
|
||||
@media(max-width:768px){
|
||||
.skeleton-container{grid-template-columns:1fr;grid-template-rows:auto auto 1fr auto;gap:12px;padding:12px}
|
||||
.skeleton-header{grid-column:1;height:50px}
|
||||
.skeleton-left{grid-column:1;grid-row:2}
|
||||
.skeleton-canvas{grid-column:1;grid-row:3;min-height:300px}
|
||||
.skeleton-right{grid-column:1;grid-row:4}
|
||||
.skeleton-footer{grid-column:1;grid-row:5;flex-direction:column;height:auto}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════
|
||||
QUICK START TUTORIAL
|
||||
═══════════════════════════════════════════════════════ -->
|
||||
<div class="tutorial-overlay" id="tutorial-overlay">
|
||||
<div class="tutorial-card">
|
||||
<div class="tutorial-title" id="tut-title">Welcome to Discord ID Bypass</div>
|
||||
<div class="tutorial-text" id="tut-text">Let's get you started in 3 simple steps</div>
|
||||
<div class="tutorial-step" id="tut-step"></div>
|
||||
<button class="tutorial-btn" id="tut-btn">Start</button>
|
||||
<div class="tutorial-skip" id="tut-skip">Skip tutorial</div>
|
||||
<div class="tutorial-progress" id="tut-progress"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════
|
||||
SKELETON LOADING OVERLAY
|
||||
═══════════════════════════════════════════════════════ -->
|
||||
<div class="skeleton-overlay" id="skeleton-overlay">
|
||||
<div class="skeleton-container">
|
||||
<!-- Header -->
|
||||
<div class="skeleton-header skeleton-box">
|
||||
<div class="skeleton-logo"></div>
|
||||
<div class="skeleton-title"></div>
|
||||
</div>
|
||||
|
||||
<!-- Left panels -->
|
||||
<div class="skeleton-left">
|
||||
<div class="skeleton-box skeleton-panel">
|
||||
<div class="skeleton-panel-header"></div>
|
||||
<div class="skeleton-row short"></div>
|
||||
<div class="skeleton-row short"></div>
|
||||
</div>
|
||||
<div class="skeleton-box skeleton-panel">
|
||||
<div class="skeleton-panel-header"></div>
|
||||
<div class="skeleton-row"></div>
|
||||
<div class="skeleton-row"></div>
|
||||
<div class="skeleton-row"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Center canvas -->
|
||||
<div class="skeleton-canvas skeleton-box">
|
||||
<div class="skeleton-canvas-text">INITIALIZING THREE.JS</div>
|
||||
</div>
|
||||
|
||||
<!-- Right panel -->
|
||||
<div class="skeleton-right">
|
||||
<div class="skeleton-box skeleton-panel">
|
||||
<div class="skeleton-panel-header"></div>
|
||||
<div class="skeleton-button"></div>
|
||||
<div class="skeleton-dropzone"></div>
|
||||
<div class="skeleton-row short"></div>
|
||||
<div class="skeleton-row short"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="skeleton-footer">
|
||||
<div class="skeleton-box skeleton-footer-panel">
|
||||
<div class="skeleton-panel-header"></div>
|
||||
<div class="skeleton-row"></div>
|
||||
<div class="skeleton-row"></div>
|
||||
</div>
|
||||
<div class="skeleton-box skeleton-footer-panel">
|
||||
<div class="skeleton-panel-header"></div>
|
||||
<div class="skeleton-row"></div>
|
||||
<div class="skeleton-row"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="canvas-container" style="width:100vw;height:100vh;position:relative;">
|
||||
<button class="hide-ui-btn" id="hide-ui-btn">Hide UI [H]</button>
|
||||
<div class="hud" id="hud">
|
||||
<button class="hide-ui-btn" id="hide-ui-btn">Hide UI [H]</button>
|
||||
<button class="phoneme-toggle" id="phoneme-toggle">Phonemes [P]</button>
|
||||
<div class="main-title"><span>☠</span> Discord ID Bypass Tool <span style="font-size:11px;opacity:0.5;margin-left:6px">by PromptPirate</span></div>
|
||||
|
||||
<div class="hp controller-status">
|
||||
@@ -125,11 +306,6 @@
|
||||
<div class="sub">Keyboard: Always Active</div>
|
||||
</div>
|
||||
|
||||
<div class="hp always-visible hide-ui-elements">
|
||||
<div class="ht">UI Element Visibility</div>
|
||||
<button class="cb" id="ui-hide">Hide UI</button>
|
||||
</div>
|
||||
|
||||
<div class="hp sensitivity-panel">
|
||||
<div class="ht">Sensitivity<span class="ht-toggle">−</span></div>
|
||||
<div class="sr"><span style="min-width:45px">Head</span><button class="sb" id="hs-d">−</button><span class="sv" id="hs-v">1.0</span><button class="sb" id="hs-u">+</button></div>
|
||||
@@ -142,6 +318,95 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hp lighting-panel">
|
||||
<div class="ht">Lighting<span class="ht-toggle">−</span></div>
|
||||
<div class="light-row">
|
||||
<span class="light-label">Key Light</span>
|
||||
<button class="light-toggle active" id="key-toggle">ON</button>
|
||||
<input type="color" class="light-color" id="key-color" value="#dce8ff" />
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:80px">Intensity</span>
|
||||
<input type="range" class="light-slider" id="key-intensity" min="0" max="3" step="0.1" value="1.4" />
|
||||
<span class="light-value" id="key-val">1.4</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:20px">X</span>
|
||||
<input type="range" class="light-slider" id="key-x" min="-10" max="10" step="0.5" value="3" />
|
||||
<span class="light-value" id="key-x-val">3</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:20px">Y</span>
|
||||
<input type="range" class="light-slider" id="key-y" min="-10" max="10" step="0.5" value="4" />
|
||||
<span class="light-value" id="key-y-val">4</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:20px">Z</span>
|
||||
<input type="range" class="light-slider" id="key-z" min="-10" max="10" step="0.5" value="5" />
|
||||
<span class="light-value" id="key-z-val">5</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label">Fill Light</span>
|
||||
<button class="light-toggle active" id="fill-toggle">ON</button>
|
||||
<input type="color" class="light-color" id="fill-color" value="#64dcff" />
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:80px">Intensity</span>
|
||||
<input type="range" class="light-slider" id="fill-intensity" min="0" max="2" step="0.1" value="0.4" />
|
||||
<span class="light-value" id="fill-val">0.4</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:20px">X</span>
|
||||
<input type="range" class="light-slider" id="fill-x" min="-10" max="10" step="0.5" value="-3" />
|
||||
<span class="light-value" id="fill-x-val">-3</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:20px">Y</span>
|
||||
<input type="range" class="light-slider" id="fill-y" min="-10" max="10" step="0.5" value="2" />
|
||||
<span class="light-value" id="fill-y-val">2</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:20px">Z</span>
|
||||
<input type="range" class="light-slider" id="fill-z" min="-10" max="10" step="0.5" value="2" />
|
||||
<span class="light-value" id="fill-z-val">2</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label">Rim Light</span>
|
||||
<button class="light-toggle active" id="rim-toggle">ON</button>
|
||||
<input type="color" class="light-color" id="rim-color" value="#a78bfa" />
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:80px">Intensity</span>
|
||||
<input type="range" class="light-slider" id="rim-intensity" min="0" max="2" step="0.1" value="0.5" />
|
||||
<span class="light-value" id="rim-val">0.5</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:20px">X</span>
|
||||
<input type="range" class="light-slider" id="rim-x" min="-10" max="10" step="0.5" value="0" />
|
||||
<span class="light-value" id="rim-x-val">0</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:20px">Y</span>
|
||||
<input type="range" class="light-slider" id="rim-y" min="-10" max="10" step="0.5" value="2" />
|
||||
<span class="light-value" id="rim-y-val">2</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:20px">Z</span>
|
||||
<input type="range" class="light-slider" id="rim-z" min="-10" max="10" step="0.5" value="-4" />
|
||||
<span class="light-value" id="rim-z-val">-4</span>
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label">Ambient</span>
|
||||
<button class="light-toggle active" id="ambient-toggle">ON</button>
|
||||
<input type="color" class="light-color" id="ambient-color" value="#506080" />
|
||||
</div>
|
||||
<div class="light-row">
|
||||
<span class="light-label" style="min-width:80px">Intensity</span>
|
||||
<input type="range" class="light-slider" id="ambient-intensity" min="0" max="2" step="0.1" value="0.8" />
|
||||
<span class="light-value" id="ambient-val">0.8</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hp model-panel" id="model-panel">
|
||||
<div class="ht">Model<span class="ht-toggle">−</span></div>
|
||||
<button class="lbtn" id="load-btn">Load Model File</button>
|
||||
@@ -214,18 +479,72 @@
|
||||
|
||||
<div class="hp kid-panel" id="kid-panel">
|
||||
<div class="ht">k-ID Bypass<span class="ht-toggle">−</span></div>
|
||||
<div style="font-size:10px;color:#707080;margin-bottom:6px">Generate bypass payload for Discord age verification</div>
|
||||
<label style="font-size:10px;color:#a0a0b0">Target Age:</label>
|
||||
<input type="number" class="kid-input" id="kid-age" value="25" min="18" max="99" />
|
||||
<button class="kid-btn" id="kid-generate">Generate Bypass Data</button>
|
||||
<button class="kid-btn" id="kid-test" style="opacity:0.7;font-size:10px;padding:5px 10px;margin-top:4px">Test Mode (No Encryption)</button>
|
||||
<div style="font-size:10px;color:#707080;margin-bottom:6px">Verify your Discord account as adult using QR code</div>
|
||||
|
||||
<div style="font-size:9px;color:#5a5a6a;margin-bottom:8px;line-height:1.4">
|
||||
1. Start Discord age verification<br>
|
||||
2. Choose "Face Scan" option<br>
|
||||
3. Scan/upload the QR code below
|
||||
</div>
|
||||
|
||||
<div style="display:flex;gap:6px;margin-bottom:8px">
|
||||
<button class="cb" id="mode-api" style="flex:1;font-size:9px;padding:4px;background:rgba(100,220,255,0.2);border-color:#64dcff">API Mode</button>
|
||||
<button class="cb" id="mode-standalone" style="flex:1;font-size:9px;padding:4px">Standalone</button>
|
||||
</div>
|
||||
<div style="font-size:8px;color:#5a5a6a;margin-bottom:6px" id="mode-desc">Using kibty.town API (fast, may be patched)</div>
|
||||
|
||||
<label style="font-size:10px;color:#a0a0b0">QR Code URL or Image:</label>
|
||||
<input type="text" class="kid-input" id="kid-qr-url" placeholder="https://... or drop QR image" style="margin-bottom:4px" />
|
||||
|
||||
<label class="kid-btn" style="cursor:pointer;text-align:center;margin-top:4px;opacity:0.8;font-size:10px;padding:6px">
|
||||
📷 Upload QR Image
|
||||
<input type="file" id="kid-qr-file" accept="image/*" style="display:none" />
|
||||
</label>
|
||||
|
||||
<button class="kid-btn" id="kid-verify" style="background:rgba(74,222,128,0.1);border-color:rgba(74,222,128,0.3);color:#4ade80">
|
||||
✓ Verify Account
|
||||
</button>
|
||||
|
||||
<div style="font-size:9px;color:#5a5a6a;margin-top:8px;line-height:1.4">
|
||||
Status: <span id="kid-status" style="color:#64dcff">Ready</span>
|
||||
</div>
|
||||
|
||||
<div class="kid-output" id="kid-output"></div>
|
||||
</div>
|
||||
|
||||
<div class="orbit-hint">Right-click drag to orbit · Scroll to zoom</div>
|
||||
|
||||
<!-- Phoneme Panel -->
|
||||
<div class="phoneme-panel" id="phoneme-panel">
|
||||
<div class="phoneme-grid">
|
||||
<button class="phoneme-btn" data-phoneme="a">A</button>
|
||||
<button class="phoneme-btn" data-phoneme="e">E</button>
|
||||
<button class="phoneme-btn" data-phoneme="i">I</button>
|
||||
<button class="phoneme-btn" data-phoneme="o">O</button>
|
||||
<button class="phoneme-btn" data-phoneme="u">U</button>
|
||||
<button class="phoneme-btn" data-phoneme="neutral">—</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Controls -->
|
||||
<div class="mobile-controls">
|
||||
<div class="joystick-container" id="joystick-head">
|
||||
<div class="joystick-label">HEAD</div>
|
||||
<div class="joystick-base">
|
||||
<div class="joystick-stick" id="joystick-head-stick"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mobile-btn-group">
|
||||
<div class="mobile-btn" id="mobile-mouth">MOUTH</div>
|
||||
<div class="mobile-btn" id="mobile-roll-l">ROLL L</div>
|
||||
<div class="mobile-btn" id="mobile-roll-r">ROLL R</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js"></script>
|
||||
<script src="kid-bypass-standalone.js"></script>
|
||||
<script src="kid-bypass.js"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
||||
@@ -234,10 +553,11 @@
|
||||
// CONFIG & STATE
|
||||
// ═══════════════════════════════════════════════════════
|
||||
var CFG={hS:1,mS:1,mRange:1.0,yawMax:80,pitchMax:50,rollMax:35,dz:0.12,sm:0.12,msm:0.15,jawAxis:'x',jawDir:1,jawAngle:0.4};
|
||||
var S={tY:0,tP:0,tR:0,tM:0,cY:0,cP:0,cR:0,cM:0,keys:{}};
|
||||
var A={head:null,neck:null,jaw:null,headI:null,neckI:null,jawI:null,morphMesh:null,morphIdx:-1};
|
||||
var S={tY:0,tP:0,tR:0,tM:0,cY:0,cP:0,cR:0,cM:0,keys:{},phoneme:'neutral',gyroEnabled:false};
|
||||
var A={head:null,neck:null,jaw:null,headI:null,neckI:null,jawI:null,morphMesh:null,morphIdx:-1,phonemeMorphs:{}};
|
||||
var loadedModel=null, vrmData=null, allBones=[];
|
||||
var orbitTarget=new THREE.Vector3(0,0.3,0),orbitTheta=0,orbitPhi=0.15,orbitDist=3.5,isDrag=false,lastM={x:0,y:0};
|
||||
var mobileJoystick={active:false,startX:0,startY:0,currentX:0,currentY:0};
|
||||
|
||||
function $(id){return document.getElementById(id)}
|
||||
function showErr(m){$('err-box').textContent=m;$('err-box').style.display='block';$('ok-box').style.display='none'}
|
||||
@@ -262,6 +582,7 @@ var kl=new THREE.DirectionalLight(0xdce8ff,1.4);kl.position.set(3,4,5);kl.castSh
|
||||
var fl=new THREE.DirectionalLight(0x64dcff,0.4);fl.position.set(-3,2,2);scene.add(fl);
|
||||
var rl=new THREE.DirectionalLight(0xa78bfa,0.5);rl.position.set(0,2,-4);scene.add(rl);
|
||||
scene.add(new THREE.PointLight(0x64dcff,0.3,10).translateY(-2).translateZ(2));
|
||||
var ambientLight=scene.children.find(function(c){return c.isAmbientLight});
|
||||
var gnd=new THREE.Mesh(new THREE.PlaneGeometry(30,30),new THREE.MeshStandardMaterial({color:0x0a0a12,roughness:0.95}));
|
||||
gnd.rotation.x=-Math.PI/2;gnd.position.y=-3;gnd.receiveShadow=true;scene.add(gnd);
|
||||
|
||||
@@ -534,7 +855,7 @@ function loadFBX(url,name){
|
||||
function prepareScene(obj,fileName){
|
||||
if(loadedModel) scene.remove(loadedModel);
|
||||
A.head=A.neck=A.jaw=null;A.headI=A.neckI=A.jawI=null;
|
||||
A.morphMesh=null;A.morphIdx=-1;allBones=[];vrmData=null;
|
||||
A.morphMesh=null;A.morphIdx=-1;A.phonemeMorphs={};allBones=[];vrmData=null;
|
||||
|
||||
loadedModel=obj;
|
||||
|
||||
@@ -634,6 +955,30 @@ function prepareScene(obj,fileName){
|
||||
var b=activeRow.querySelector('.morph-map');if(b){b.classList.add('mapped');b.textContent='✓ Mapped'}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-detect phoneme morphs (A, E, I, O, U)
|
||||
var phonemePatterns={
|
||||
a: [/\baa?\b/i, /viseme.*aa/i, /mouth.*a$/i],
|
||||
e: [/\bee?\b/i, /viseme.*ee/i, /mouth.*e$/i],
|
||||
i: [/\bii?\b/i, /viseme.*ii/i, /mouth.*i$/i],
|
||||
o: [/\boo?\b/i, /viseme.*oh/i, /mouth.*o$/i],
|
||||
u: [/\buu?\b/i, /viseme.*uu/i, /mouth.*u$/i]
|
||||
};
|
||||
for(var ph in phonemePatterns){
|
||||
for(var i=0;i<allMorphs.length;i++){
|
||||
for(var p=0;p<phonemePatterns[ph].length;p++){
|
||||
if(phonemePatterns[ph][p].test(allMorphs[i].name)){
|
||||
A.phonemeMorphs[ph]={mesh:allMorphs[i].mesh,idx:allMorphs[i].idx};
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(A.phonemeMorphs[ph]) break;
|
||||
}
|
||||
}
|
||||
if(Object.keys(A.phonemeMorphs).length>0){
|
||||
$('phoneme-toggle').style.display='block';
|
||||
console.log('[Phoneme] Auto-detected:',Object.keys(A.phonemeMorphs));
|
||||
}
|
||||
} else {
|
||||
$('morph-section').style.display='none';
|
||||
$('morph-tester').style.display='none';
|
||||
@@ -956,16 +1301,6 @@ $('cam-reset').onclick=function(){
|
||||
else animCam(new THREE.Vector3(0,0.3,0),3.5);
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// UI HIDE / SHOW
|
||||
// ═══════════════════════════════════════════════════════
|
||||
$('ui-hide').onclick=function(){
|
||||
const elements=document.querySelectorAll('.hp:not(.always-visible)');
|
||||
const isHidden = [...elements].every(el => el.classList.contains('hidden'));
|
||||
elements.forEach(el => {el.classList.toggle('hidden')});
|
||||
$('ui-hide').textContent = isHidden ? 'Hide UI' : 'Show UI';
|
||||
};
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// GAMEPAD
|
||||
// ═══════════════════════════════════════════════════════
|
||||
@@ -1057,6 +1392,12 @@ function applyToModel(){
|
||||
if(A.morphMesh&&A.morphIdx>=0){
|
||||
A.morphMesh.morphTargetInfluences[A.morphIdx]=S.cM*CFG.mRange;
|
||||
}
|
||||
|
||||
// Apply phoneme morphs
|
||||
if(S.phoneme!=='neutral'&&A.phonemeMorphs[S.phoneme]){
|
||||
var pm=A.phonemeMorphs[S.phoneme];
|
||||
pm.mesh.morphTargetInfluences[pm.idx]=0.8;
|
||||
}
|
||||
}
|
||||
|
||||
function updateHUD(){
|
||||
@@ -1157,27 +1498,392 @@ if(innerWidth<=768){
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// k-ID BYPASS
|
||||
// k-ID BYPASS - Working Implementation with Mode Toggle
|
||||
// ═══════════════════════════════════════════════════════
|
||||
$('kid-generate').onclick=async function(){
|
||||
var age=parseInt($('kid-age').value)||25;
|
||||
var out=$('kid-output');
|
||||
out.textContent='Generating...';out.style.display='block';
|
||||
try{
|
||||
var result=await KIDBypass.intercept(age);
|
||||
out.textContent=JSON.stringify(result,null,2);
|
||||
}catch(err){
|
||||
out.textContent='Error: '+err.message;
|
||||
(function(){
|
||||
var qrUrlInput = $('kid-qr-url');
|
||||
var qrFileInput = $('kid-qr-file');
|
||||
var verifyBtn = $('kid-verify');
|
||||
var statusSpan = $('kid-status');
|
||||
var outputDiv = $('kid-output');
|
||||
var modeApiBtn = $('mode-api');
|
||||
var modeStandaloneBtn = $('mode-standalone');
|
||||
var modeDesc = $('mode-desc');
|
||||
|
||||
// Mode toggle handlers
|
||||
modeApiBtn.addEventListener('click', function(){
|
||||
KIDBypass.setMode('api');
|
||||
modeApiBtn.style.background = 'rgba(100,220,255,0.2)';
|
||||
modeApiBtn.style.borderColor = '#64dcff';
|
||||
modeStandaloneBtn.style.background = '';
|
||||
modeStandaloneBtn.style.borderColor = '';
|
||||
modeDesc.textContent = 'Using kibty.town API (fast, may be patched)';
|
||||
statusSpan.textContent = 'Ready (API Mode)';
|
||||
statusSpan.style.color = '#64dcff';
|
||||
});
|
||||
|
||||
modeStandaloneBtn.addEventListener('click', function(){
|
||||
KIDBypass.setMode('standalone');
|
||||
modeStandaloneBtn.style.background = 'rgba(100,220,255,0.2)';
|
||||
modeStandaloneBtn.style.borderColor = '#64dcff';
|
||||
modeApiBtn.style.background = '';
|
||||
modeApiBtn.style.borderColor = '';
|
||||
modeDesc.textContent = 'Direct verification (slower, 100% reliable)';
|
||||
statusSpan.textContent = 'Ready (Standalone Mode)';
|
||||
statusSpan.style.color = '#4ade80';
|
||||
});
|
||||
|
||||
// Drag & drop for QR image
|
||||
qrUrlInput.addEventListener('dragover', function(e){
|
||||
e.preventDefault();
|
||||
this.style.borderColor = 'rgba(100,220,255,0.5)';
|
||||
});
|
||||
|
||||
qrUrlInput.addEventListener('dragleave', function(e){
|
||||
this.style.borderColor = '';
|
||||
});
|
||||
|
||||
qrUrlInput.addEventListener('drop', function(e){
|
||||
e.preventDefault();
|
||||
this.style.borderColor = '';
|
||||
var file = e.dataTransfer.files[0];
|
||||
if(file && file.type.startsWith('image/')){
|
||||
handleQRImage(file);
|
||||
}
|
||||
});
|
||||
|
||||
// File input handler
|
||||
qrFileInput.addEventListener('change', function(e){
|
||||
var file = e.target.files[0];
|
||||
if(file){
|
||||
handleQRImage(file);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle QR image upload
|
||||
async function handleQRImage(file){
|
||||
statusSpan.textContent = 'Scanning QR code...';
|
||||
statusSpan.style.color = '#facc15';
|
||||
outputDiv.style.display = 'none';
|
||||
|
||||
try{
|
||||
var qrUrl = await KIDBypass.verifyFromImage(file);
|
||||
qrUrlInput.value = qrUrl;
|
||||
statusSpan.textContent = 'QR code detected!';
|
||||
statusSpan.style.color = '#4ade80';
|
||||
} catch(err){
|
||||
statusSpan.textContent = 'Failed: ' + err.message;
|
||||
statusSpan.style.color = '#f87171';
|
||||
outputDiv.textContent = 'Error: ' + err.message;
|
||||
outputDiv.style.display = 'block';
|
||||
}
|
||||
}
|
||||
};
|
||||
$('kid-test').onclick=function(){
|
||||
var age=parseInt($('kid-age').value)||25;
|
||||
var out=$('kid-output');
|
||||
out.textContent=JSON.stringify(KIDBypass.test(age),null,2);
|
||||
out.style.display='block';
|
||||
};
|
||||
|
||||
// Verify button handler
|
||||
verifyBtn.addEventListener('click', async function(){
|
||||
var qrUrl = qrUrlInput.value.trim();
|
||||
|
||||
if(!qrUrl){
|
||||
statusSpan.textContent = 'Please enter QR code URL';
|
||||
statusSpan.style.color = '#f87171';
|
||||
return;
|
||||
}
|
||||
|
||||
if(KIDBypass.isVerifying()){
|
||||
statusSpan.textContent = 'Verification in progress...';
|
||||
statusSpan.style.color = '#facc15';
|
||||
return;
|
||||
}
|
||||
|
||||
statusSpan.textContent = 'Verifying...';
|
||||
statusSpan.style.color = '#facc15';
|
||||
outputDiv.style.display = 'none';
|
||||
verifyBtn.disabled = true;
|
||||
verifyBtn.style.opacity = '0.5';
|
||||
|
||||
try{
|
||||
var result = await KIDBypass.verify(qrUrl, function(progress){
|
||||
statusSpan.textContent = progress;
|
||||
});
|
||||
|
||||
statusSpan.textContent = '✓ Verified successfully!';
|
||||
statusSpan.style.color = '#4ade80';
|
||||
|
||||
outputDiv.textContent = 'Success! Your account has been verified as adult.\n\nGo back to Discord to continue.';
|
||||
outputDiv.style.display = 'block';
|
||||
outputDiv.style.color = '#4ade80';
|
||||
|
||||
// Clear input after success
|
||||
setTimeout(function(){
|
||||
qrUrlInput.value = '';
|
||||
}, 2000);
|
||||
|
||||
} catch(err){
|
||||
statusSpan.textContent = 'Verification failed';
|
||||
statusSpan.style.color = '#f87171';
|
||||
|
||||
outputDiv.textContent = 'Error: ' + err.message + '\n\nMake sure:\n1. QR code URL is correct\n2. You\'re using the QR from Discord verification page\n3. Try switching to ' + (KIDBypass.getMode() === 'api' ? 'Standalone' : 'API') + ' mode';
|
||||
outputDiv.style.display = 'block';
|
||||
outputDiv.style.color = '#f87171';
|
||||
} finally {
|
||||
verifyBtn.disabled = false;
|
||||
verifyBtn.style.opacity = '1';
|
||||
}
|
||||
});
|
||||
|
||||
console.log('[k-ID Bypass] Initialized. Mode:', KIDBypass.getMode(), '| API:', KIDBypass.getEndpoint());
|
||||
})();
|
||||
|
||||
console.log('[HC] Initialized. Three.js r'+THREE.REVISION);
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// LIGHTING CONTROLS
|
||||
// ═══════════════════════════════════════════════════════
|
||||
(function(){
|
||||
function updateLightColor(light,colorHex){light.color.setStyle(colorHex)}
|
||||
function updateLightIntensity(light,val){light.intensity=parseFloat(val)}
|
||||
function updateLightPos(light,x,y,z){light.position.set(x,y,z)}
|
||||
|
||||
// Key Light
|
||||
$('key-intensity').oninput=function(){updateLightIntensity(kl,this.value);$('key-val').textContent=this.value};
|
||||
$('key-color').oninput=function(){updateLightColor(kl,this.value)};
|
||||
$('key-x').oninput=function(){kl.position.x=parseFloat(this.value);$('key-x-val').textContent=this.value};
|
||||
$('key-y').oninput=function(){kl.position.y=parseFloat(this.value);$('key-y-val').textContent=this.value};
|
||||
$('key-z').oninput=function(){kl.position.z=parseFloat(this.value);$('key-z-val').textContent=this.value};
|
||||
$('key-toggle').onclick=function(){
|
||||
kl.visible=!kl.visible;
|
||||
this.classList.toggle('active');
|
||||
this.textContent=kl.visible?'ON':'OFF';
|
||||
};
|
||||
|
||||
// Fill Light
|
||||
$('fill-intensity').oninput=function(){updateLightIntensity(fl,this.value);$('fill-val').textContent=this.value};
|
||||
$('fill-color').oninput=function(){updateLightColor(fl,this.value)};
|
||||
$('fill-x').oninput=function(){fl.position.x=parseFloat(this.value);$('fill-x-val').textContent=this.value};
|
||||
$('fill-y').oninput=function(){fl.position.y=parseFloat(this.value);$('fill-y-val').textContent=this.value};
|
||||
$('fill-z').oninput=function(){fl.position.z=parseFloat(this.value);$('fill-z-val').textContent=this.value};
|
||||
$('fill-toggle').onclick=function(){
|
||||
fl.visible=!fl.visible;
|
||||
this.classList.toggle('active');
|
||||
this.textContent=fl.visible?'ON':'OFF';
|
||||
};
|
||||
|
||||
// Rim Light
|
||||
$('rim-intensity').oninput=function(){updateLightIntensity(rl,this.value);$('rim-val').textContent=this.value};
|
||||
$('rim-color').oninput=function(){updateLightColor(rl,this.value)};
|
||||
$('rim-x').oninput=function(){rl.position.x=parseFloat(this.value);$('rim-x-val').textContent=this.value};
|
||||
$('rim-y').oninput=function(){rl.position.y=parseFloat(this.value);$('rim-y-val').textContent=this.value};
|
||||
$('rim-z').oninput=function(){rl.position.z=parseFloat(this.value);$('rim-z-val').textContent=this.value};
|
||||
$('rim-toggle').onclick=function(){
|
||||
rl.visible=!rl.visible;
|
||||
this.classList.toggle('active');
|
||||
this.textContent=rl.visible?'ON':'OFF';
|
||||
};
|
||||
|
||||
// Ambient Light
|
||||
$('ambient-intensity').oninput=function(){updateLightIntensity(ambientLight,this.value);$('ambient-val').textContent=this.value};
|
||||
$('ambient-color').oninput=function(){updateLightColor(ambientLight,this.value)};
|
||||
$('ambient-toggle').onclick=function(){
|
||||
ambientLight.visible=!ambientLight.visible;
|
||||
this.classList.toggle('active');
|
||||
this.textContent=ambientLight.visible?'ON':'OFF';
|
||||
};
|
||||
})();
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// QUICK START TUTORIAL
|
||||
// ═══════════════════════════════════════════════════════
|
||||
(function(){
|
||||
var steps=[
|
||||
{title:'Welcome!',text:'This tool lets you control a 3D avatar to bypass Discord age verification',step:'Step 1: Load a model using the panel on the right →'},
|
||||
{title:'Adjust Lighting',text:'Use the Lighting panel to add proper shadows on the face for better verification success',step:'Step 2: Adjust light position (X,Y,Z) and intensity to create natural shadows'},
|
||||
{title:'Control Your Avatar',text:'Use WASD for head movement, Space for mouth opening',step:'Step 3: Test controls and adjust sensitivity'},
|
||||
{title:'Ready to Go!',text:'When ready, use OBS Virtual Camera to capture this window',step:'Step 4: Open Discord and start verification'}
|
||||
];
|
||||
var current=0;
|
||||
var overlay=$('tutorial-overlay');
|
||||
var hasSeenTutorial=localStorage.getItem('tutorial_seen');
|
||||
|
||||
function showStep(i){
|
||||
current=i;
|
||||
$('tut-title').textContent=steps[i].title;
|
||||
$('tut-text').textContent=steps[i].text;
|
||||
$('tut-step').textContent=steps[i].step;
|
||||
$('tut-btn').textContent=i===steps.length-1?'Got it!':'Next';
|
||||
var prog=$('tut-progress');
|
||||
prog.innerHTML='';
|
||||
for(var j=0;j<steps.length;j++){
|
||||
var dot=document.createElement('div');
|
||||
dot.className='tutorial-dot'+(j===i?' active':'');
|
||||
prog.appendChild(dot);
|
||||
}
|
||||
}
|
||||
|
||||
$('tut-btn').onclick=function(){
|
||||
if(current<steps.length-1){showStep(current+1)}
|
||||
else{overlay.classList.remove('active');localStorage.setItem('tutorial_seen','1')}
|
||||
};
|
||||
$('tut-skip').onclick=function(){overlay.classList.remove('active');localStorage.setItem('tutorial_seen','1')};
|
||||
|
||||
if(!hasSeenTutorial){
|
||||
setTimeout(function(){overlay.classList.add('active');showStep(0)},1000);
|
||||
}
|
||||
})();
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// PHONEME CONTROLS
|
||||
// ═══════════════════════════════════════════════════════
|
||||
$('phoneme-toggle').onclick=function(){
|
||||
var panel=$('phoneme-panel');
|
||||
panel.classList.toggle('visible');
|
||||
};
|
||||
document.querySelectorAll('.phoneme-btn').forEach(function(btn){
|
||||
btn.onclick=function(){
|
||||
document.querySelectorAll('.phoneme-btn').forEach(function(b){b.classList.remove('active')});
|
||||
this.classList.add('active');
|
||||
S.phoneme=this.getAttribute('data-phoneme');
|
||||
// Reset all phoneme morphs
|
||||
for(var ph in A.phonemeMorphs){
|
||||
A.phonemeMorphs[ph].mesh.morphTargetInfluences[A.phonemeMorphs[ph].idx]=0;
|
||||
}
|
||||
};
|
||||
});
|
||||
window.addEventListener('keydown',function(e){
|
||||
if(e.target.tagName==='INPUT'||e.target.tagName==='SELECT')return;
|
||||
if(e.code==='KeyP'){$('phoneme-toggle').click()}
|
||||
});
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// MOBILE VIRTUAL JOYSTICK
|
||||
// ═══════════════════════════════════════════════════════
|
||||
(function(){
|
||||
var joyHead=$('joystick-head');
|
||||
var joyStick=$('joystick-head-stick');
|
||||
var baseRect=null;
|
||||
|
||||
function startJoy(e){
|
||||
e.preventDefault();
|
||||
baseRect=joyHead.getBoundingClientRect();
|
||||
mobileJoystick.active=true;
|
||||
mobileJoystick.startX=baseRect.left+baseRect.width/2;
|
||||
mobileJoystick.startY=baseRect.top+baseRect.height/2;
|
||||
}
|
||||
function moveJoy(e){
|
||||
if(!mobileJoystick.active)return;
|
||||
e.preventDefault();
|
||||
var touch=e.touches?e.touches[0]:e;
|
||||
var dx=touch.clientX-mobileJoystick.startX;
|
||||
var dy=touch.clientY-mobileJoystick.startY;
|
||||
var dist=Math.sqrt(dx*dx+dy*dy);
|
||||
var maxDist=50;
|
||||
if(dist>maxDist){dx=dx/dist*maxDist;dy=dy/dist*maxDist}
|
||||
joyStick.style.transform='translate(calc(-50% + '+dx+'px), calc(-50% + '+dy+'px))';
|
||||
// Map to head rotation
|
||||
S.tY=(dx/maxDist)*CFG.yawMax;
|
||||
S.tP=(dy/maxDist)*CFG.pitchMax;
|
||||
}
|
||||
function endJoy(){
|
||||
mobileJoystick.active=false;
|
||||
joyStick.style.transform='translate(-50%,-50%)';
|
||||
S.tY=0;S.tP=0;
|
||||
}
|
||||
|
||||
joyHead.addEventListener('touchstart',startJoy);
|
||||
joyHead.addEventListener('mousedown',startJoy);
|
||||
document.addEventListener('touchmove',moveJoy);
|
||||
document.addEventListener('mousemove',moveJoy);
|
||||
document.addEventListener('touchend',endJoy);
|
||||
document.addEventListener('mouseup',endJoy);
|
||||
|
||||
// Mobile buttons
|
||||
$('mobile-mouth').addEventListener('touchstart',function(){this.classList.add('active');S.tM=1});
|
||||
$('mobile-mouth').addEventListener('touchend',function(){this.classList.remove('active');S.tM=0});
|
||||
$('mobile-roll-l').addEventListener('touchstart',function(){this.classList.add('active');S.tR=-CFG.rollMax});
|
||||
$('mobile-roll-l').addEventListener('touchend',function(){this.classList.remove('active');S.tR=0});
|
||||
$('mobile-roll-r').addEventListener('touchstart',function(){this.classList.add('active');S.tR=CFG.rollMax});
|
||||
$('mobile-roll-r').addEventListener('touchend',function(){this.classList.remove('active');S.tR=0});
|
||||
})();
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// GYROSCOPE SUPPORT
|
||||
// ═══════════════════════════════════════════════════════
|
||||
if(window.DeviceOrientationEvent){
|
||||
window.addEventListener('deviceorientation',function(e){
|
||||
if(!S.gyroEnabled)return;
|
||||
if(e.beta!==null&&e.gamma!==null){
|
||||
// Beta: front-back tilt (-180 to 180), Gamma: left-right tilt (-90 to 90)
|
||||
S.tP=THREE.MathUtils.clamp((e.beta-90)/90*CFG.pitchMax,-CFG.pitchMax,CFG.pitchMax);
|
||||
S.tY=THREE.MathUtils.clamp(e.gamma/90*CFG.yawMax,-CFG.yawMax,CFG.yawMax);
|
||||
}
|
||||
});
|
||||
// Auto-enable gyro on mobile
|
||||
if(/Android|iPhone|iPad/i.test(navigator.userAgent)){
|
||||
setTimeout(function(){
|
||||
if(typeof DeviceOrientationEvent.requestPermission==='function'){
|
||||
DeviceOrientationEvent.requestPermission().then(function(state){
|
||||
if(state==='granted'){S.gyroEnabled=true;console.log('[Gyro] Enabled')}
|
||||
});
|
||||
} else {
|
||||
S.gyroEnabled=true;console.log('[Gyro] Enabled (no permission needed)');
|
||||
}
|
||||
},2000);
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// TOUCH GESTURES - Pinch Zoom & Two-Finger Rotate
|
||||
// ═══════════════════════════════════════════════════════
|
||||
(function(){
|
||||
var lastDist=0,lastAngle=0;
|
||||
ren.domElement.addEventListener('touchstart',function(e){
|
||||
if(e.touches.length===2){
|
||||
var dx=e.touches[1].clientX-e.touches[0].clientX;
|
||||
var dy=e.touches[1].clientY-e.touches[0].clientY;
|
||||
lastDist=Math.sqrt(dx*dx+dy*dy);
|
||||
lastAngle=Math.atan2(dy,dx);
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
ren.domElement.addEventListener('touchmove',function(e){
|
||||
if(e.touches.length===2){
|
||||
var dx=e.touches[1].clientX-e.touches[0].clientX;
|
||||
var dy=e.touches[1].clientY-e.touches[0].clientY;
|
||||
var dist=Math.sqrt(dx*dx+dy*dy);
|
||||
var angle=Math.atan2(dy,dx);
|
||||
// Pinch zoom
|
||||
if(lastDist>0){
|
||||
var scale=dist/lastDist;
|
||||
orbitDist=Math.max(0.3,Math.min(15,orbitDist/scale));
|
||||
}
|
||||
// Two-finger rotate
|
||||
if(lastAngle!==0){
|
||||
var deltaAngle=angle-lastAngle;
|
||||
orbitTheta-=deltaAngle;
|
||||
}
|
||||
lastDist=dist;
|
||||
lastAngle=angle;
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
ren.domElement.addEventListener('touchend',function(){lastDist=0;lastAngle=0});
|
||||
})();
|
||||
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// SKELETON LOADING CONTROLLER
|
||||
// ═══════════════════════════════════════════════════════
|
||||
(function(){
|
||||
var overlay = $('skeleton-overlay');
|
||||
|
||||
// Hide skeleton immediately after DOM ready
|
||||
setTimeout(function(){
|
||||
if(overlay && overlay.parentNode){
|
||||
overlay.classList.add('fade-out');
|
||||
setTimeout(function(){
|
||||
if(overlay.parentNode) overlay.remove();
|
||||
}, 400);
|
||||
}
|
||||
}, 500); // Hide after 0.5 second
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,569 @@
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// k-ID Bypass — Standalone Full Implementation
|
||||
// No external API dependency - runs 100% in browser
|
||||
// Based on: kibty.town standalone-verify.ts
|
||||
// ═══════════════════════════════════════════════════════
|
||||
|
||||
var KIDBypassStandalone = (function(){
|
||||
'use strict';
|
||||
|
||||
var BASE_URL = 'https://eu-west-1.faceassure.com';
|
||||
|
||||
// ─── Helper Functions ───
|
||||
function randomInt(min, max){
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
function randomFloat(min, max, decimals){
|
||||
decimals = decimals || 15;
|
||||
return parseFloat((Math.random() * (max - min) + min).toFixed(decimals));
|
||||
}
|
||||
|
||||
function randomChoice(arr){
|
||||
return arr[Math.floor(Math.random() * arr.length)];
|
||||
}
|
||||
|
||||
function generateId(id, sub, sessionId, delimiter){
|
||||
delimiter = delimiter || '|';
|
||||
var s = 0;
|
||||
var a = '' + id + delimiter + sub + delimiter + sessionId;
|
||||
for(var i = 0; i < a.length; i++){
|
||||
s = (s << 5) - s + a.charCodeAt(i);
|
||||
s &= s;
|
||||
}
|
||||
return '' + s;
|
||||
}
|
||||
|
||||
function generateUserAgent(){
|
||||
var agents = [
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.6 Mobile/15E148 Safari/604.1',
|
||||
'Mozilla/5.0 (Android 13; Mobile; rv:109.0) Gecko/109.0 Firefox/117.0',
|
||||
'Mozilla/5.0 (Linux; Android 13; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Mobile Safari/537.36'
|
||||
];
|
||||
return agents[Math.floor(Math.random() * agents.length)];
|
||||
}
|
||||
|
||||
function parseUserAgent(userAgent){
|
||||
var isIOS = /iPhone|iPad/.test(userAgent);
|
||||
var isAndroid = /Android/.test(userAgent);
|
||||
var isSafari = /Safari/.test(userAgent) && !/Chrome/.test(userAgent);
|
||||
var isChrome = /Chrome/.test(userAgent);
|
||||
var isFirefox = /Firefox/.test(userAgent);
|
||||
|
||||
return {
|
||||
browser: {
|
||||
name: isSafari ? 'Safari' : isChrome ? 'Chrome' : isFirefox ? 'Firefox' : 'Safari',
|
||||
version: isIOS ? '17.0' : '117.0'
|
||||
},
|
||||
device: {
|
||||
type: 'mobile',
|
||||
vendor: isIOS ? 'Apple' : 'Samsung',
|
||||
model: isIOS ? 'iPhone' : 'Galaxy'
|
||||
},
|
||||
os: {
|
||||
name: isIOS ? 'iOS' : isAndroid ? 'Android' : 'iOS',
|
||||
version: isIOS ? '17.0' : '13'
|
||||
},
|
||||
engine: { name: isSafari || isIOS ? 'WebKit' : 'Blink' },
|
||||
cpu: { architecture: '64' }
|
||||
};
|
||||
}
|
||||
|
||||
function getRandomLocation(){
|
||||
var locations = [
|
||||
{country: 'United States', state: 'California', timezone: 'America/Los_Angeles', lang: 'en-US,en;q=0.9'},
|
||||
{country: 'United States', state: 'New York', timezone: 'America/New_York', lang: 'en-US,en;q=0.9'},
|
||||
{country: 'Canada', state: 'Ontario', timezone: 'America/Toronto', lang: 'en-CA,en;q=0.9,fr;q=0.8'},
|
||||
{country: 'Australia', state: 'New South Wales', timezone: 'Australia/Sydney', lang: 'en-AU,en;q=0.9'},
|
||||
{country: 'Germany', state: 'Berlin', timezone: 'Europe/Berlin', lang: 'de-DE,de;q=0.9,en;q=0.8'}
|
||||
];
|
||||
return locations[Math.floor(Math.random() * locations.length)];
|
||||
}
|
||||
|
||||
function generateMediaMetadata(sub, sessionId){
|
||||
var randomHex = function(){
|
||||
return Array.from({length: 32}, function(){
|
||||
return Math.floor(Math.random() * 16).toString(16).toUpperCase();
|
||||
}).join('');
|
||||
};
|
||||
|
||||
var specs = [
|
||||
{width: 4032, height: 3024, frameRate: 60, zoom: 10, aspectRatio: 4032 / 3024},
|
||||
{width: 3840, height: 2160, frameRate: 60, zoom: 8, aspectRatio: 3840 / 2160},
|
||||
{width: 1920, height: 1080, frameRate: 120, zoom: 5, aspectRatio: 1920 / 1080},
|
||||
{width: 2560, height: 1440, frameRate: 60, zoom: 6, aspectRatio: 2560 / 1440}
|
||||
];
|
||||
|
||||
var spec = randomChoice(specs);
|
||||
var deviceId = generateId(randomHex(), sub, sessionId, '-');
|
||||
|
||||
return [
|
||||
{
|
||||
mediaKind: 'audioinput',
|
||||
mediaLabel: randomChoice(['', 'Built-in Microphone', 'Default']),
|
||||
mediaId: randomHex(),
|
||||
mediaCapabilities: {}
|
||||
},
|
||||
{
|
||||
mediaKind: 'videoinput',
|
||||
mediaLabel: 'Front Camera',
|
||||
mediaId: deviceId,
|
||||
mediaCapabilities: {
|
||||
aspectRatio: {max: spec.aspectRatio, min: randomFloat(0.0003, 0.001, 15)},
|
||||
backgroundBlur: [false],
|
||||
deviceId: deviceId,
|
||||
facingMode: ['user'],
|
||||
focusDistance: {min: randomFloat(0.1, 0.3)},
|
||||
frameRate: {max: spec.frameRate, min: 1},
|
||||
groupId: randomHex(),
|
||||
height: {max: spec.height, min: 1},
|
||||
powerEfficient: [false, true],
|
||||
whiteBalanceMode: randomChoice([
|
||||
['manual', 'continuous'],
|
||||
['auto', 'manual'],
|
||||
['continuous']
|
||||
]),
|
||||
width: {max: spec.width, min: 1},
|
||||
zoom: {max: spec.zoom, min: 1}
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
var AMAP_MAP = {
|
||||
0: [0, 2], 1: [2, 4], 2: [4, 8], 3: [8, 13], 4: [13, 18], 5: [18, 21],
|
||||
6: [21, 25], 7: [25, 28], 8: [28, 32], 9: [32, 36], 10: [36, 40],
|
||||
11: [40, 45], 12: [45, 50], 13: [50, 60], 14: [60, 70], 15: [70, 120]
|
||||
};
|
||||
|
||||
function amap(e){
|
||||
var n = AMAP_MAP[~~e];
|
||||
var r = e % 1;
|
||||
return n[0] + r * (n[1] - n[0]);
|
||||
}
|
||||
|
||||
function removeOutliersWithZscore(arr){
|
||||
var r = arr.reduce(function(e, t){return e + t}, 0) / arr.length;
|
||||
var a = arr.reduce(function(e, t){return e + Math.pow(t - r, 2)}, 0) / arr.length;
|
||||
var s = Math.sqrt(a);
|
||||
return arr.filter(function(e){return Math.abs((e - r) / s) <= 1});
|
||||
}
|
||||
|
||||
function calculateSpeedAndIntervals(measurements, timestamps){
|
||||
var intervals = [];
|
||||
var speeds = [];
|
||||
for(var i = 1; i < measurements.length; i++){
|
||||
var distance = Math.abs(measurements[i] - measurements[i - 1]);
|
||||
var timeInterval = (timestamps[i] - timestamps[i - 1]) / 1000;
|
||||
intervals.push(timeInterval);
|
||||
speeds.push(timeInterval > 0 ? distance / timeInterval : 0);
|
||||
}
|
||||
return {intervals: intervals, speeds: speeds};
|
||||
}
|
||||
|
||||
async function encryptPayload(nonce, payload){
|
||||
var getKey = async function(nonce, timestamp, transactionId){
|
||||
var data = nonce + timestamp + transactionId;
|
||||
var dataEncoded = new TextEncoder().encode(data);
|
||||
var key = await crypto.subtle.importKey('raw', dataEncoded, {name: 'HKDF'}, false, ['deriveBits']);
|
||||
var derived = await crypto.subtle.deriveBits(
|
||||
{name: 'HKDF', hash: 'SHA-256', salt: new Uint8Array(0), info: new TextEncoder().encode('payload-encryption')},
|
||||
key, 32 * 8
|
||||
);
|
||||
return await crypto.subtle.importKey('raw', derived, {name: 'AES-GCM'}, false, ['encrypt']);
|
||||
};
|
||||
|
||||
var timestamp = new Date().toISOString();
|
||||
var key = await getKey(nonce, timestamp, payload.transaction_id);
|
||||
var iv = crypto.getRandomValues(new Uint8Array(12));
|
||||
var encryptedBuffer = await crypto.subtle.encrypt(
|
||||
{name: 'AES-GCM', iv: iv},
|
||||
key,
|
||||
new TextEncoder().encode(JSON.stringify(payload))
|
||||
);
|
||||
|
||||
var rawBuffer = new Uint8Array(encryptedBuffer);
|
||||
var encryptedPayloadBuf = rawBuffer.subarray(0, rawBuffer.length - 16);
|
||||
var authTagBuf = rawBuffer.subarray(rawBuffer.length - 16);
|
||||
|
||||
return {
|
||||
encrypted_payload: btoa(String.fromCharCode.apply(null, encryptedPayloadBuf)),
|
||||
iv: btoa(String.fromCharCode.apply(null, iv)),
|
||||
auth_tag: btoa(String.fromCharCode.apply(null, authTagBuf)),
|
||||
timestamp: timestamp
|
||||
};
|
||||
}
|
||||
|
||||
function generateBoundingBox(){
|
||||
var topLeft = [randomFloat(140, 160), randomFloat(250, 270)];
|
||||
var width = randomFloat(170, 190);
|
||||
var height = randomFloat(220, 240);
|
||||
return {
|
||||
topLeft: topLeft,
|
||||
bottomRight: [topLeft[0] + width, topLeft[1] + height],
|
||||
width: width,
|
||||
height: height
|
||||
};
|
||||
}
|
||||
|
||||
function generateTimeline(maxTime){
|
||||
var entries = [];
|
||||
var lastTime = randomInt(1000, 3000);
|
||||
for(var i = 0; i < randomInt(1, 3); i++){
|
||||
var end = lastTime + randomInt(300, 1500);
|
||||
if(end < maxTime){
|
||||
entries.push([lastTime, end]);
|
||||
lastTime = end + randomInt(1000, 3000);
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
function generateStateTimelines(completionTime){
|
||||
var states = ['TIME_UNTIL_CLICK_START', 'GET_READY', 'NO_FACE', 'LOOK_STRAIGHT', 'TURN_LEFT', 'CENTRE_FACE', 'KEEP_YOUR_MOUTH_OPEN', 'CLOSE_YOUR_MOUTH', 'SLOWLY_COME_CLOSER_TO_THE_CAMERA', 'SLOWLY_DISTANCE_YOURSELF_FROM_THE_CAMERA', 'TOO_DARK'];
|
||||
var noState = ['VIDEO_PROCESSING', 'STAY_STILL', 'TURN_RIGHT', 'ALIGN_YOUR_FACE_WITH_THE_CAMERA_UP', 'ALIGN_YOUR_FACE_WITH_THE_CAMERA_DOWN', 'SLIGHTLY_TILT_YOUR_HEAD_LEFT', 'SLIGHTLY_TILT_YOUR_HEAD_RIGHT', 'OPEN_YOUR_MOUTH'];
|
||||
var timelines = {};
|
||||
states.forEach(function(state){timelines[state] = generateTimeline(completionTime)});
|
||||
noState.forEach(function(state){timelines[state] = []});
|
||||
return timelines;
|
||||
}
|
||||
|
||||
// ─── Main Verification Function ───
|
||||
async function verify(qrCodeUrlStr, onProgress){
|
||||
onProgress = onProgress || function(){};
|
||||
|
||||
var userAgent = generateUserAgent();
|
||||
var parsedUserAgent = parseUserAgent(userAgent);
|
||||
var location = getRandomLocation();
|
||||
|
||||
var commonHeaders = {
|
||||
'User-Agent': userAgent,
|
||||
'accept': '*/*',
|
||||
'accept-language': location.lang,
|
||||
'access-control-allow-origin': '*',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-site': 'cross-site'
|
||||
};
|
||||
|
||||
onProgress('Parsing QR code...');
|
||||
var qrCodeUrl = new URL(qrCodeUrlStr);
|
||||
var shortlinkId = qrCodeUrl.searchParams.get('sl');
|
||||
if(!shortlinkId) throw new Error('Shortlink ID not found in QR code URL');
|
||||
|
||||
onProgress('Fetching shortlink...');
|
||||
var res = await fetch(BASE_URL + '/shortlinks/' + shortlinkId, {headers: commonHeaders});
|
||||
if(!res.ok) throw new Error('Failed to get shortlink (status=' + res.status + ')');
|
||||
|
||||
var data = await res.json();
|
||||
var originalUrl = new URL(data.Item.original_url.S.replace('#', ''));
|
||||
var token = originalUrl.searchParams.get('token');
|
||||
if(!token) throw new Error('Token not found in original URL');
|
||||
|
||||
var parts = token.split('.');
|
||||
if(parts.length !== 3) throw new Error('Token is an invalid JWT');
|
||||
var jwtPayload = JSON.parse(atob(parts[1].replace(/-/g, '+').replace(/_/g, '/')));
|
||||
|
||||
onProgress('Generating session...');
|
||||
var sessionRes = await fetch(BASE_URL + '/age-services/d-privately-age-services', {
|
||||
method: 'POST',
|
||||
headers: Object.assign({'Content-Type': 'application/json'}, commonHeaders),
|
||||
body: JSON.stringify({
|
||||
request_type: 'generate_new_session',
|
||||
transaction_id: jwtPayload.jti,
|
||||
api_key: null,
|
||||
api_secret: null,
|
||||
token: token,
|
||||
longURL: null,
|
||||
userAgent: userAgent
|
||||
})
|
||||
});
|
||||
|
||||
if(!sessionRes.ok) throw new Error('Failed to generate session (status=' + sessionRes.status + ')');
|
||||
var sessionData = await sessionRes.json();
|
||||
|
||||
onProgress('Building payload...');
|
||||
var baseAge = randomFloat(25.2, 26.0);
|
||||
var minAge = baseAge - randomFloat(0.1, 0.5);
|
||||
var maxAge = baseAge + randomFloat(0.1, 0.5);
|
||||
var averageAge = (minAge + maxAge) / 2;
|
||||
var currentTime = Date.now() / 1000;
|
||||
var initialAdjustmentTime = randomInt(200, 800);
|
||||
var completionTime = randomInt(8000, 15000);
|
||||
|
||||
var raws = Array.from({length: 10}, function(){return randomFloat(6.005, 7.007)});
|
||||
var primaryOutputs = removeOutliersWithZscore(raws.map(function(r){return amap(r)}));
|
||||
var outputs = removeOutliersWithZscore(primaryOutputs);
|
||||
|
||||
var gestureMeasurementTime = Date.now();
|
||||
var recordedMeasurements = Array.from({length: 5}, function(){return randomFloat(0.1, 0.8, 17)});
|
||||
var recordedTimestamps = [
|
||||
randomInt(500, Math.min(completionTime, 1000)) - gestureMeasurementTime,
|
||||
randomInt(700, Math.min(completionTime, 1000)) - gestureMeasurementTime,
|
||||
randomInt(1000, Math.min(completionTime, 1400)) - gestureMeasurementTime,
|
||||
randomInt(1400, Math.min(completionTime, 1600)) - gestureMeasurementTime,
|
||||
randomInt(1600, Math.min(completionTime, 1800)) - gestureMeasurementTime
|
||||
];
|
||||
var recordedData = calculateSpeedAndIntervals(recordedMeasurements, recordedTimestamps);
|
||||
|
||||
var failedMeasurements = Array.from({length: 5}, function(){return randomFloat(0.1, 0.8, 17)});
|
||||
var failedTimestamps = [
|
||||
randomInt(500, Math.min(completionTime, 1000)) - gestureMeasurementTime,
|
||||
randomInt(700, Math.min(completionTime, 1000)) - gestureMeasurementTime,
|
||||
randomInt(1000, Math.min(completionTime, 1400)) - gestureMeasurementTime,
|
||||
randomInt(1400, Math.min(completionTime, 1600)) - gestureMeasurementTime
|
||||
];
|
||||
var failedData = calculateSpeedAndIntervals(failedMeasurements, failedTimestamps);
|
||||
|
||||
var stateTimelines = generateStateTimelines(completionTime);
|
||||
var stateCompletionTimes = {};
|
||||
for(var key in stateTimelines){
|
||||
if(stateTimelines[key].length < 1) continue;
|
||||
var totalDuration = 0;
|
||||
for(var i = 0; i < stateTimelines[key].length; i++){
|
||||
totalDuration += stateTimelines[key][i][1] - stateTimelines[key][i][0];
|
||||
}
|
||||
stateCompletionTimes[key] = totalDuration;
|
||||
}
|
||||
|
||||
var mediaMetadata = generateMediaMetadata(jwtPayload.sub, sessionData.session_id);
|
||||
var ageCheckSession = generateId(
|
||||
mediaMetadata.find(function(m){return m.mediaKind === 'videoinput'}).mediaId,
|
||||
jwtPayload.sub,
|
||||
sessionData.session_id
|
||||
);
|
||||
|
||||
var laplacianBlurScores = Array.from({length: 300}, function(){return randomFloat(10, 300, 15)});
|
||||
|
||||
var payload = {
|
||||
request_type: 'complete_transaction',
|
||||
transaction_id: sessionData.transaction_id,
|
||||
api_key: sessionData.session_id,
|
||||
api_secret: sessionData.session_password,
|
||||
remote_pld: {},
|
||||
browser_response_data: {
|
||||
age: 'yes',
|
||||
age_confidence: 1,
|
||||
genuineness: Array.from({length: 5}, function(){return randomFloat(0.4, 0.98)}),
|
||||
product: 'age',
|
||||
modality: 'image',
|
||||
unverifiedPayload: {
|
||||
iss: 'https://api.privately.swiss',
|
||||
sub: jwtPayload.sub,
|
||||
aud: 'https://api.k-id.com',
|
||||
exp: jwtPayload.exp,
|
||||
nbf: jwtPayload.nbf,
|
||||
iat: jwtPayload.iat,
|
||||
jti: jwtPayload.jti,
|
||||
age: jwtPayload.age,
|
||||
liv: true,
|
||||
rlt: {minAge: minAge, maxAge: maxAge, score: 0, gate: 16},
|
||||
rsn: 'complete_transaction',
|
||||
rtf: 'interval',
|
||||
rtb: 'callback',
|
||||
vid: jwtPayload.vid,
|
||||
ver: 'v1.10.22',
|
||||
ufi: []
|
||||
},
|
||||
ageCheckSession: ageCheckSession,
|
||||
miscellaneous: {
|
||||
recordedOpennessStreak: recordedMeasurements,
|
||||
recordedSpeeds: recordedData.speeds,
|
||||
recordedIntervals: recordedData.intervals,
|
||||
failedOpennessReadings: [failedMeasurements],
|
||||
failedOpennessSpeeds: [failedData.speeds],
|
||||
failedOpennessIntervals: [failedData.intervals],
|
||||
numberOfGestureRetries: 1,
|
||||
antiSpoofConfidences: [],
|
||||
fp_scores: [],
|
||||
laplacian_blur_scores: laplacianBlurScores,
|
||||
laplacian_min_score: Math.min.apply(null, laplacianBlurScores),
|
||||
laplacian_max_score: Math.max.apply(null, laplacianBlurScores),
|
||||
laplacian_avg_score: laplacianBlurScores.reduce(function(a,b){return a+b},0) / laplacianBlurScores.length,
|
||||
glare_ratios: Array.from({length: 300}, function(){return 0}),
|
||||
allScreenDetectionDetails: {
|
||||
beforeClickingStart: {screenDetectionConfidence: [], screenFaceOverlap: [], screenBoundingBoxes: [], alternativeScore: []},
|
||||
positioning: {screenDetectionConfidence: Array.from({length: 2}, function(){return randomFloat(0.01, 0.03)}), screenFaceOverlap: [0, 0], screenBoundingBoxes: [[], []], alternativeScore: Array.from({length: 2}, function(){return randomFloat(0.2, 0.9)})},
|
||||
liveness: {screenDetectionConfidence: Array.from({length: 2}, function(){return randomFloat(0.01, 0.03)}), screenFaceOverlap: [0, 0], screenBoundingBoxes: [[], []], alternativeScore: Array.from({length: 2}, function(){return randomFloat(0.2, 0.9)})},
|
||||
distancing: {screenDetectionConfidence: Array.from({length: 2}, function(){return randomFloat(0.01, 0.03)}), screenFaceOverlap: [0, 0], screenBoundingBoxes: [Array.from({length: 2}, generateBoundingBox)], alternativeScore: Array.from({length: 2}, function(){return randomFloat(0.2, 0.9)})},
|
||||
closing: {screenDetectionConfidence: Array.from({length: 2}, function(){return randomFloat(0.01, 0.03)}), screenFaceOverlap: [0, 0], screenBoundingBoxes: [Array.from({length: 2}, generateBoundingBox)], alternativeScore: Array.from({length: 2}, function(){return randomFloat(0.2, 0.9)})},
|
||||
postChallenge: {screenDetectionConfidence: Array.from({length: 2}, function(){return randomFloat(0.01, 0.03)}), screenFaceOverlap: [0, 0], screenBoundingBoxes: [[], []], alternativeScore: Array.from({length: 2}, function(){return randomFloat(0.2, 0.9)})}
|
||||
},
|
||||
plScores: [],
|
||||
screenDetectionExecutionTimes: {
|
||||
beforeClickingStart: [],
|
||||
positioning: Array.from({length: 2}, function(){return randomFloat(5000, 6000)}),
|
||||
liveness: Array.from({length: 2}, function(){return randomFloat(4000, 5000)}),
|
||||
distancing: Array.from({length: 2}, function(){return randomFloat(3000, 4000)}),
|
||||
closing: Array.from({length: 2}, function(){return randomFloat(2000, 3000)}),
|
||||
postChallenge: Array.from({length: 2}, function(){return randomFloat(500, 1500)})
|
||||
},
|
||||
landmarkDetectionExecutionTimes: {
|
||||
beforeClickingStart: [],
|
||||
positioning: Array.from({length: 200}, function(){return randomFloat(50, 150)}),
|
||||
liveness: Array.from({length: 50}, function(){return randomFloat(50, 110)}),
|
||||
distancing: Array.from({length: 5}, function(){return randomFloat(50, 110)}),
|
||||
closing: Array.from({length: 20}, function(){return randomFloat(50, 110)}),
|
||||
postChallenge: Array.from({length: 7}, function(){return randomFloat(50, 110)})
|
||||
},
|
||||
screenAttackMeasure: 0,
|
||||
screenAttackBoundingBox: {},
|
||||
subclient: jwtPayload.sub,
|
||||
verificationID: jwtPayload.vid,
|
||||
version: 'v1.10.22',
|
||||
sdk_path: './face-capture-v1.10.22.js',
|
||||
model_version: 'v.2025.0',
|
||||
cropper_version: 'v.0.0.3',
|
||||
start_time_stamp: currentTime - (completionTime + initialAdjustmentTime + randomInt(2000, 5000)) / 1000,
|
||||
end_time_stamp: currentTime + randomFloat(0.1, 0.5),
|
||||
device_timezone: location.timezone,
|
||||
referring_page: 'https://d3ogqhtsivkon3.cloudfront.net/index-v1.10.22.html#/?token=' + token + '&shi=false&from_qr_scan=true',
|
||||
parent_page: 'https://d3ogqhtsivkon3.cloudfront.net/dynamic_index.html?sl=' + jwtPayload.jti + '®ion=eu-central-1',
|
||||
face_confidence_limit: 0.975,
|
||||
multipleFacesDetected: false,
|
||||
targetGate: 18,
|
||||
targetConfidence: 0.9,
|
||||
averageAge: averageAge,
|
||||
selecedLivenessStyle: 'open',
|
||||
selectedMediaLabel: 'Front Camera',
|
||||
rawImageWidth: 480,
|
||||
rawImageHeight: 640,
|
||||
boundingBoxesInPixels: Array.from({length: randomInt(5, 10)}, generateBoundingBox),
|
||||
latestReportedState: 'AGE_CHECK_COMPLETE',
|
||||
challengeType: 'distance-open',
|
||||
authenticationCharacteristics: {
|
||||
session_id: sessionData.session_id,
|
||||
session_password: sessionData.session_password,
|
||||
token: token
|
||||
},
|
||||
deviceCharacteristics: {
|
||||
deviceBrowserModel: userAgent,
|
||||
isMobile: parsedUserAgent.device.type === 'mobile',
|
||||
browserName: parsedUserAgent.browser.name.toLowerCase(),
|
||||
isDeviceBrowserCompatible: true,
|
||||
deviceConnectionSpeedKbps: randomFloat(20000, 500000),
|
||||
deviceRegion: {country: location.country, state: location.state},
|
||||
mediaMetadata: mediaMetadata,
|
||||
platformDetails: {
|
||||
name: parsedUserAgent.browser.name,
|
||||
version: parsedUserAgent.browser.version,
|
||||
layout: parsedUserAgent.engine.name,
|
||||
os: {
|
||||
architecture: parseInt(parsedUserAgent.cpu.architecture) || 64,
|
||||
family: parsedUserAgent.os.name,
|
||||
version: parsedUserAgent.os.version
|
||||
},
|
||||
description: parsedUserAgent.browser.name + ' ' + parsedUserAgent.browser.version + ' on ' + parsedUserAgent.device.vendor + ' ' + parsedUserAgent.device.model,
|
||||
product: parsedUserAgent.device.model,
|
||||
manufacturer: parsedUserAgent.device.vendor
|
||||
},
|
||||
userTriedLandscapeMode: 0,
|
||||
txFinishedInLandscapeMode: false
|
||||
},
|
||||
initializationCharacteristics: {
|
||||
cropperInitTime: randomInt(150, 250),
|
||||
coreInitTime: randomInt(800, 1000),
|
||||
pageLoadTime: randomInt(250, 350) + Number(Math.random().toFixed(randomInt(7, 13))),
|
||||
from_qr_scan: true,
|
||||
blendShapesAvailable: true
|
||||
},
|
||||
executionCharacteristics: {
|
||||
experimentSetup: {
|
||||
experimentType: 'passive-liveness-override',
|
||||
experimentProbability: 1,
|
||||
deviceCoverage: 'all',
|
||||
deviceInfo: {
|
||||
name: parsedUserAgent.browser.name,
|
||||
version: parsedUserAgent.browser.version,
|
||||
layout: parsedUserAgent.engine.name,
|
||||
os: {
|
||||
architecture: parseInt(parsedUserAgent.cpu.architecture) || 64,
|
||||
family: parsedUserAgent.os.name,
|
||||
version: parsedUserAgent.os.version
|
||||
},
|
||||
description: parsedUserAgent.browser.name + ' ' + parsedUserAgent.browser.version + ' on ' + parsedUserAgent.device.vendor + ' ' + parsedUserAgent.device.model,
|
||||
product: parsedUserAgent.device.model,
|
||||
manufacturer: parsedUserAgent.device.vendor
|
||||
},
|
||||
txMode: 'experiment',
|
||||
timestamp: Date.now() - completionTime - initialAdjustmentTime - randomInt(2000, 5000)
|
||||
},
|
||||
experimentConfigResult: {
|
||||
success: true,
|
||||
txMode: 'experiment',
|
||||
experimentType: 'passive-liveness-override'
|
||||
},
|
||||
isCameraPermissionGranted: true,
|
||||
completionTime: completionTime,
|
||||
deferredComputationStartedAt: currentTime - randomFloat(0.5, 2.0),
|
||||
instructionCompletionTime: completionTime + initialAdjustmentTime + randomInt(50, 200),
|
||||
initialAdjustmentTime: initialAdjustmentTime,
|
||||
completionState: 'COMPLETE',
|
||||
unfinishedInstructions: {
|
||||
NO_FACE: false, VIDEO_PROCESSING: false, STAY_STILL: false, LOOK_STRAIGHT: false,
|
||||
GET_READY: false, TURN_LEFT: false, TURN_RIGHT: false, ALIGN_YOUR_FACE_WITH_THE_CAMERA_UP: false,
|
||||
ALIGN_YOUR_FACE_WITH_THE_CAMERA_DOWN: false, SLIGHTLY_TILT_YOUR_HEAD_LEFT: false,
|
||||
SLIGHTLY_TILT_YOUR_HEAD_RIGHT: false, CENTRE_FACE: false, OPEN_YOUR_MOUTH: false,
|
||||
KEEP_YOUR_MOUTH_OPEN: false, CLOSE_YOUR_MOUTH: false, SLOWLY_COME_CLOSER_TO_THE_CAMERA: false,
|
||||
SLOWLY_DISTANCE_YOURSELF_FROM_THE_CAMERA: false, TOO_DARK: false
|
||||
},
|
||||
stateCompletionTimes: stateCompletionTimes,
|
||||
stateTimelines: stateTimelines,
|
||||
nonNeutralExpressionTimelines: {
|
||||
browDownLeft: {}, browDownRight: {}, mouthSmileLeft: {}, mouthSmileRight: {},
|
||||
mouthPucker: {}, mouthDimpleLeft: {}, mouthDimpleRight: {}, mouthPressLeft: {},
|
||||
mouthPressRight: {}, mouthShrugLower: {}, mouthShrugUpper: {}, eyeBlinkLeft: {},
|
||||
eyeBlinkRight: {}, mouthFrownLeft: {}, mouthFrownRight: {}
|
||||
},
|
||||
handAnalysis: {faceHandSizeComparisons: []},
|
||||
predictions: {
|
||||
outputs: outputs,
|
||||
primaryOutputs: primaryOutputs,
|
||||
raws: raws,
|
||||
secondaryOutputs: [],
|
||||
secondaryRaws: [],
|
||||
age: 'yes',
|
||||
horizontal_estimates: Array.from({length: 6}, function(){return randomFloat(3.1, 3.2)}),
|
||||
vertical_estimates: Array.from({length: 6}, function(){return randomFloat(-1.6, -1.5)}),
|
||||
horizontalratiotocenter_estimates: Array.from({length: 6}, function(){return randomFloat(1.01, 1.03)}),
|
||||
zy_estimates: Array.from({length: 6}, function(){return randomFloat(0.42, 0.44)}),
|
||||
driftfromcenterx_estimates: Array.from({length: 6}, function(){return randomFloat(0.005, 0.007)}),
|
||||
driftfromcentery_estimates: Array.from({length: 6}, function(){return randomFloat(-0.35, -0.37)}),
|
||||
xScaledShiftAmt: 11.5,
|
||||
yScaledShiftAmt: -2
|
||||
}
|
||||
},
|
||||
errorCharacteristics: {
|
||||
systemErrors: [],
|
||||
userErrors: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onProgress('Encrypting payload...');
|
||||
var encryptionData = await encryptPayload(sessionData.nonce, payload);
|
||||
payload = Object.assign(payload, encryptionData);
|
||||
|
||||
onProgress('Submitting verification...');
|
||||
var completeRes = await fetch(BASE_URL + '/age-services/d-privately-age-services', {
|
||||
method: 'POST',
|
||||
headers: Object.assign({'Content-Type': 'application/json'}, commonHeaders),
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if(!completeRes.ok){
|
||||
var errorText = await completeRes.text();
|
||||
throw new Error('Failed to complete transaction (status=' + completeRes.status + ', body=' + errorText + ')');
|
||||
}
|
||||
|
||||
onProgress('Verification complete!');
|
||||
return {success: true, transaction_id: payload.transaction_id};
|
||||
}
|
||||
|
||||
// ─── Public API ───
|
||||
return {
|
||||
verify: verify
|
||||
};
|
||||
})();
|
||||
+127
-231
@@ -1,256 +1,152 @@
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// k-ID Bypass — by kibty.town & Dziurwa14 & TheUnrealZaka
|
||||
// Modified by: Sofinco
|
||||
// Enhanced: Natural behavior simulation
|
||||
// k-ID Bypass — Working Implementation
|
||||
// Based on: kibty.town & Dziurwa14
|
||||
// Full verification via QR code scanning
|
||||
// ═══════════════════════════════════════════════════════
|
||||
|
||||
var KIDBypass = (function(){
|
||||
'use strict';
|
||||
|
||||
function randomInt(min,max){return Math.floor(Math.random()*(max-min+1))+min}
|
||||
function randomFloat(min,max){return Math.random()*(max-min)+min}
|
||||
function gaussianRandom(mean,std){var u=1-Math.random(),v=Math.random();return mean+std*Math.sqrt(-2*Math.log(u))*Math.cos(2*Math.PI*v)}
|
||||
var API_ENDPOINT = 'https://age-verifier.kibty.town/api/verify';
|
||||
var verificationInProgress = false;
|
||||
var useStandaloneMode = false; // Toggle between API and Standalone
|
||||
|
||||
// ─── HKDF-SHA256 Key Derivation ───
|
||||
async function deriveKey(nonce, timestamp, transactionId){
|
||||
var ikm = new TextEncoder().encode(nonce + timestamp + transactionId);
|
||||
var salt = new Uint8Array(32);
|
||||
var key = await crypto.subtle.importKey('raw', ikm, {name: 'HKDF'}, false, ['deriveBits']);
|
||||
var bits = await crypto.subtle.deriveBits(
|
||||
{name: 'HKDF', hash: 'SHA-256', salt: salt, info: new Uint8Array()},
|
||||
key, 256
|
||||
);
|
||||
return new Uint8Array(bits);
|
||||
}
|
||||
|
||||
// ─── AES-GCM Encryption ───
|
||||
async function encryptPayload(payload, nonce, timestamp, transactionId){
|
||||
var key = await deriveKey(nonce, timestamp, transactionId);
|
||||
var iv = crypto.getRandomValues(new Uint8Array(12));
|
||||
var cryptoKey = await crypto.subtle.importKey('raw', key, {name: 'AES-GCM'}, false, ['encrypt']);
|
||||
var encrypted = await crypto.subtle.encrypt(
|
||||
{name: 'AES-GCM', iv: iv, tagLength: 128},
|
||||
cryptoKey,
|
||||
new TextEncoder().encode(JSON.stringify(payload))
|
||||
);
|
||||
var ciphertext = new Uint8Array(encrypted.slice(0, -16));
|
||||
var authTag = new Uint8Array(encrypted.slice(-16));
|
||||
return {
|
||||
encrypted_payload: btoa(String.fromCharCode(...ciphertext)),
|
||||
auth_tag: btoa(String.fromCharCode(...authTag)),
|
||||
iv: btoa(String.fromCharCode(...iv)),
|
||||
timestamp: timestamp
|
||||
};
|
||||
}
|
||||
|
||||
// ─── Z-Score Filter ───
|
||||
function zFilter(arr, threshold){
|
||||
if(arr.length < 2) return arr;
|
||||
var mean = arr.reduce((a,b)=>a+b,0) / arr.length;
|
||||
var std = Math.sqrt(arr.reduce((a,b)=>a+Math.pow(b-mean,2),0) / arr.length);
|
||||
if(std === 0) return arr;
|
||||
return arr.filter(x => Math.abs((x - mean) / std) <= threshold);
|
||||
}
|
||||
|
||||
// ─── Age Predictions (Natural variance) ───
|
||||
function generatePredictions(targetAge){
|
||||
var raws = [];
|
||||
var baseAge = targetAge + gaussianRandom(0, 1.5);
|
||||
for(var i = 0; i < randomInt(10, 14); i++){
|
||||
var noise = gaussianRandom(0, 2.5);
|
||||
var drift = Math.sin(i * 0.5) * 1.2;
|
||||
raws.push(Math.max(18, Math.min(99, baseAge + noise + drift)));
|
||||
// ─── QR Code Scanner (jsQR integration) ───
|
||||
async function decodeQRFromImage(file){
|
||||
if(typeof jsQR === 'undefined'){
|
||||
throw new Error('QR scanner library not loaded');
|
||||
}
|
||||
var outputs = zFilter(raws, 2.0);
|
||||
var primary = zFilter(outputs, 2.0);
|
||||
var final = zFilter(primary, 2.0);
|
||||
|
||||
return {
|
||||
raws: raws,
|
||||
outputs: outputs,
|
||||
primaryOutputs: primary,
|
||||
finalOutputs: final,
|
||||
xScaledShiftAmt: [0.02, -0.02][Math.random() < 0.5 ? 0 : 1],
|
||||
yScaledShiftAmt: [0.015, -0.015][Math.random() < 0.5 ? 0 : 1]
|
||||
};
|
||||
}
|
||||
|
||||
// ─── Timeline Generation (Natural timing) ───
|
||||
function generateTimeline(maxTime){
|
||||
var entries = [];
|
||||
var lastTime = randomInt(1200, 2800);
|
||||
var numEvents = randomInt(2, 4);
|
||||
for(var i = 0; i < numEvents; i++){
|
||||
var duration = randomInt(400, 1200);
|
||||
var end = lastTime + duration;
|
||||
if(end < maxTime){
|
||||
entries.push([lastTime, end]);
|
||||
var gap = randomInt(1200, 2500) + Math.floor(gaussianRandom(0, 300));
|
||||
lastTime = end + Math.max(800, gap);
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
// ─── State Completion Times ───
|
||||
function calculateStateCompletionTimes(stateTimelines){
|
||||
var times = {};
|
||||
for(var key in stateTimelines){
|
||||
var timeline = stateTimelines[key];
|
||||
if(timeline.length < 1) continue;
|
||||
var totalDuration = 0;
|
||||
for(var i = 0; i < timeline.length; i++){
|
||||
totalDuration += timeline[i][1] - timeline[i][0];
|
||||
}
|
||||
times[key] = totalDuration;
|
||||
}
|
||||
return times;
|
||||
}
|
||||
|
||||
// ─── Mouth Tracking (Natural behavior) ───
|
||||
function generateOpennessData(){
|
||||
var streak = [], speeds = [], failedReadings = [], failedSpeeds = [], failedIntervals = [];
|
||||
var lastTimestamp = Date.now() - randomInt(4500, 5500), isOpen = false, openStart = 0;
|
||||
var numEvents = randomInt(6, 10);
|
||||
|
||||
for(var i = 0; i < numEvents; i++){
|
||||
var delay = randomInt(250, 550) + Math.floor(gaussianRandom(0, 100));
|
||||
var timestamp = lastTimestamp + delay;
|
||||
var threshold = 0.55 + gaussianRandom(0, 0.1);
|
||||
var value = Math.random();
|
||||
try {
|
||||
// Modern approach using createImageBitmap (same as k-id-age-verifier)
|
||||
var bitmap = await createImageBitmap(file);
|
||||
var canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(bitmap, 0, 0);
|
||||
var imageData = ctx.getImageData(0, 0, bitmap.width, bitmap.height);
|
||||
var result = jsQR(imageData.data, imageData.width, imageData.height);
|
||||
|
||||
if(value > threshold && !isOpen){
|
||||
isOpen = true; openStart = timestamp;
|
||||
streak.push({start: timestamp, duration: 0});
|
||||
} else if(value < (threshold - 0.2) && isOpen){
|
||||
isOpen = false;
|
||||
var duration = timestamp - openStart;
|
||||
if(duration > 100){
|
||||
streak[streak.length - 1].duration = duration;
|
||||
speeds.push(duration > 0 ? 1000 / duration : 0);
|
||||
} else {
|
||||
streak.pop();
|
||||
}
|
||||
if(result){
|
||||
return result.data;
|
||||
} else {
|
||||
throw new Error('No QR code found in image');
|
||||
}
|
||||
|
||||
if(value < 0.35){
|
||||
failedReadings.push({timestamp: timestamp, reason: 'insufficient_openness'});
|
||||
if(failedReadings.length > 1){
|
||||
var interval = timestamp - failedReadings[failedReadings.length - 2].timestamp;
|
||||
failedIntervals.push(interval);
|
||||
failedSpeeds.push(interval > 0 ? 1000 / interval : 0);
|
||||
}
|
||||
}
|
||||
lastTimestamp = timestamp;
|
||||
}
|
||||
|
||||
return {
|
||||
recordedOpennessStreak: streak,
|
||||
recordedSpeeds: speeds,
|
||||
failedOpennessReadings: failedReadings,
|
||||
failedOpennessSpeeds: failedSpeeds,
|
||||
failedOpennessIntervals: failedIntervals
|
||||
};
|
||||
}
|
||||
|
||||
// ─── Device List (Natural variation) ───
|
||||
function generateDevices(){
|
||||
var cameraPool = [
|
||||
'HD Webcam', 'Integrated Camera', 'USB Camera', 'FaceTime HD Camera',
|
||||
'Logitech Webcam', 'HP TrueVision HD', 'Lenovo EasyCamera', 'Dell Webcam'
|
||||
];
|
||||
var numDevices = randomInt(2, 4);
|
||||
var cameras = [];
|
||||
var usedNames = new Set();
|
||||
|
||||
for(var i = 0; i < numDevices; i++){
|
||||
var name = cameraPool[randomInt(0, cameraPool.length - 1)];
|
||||
while(usedNames.has(name)){
|
||||
name = cameraPool[randomInt(0, cameraPool.length - 1)];
|
||||
}
|
||||
usedNames.add(name);
|
||||
cameras.push(name);
|
||||
}
|
||||
|
||||
var selected = cameras[randomInt(0, cameras.length - 1)];
|
||||
return {
|
||||
devices: cameras.map(function(label, i){
|
||||
return {
|
||||
deviceId: 'dev_' + Date.now().toString(36) + '_' + Math.random().toString(36).substr(2, 9),
|
||||
label: label,
|
||||
kind: 'videoinput'
|
||||
} catch(err) {
|
||||
// Fallback for older browsers
|
||||
return new Promise(function(resolve, reject){
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e){
|
||||
var img = new Image();
|
||||
img.onload = function(){
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0);
|
||||
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
var result = jsQR(imageData.data, imageData.width, imageData.height);
|
||||
if(result){
|
||||
resolve(result.data);
|
||||
} else {
|
||||
reject(new Error('No QR code found in image'));
|
||||
}
|
||||
};
|
||||
img.onerror = function(){reject(new Error('Failed to load image'))};
|
||||
img.src = e.target.result;
|
||||
};
|
||||
}),
|
||||
selectedCamera: selected
|
||||
};
|
||||
reader.onerror = function(){reject(new Error('Failed to read file'))};
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Main Payload Generator (Natural timing) ───
|
||||
function generatePayload(targetAge){
|
||||
var currentTime = Date.now() / 1000;
|
||||
var initialAdjustmentTime = randomInt(250, 750) + Math.floor(gaussianRandom(0, 100));
|
||||
var completionTime = randomInt(9000, 14000) + Math.floor(gaussianRandom(0, 1500));
|
||||
// ─── Verify via API or Standalone ───
|
||||
async function verifyWithQRCode(qrCodeUrl, onProgress){
|
||||
if(verificationInProgress){
|
||||
throw new Error('Verification already in progress');
|
||||
}
|
||||
|
||||
var nonce = Math.random().toString(36).substr(2, 16) + Math.random().toString(36).substr(2, 4);
|
||||
var timestamp = Date.now();
|
||||
var transactionId = 'txn_' + Date.now().toString(36) + '_' + Math.random().toString(36).substr(2, 12);
|
||||
verificationInProgress = true;
|
||||
|
||||
var predictions = generatePredictions(targetAge);
|
||||
var mouthTracking = generateOpennessData();
|
||||
var deviceInfo = generateDevices();
|
||||
|
||||
var stateTimelines = {
|
||||
init: generateTimeline(completionTime),
|
||||
camera_ready: generateTimeline(completionTime),
|
||||
face_detected: generateTimeline(completionTime),
|
||||
mouth_tracking: generateTimeline(completionTime),
|
||||
predictions_start: generateTimeline(completionTime)
|
||||
};
|
||||
|
||||
var stateCompletionTimes = calculateStateCompletionTimes(stateTimelines);
|
||||
|
||||
var jitter = gaussianRandom(0, 500);
|
||||
var startOffset = completionTime + initialAdjustmentTime + randomInt(2200, 4800) + jitter;
|
||||
|
||||
return {
|
||||
nonce: nonce,
|
||||
timestamp: timestamp,
|
||||
transactionId: transactionId,
|
||||
predictions: predictions,
|
||||
mouthTracking: mouthTracking,
|
||||
stateTimelines: stateTimelines,
|
||||
stateCompletionTimes: stateCompletionTimes,
|
||||
devices: deviceInfo.devices,
|
||||
selectedCamera: deviceInfo.selectedCamera,
|
||||
metadata: {
|
||||
sdk_path: './face-capture-v1.10.22.js',
|
||||
model_version: 'v.2025.0',
|
||||
cropper_version: 'v.0.0.3',
|
||||
start_time_stamp: currentTime - startOffset / 1000,
|
||||
end_time_stamp: currentTime + randomFloat(0.15, 0.45),
|
||||
txMode: 'experiment',
|
||||
timestamp: Date.now() - startOffset,
|
||||
isCameraPermissionGranted: true,
|
||||
completionTime: completionTime,
|
||||
deferredComputationStartedAt: currentTime - randomFloat(0.6, 1.8),
|
||||
instructionCompletionTime: completionTime + initialAdjustmentTime + randomInt(80, 180),
|
||||
initialAdjustmentTime: initialAdjustmentTime,
|
||||
completionState: 'COMPLETE'
|
||||
try{
|
||||
if(useStandaloneMode){
|
||||
// Use standalone full implementation
|
||||
if(typeof KIDBypassStandalone === 'undefined'){
|
||||
throw new Error('Standalone mode not loaded. Please refresh the page.');
|
||||
}
|
||||
var result = await KIDBypassStandalone.verify(qrCodeUrl, onProgress);
|
||||
verificationInProgress = false;
|
||||
return result;
|
||||
} else {
|
||||
// Use API endpoint
|
||||
var response = await fetch(API_ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
type: 'qr_link',
|
||||
identifier: qrCodeUrl
|
||||
})
|
||||
});
|
||||
|
||||
if(!response.ok){
|
||||
var errorText = await response.text();
|
||||
throw new Error('Verification failed: ' + errorText);
|
||||
}
|
||||
|
||||
var result = await response.json();
|
||||
verificationInProgress = false;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
} catch(err){
|
||||
verificationInProgress = false;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Public API ───
|
||||
return {
|
||||
intercept: async function(targetAge){
|
||||
targetAge = targetAge || 25;
|
||||
var payload = generatePayload(targetAge);
|
||||
var encrypted = await encryptPayload(payload, payload.nonce, payload.timestamp, payload.transactionId);
|
||||
return {encrypted: encrypted, raw: payload};
|
||||
// Verify using QR code URL
|
||||
verify: async function(qrCodeUrl, onProgress){
|
||||
if(!qrCodeUrl || typeof qrCodeUrl !== 'string'){
|
||||
throw new Error('Invalid QR code URL');
|
||||
}
|
||||
return await verifyWithQRCode(qrCodeUrl, onProgress);
|
||||
},
|
||||
test: function(targetAge){
|
||||
targetAge = targetAge || 25;
|
||||
return generatePayload(targetAge);
|
||||
|
||||
// Verify using QR code image file
|
||||
verifyFromImage: async function(imageFile){
|
||||
if(!imageFile || !(imageFile instanceof File)){
|
||||
throw new Error('Invalid image file');
|
||||
}
|
||||
var qrCodeUrl = await decodeQRFromImage(imageFile);
|
||||
return await verifyWithQRCode(qrCodeUrl);
|
||||
},
|
||||
|
||||
// Check if verification is in progress
|
||||
isVerifying: function(){
|
||||
return verificationInProgress;
|
||||
},
|
||||
|
||||
// Get API endpoint (for debugging)
|
||||
getEndpoint: function(){
|
||||
return API_ENDPOINT;
|
||||
},
|
||||
|
||||
// Set verification mode
|
||||
setMode: function(mode){
|
||||
if(mode === 'standalone'){
|
||||
useStandaloneMode = true;
|
||||
} else if(mode === 'api'){
|
||||
useStandaloneMode = false;
|
||||
}
|
||||
return useStandaloneMode ? 'standalone' : 'api';
|
||||
},
|
||||
|
||||
// Get current mode
|
||||
getMode: function(){
|
||||
return useStandaloneMode ? 'standalone' : 'api';
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
// ═══════════════════════════════════════════════════════
|
||||
// k-ID Bypass — Working Implementation
|
||||
// Based on: kibty.town & Dziurwa14
|
||||
// Full verification via QR code scanning
|
||||
// ═══════════════════════════════════════════════════════
|
||||
|
||||
var KIDBypass = (function(){
|
||||
'use strict';
|
||||
|
||||
var API_ENDPOINT = 'https://age-verifier.kibty.town/api/verify';
|
||||
var verificationInProgress = false;
|
||||
|
||||
// ─── QR Code Scanner (jsQR integration) ───
|
||||
async function decodeQRFromImage(file){
|
||||
return new Promise(function(resolve, reject){
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e){
|
||||
var img = new Image();
|
||||
img.onload = function(){
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0);
|
||||
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Simple QR detection (fallback if jsQR not available)
|
||||
if(typeof jsQR !== 'undefined'){
|
||||
var result = jsQR(imageData.data, imageData.width, imageData.height);
|
||||
if(result){
|
||||
resolve(result.data);
|
||||
} else {
|
||||
reject('No QR code found in image');
|
||||
}
|
||||
} else {
|
||||
reject('QR scanner library not loaded');
|
||||
}
|
||||
};
|
||||
img.onerror = function(){reject('Failed to load image')};
|
||||
img.src = e.target.result;
|
||||
};
|
||||
reader.onerror = function(){reject('Failed to read file')};
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Verify via API ───
|
||||
async function verifyWithQRCode(qrCodeUrl){
|
||||
if(verificationInProgress){
|
||||
throw new Error('Verification already in progress');
|
||||
}
|
||||
|
||||
verificationInProgress = true;
|
||||
|
||||
try{
|
||||
var response = await fetch(API_ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
type: 'qr_link',
|
||||
identifier: qrCodeUrl
|
||||
})
|
||||
});
|
||||
|
||||
if(!response.ok){
|
||||
var errorText = await response.text();
|
||||
throw new Error('Verification failed: ' + errorText);
|
||||
}
|
||||
|
||||
var result = await response.json();
|
||||
verificationInProgress = false;
|
||||
return result;
|
||||
} catch(err){
|
||||
verificationInProgress = false;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Public API ───
|
||||
return {
|
||||
// Verify using QR code URL
|
||||
verify: async function(qrCodeUrl){
|
||||
if(!qrCodeUrl || typeof qrCodeUrl !== 'string'){
|
||||
throw new Error('Invalid QR code URL');
|
||||
}
|
||||
return await verifyWithQRCode(qrCodeUrl);
|
||||
},
|
||||
|
||||
// Verify using QR code image file
|
||||
verifyFromImage: async function(imageFile){
|
||||
if(!imageFile || !(imageFile instanceof File)){
|
||||
throw new Error('Invalid image file');
|
||||
}
|
||||
var qrCodeUrl = await decodeQRFromImage(imageFile);
|
||||
return await verifyWithQRCode(qrCodeUrl);
|
||||
},
|
||||
|
||||
// Check if verification is in progress
|
||||
isVerifying: function(){
|
||||
return verificationInProgress;
|
||||
},
|
||||
|
||||
// Get API endpoint (for debugging)
|
||||
getEndpoint: function(){
|
||||
return API_ENDPOINT;
|
||||
}
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user