这是因为bot-score-v1.js劫持了console对象下的[log, warn, info, error, exception, table, trace]方法并绑定到了一个空函数上这个可以通过在控制台输入console.dir(console.log)会发现正常的应该是顺着[[BoundThis]]下的方法点进去这是一个典型的ob混淆可以在 https://obf-io.deobfuscate.io/ 里面解混淆让我们来看看做了什么AI生成这是一个经过高度混淆的脚本主要用于设备指纹采集、机器人检测以及数据上报。从请求路径/cdn_cgi_bs_bot/可以判断它属于Cloudflare Bot ManagementCloudflare 的机器人管理服务的一部分。下面按执行顺序和功能模块详细解释代码做了什么。1. 自保护与反调试机制开头两个闭包const _0x260d53 function () { ... }(); const _0x4703da _0x260d53(this, function () { return _0x4703da.toString().search((((.)))$) ... }); _0x4703da();_0x260d53是一个单次执行封装器它会返回一个函数但内部函数只能被调用一次通过闭包标志位_0x18bbbe控制。这通常用于防止外部重复调用或调试器干扰。_0x4703da调用自身toString()并执行正则(((.)))$搜索。这个正则是一个经典的ReDoS正则拒绝服务攻击模式同时也可以用于检测代码是否被格式化或篡改——如果函数体被改动search结果会不同可能直接抛出异常起到防逆向作用。类似的第二个闭包_0x228bed和_0x4c84d5功能更具体见下一条。2. 劫持控制台方法_0x4c84d5const _0x228bed function () { ... }(); const _0x4c84d5 _0x228bed(this, function () { const _0x17b582 function () { // 获取全局对象 (window) }; const _0x23f78c _0x17b582().console; const _0x37fa34 [log, warn, info, error, exception, table, trace]; for (...) { const _0x219b17 _0x228bed.constructor.prototype.bind(_0x228bed); _0x219b17.__proto__ _0x228bed.bind(_0x228bed); _0x219b17.toString _0x16e0f1.toString.bind(_0x16e0f1); _0x23f78c[methodName] _0x219b17; } }); _0x4c84d5();它通过Function(return (function() {}.constructor(\return this\)( ));)()来获取全局对象window此方式可避开严格模式的限制。遍历console.log、warn、info、error等方法将它们全部替换成一个绑定了_0x228bed的空白函数。同时把替换函数的__proto__和toString也做了重定向让它在开发者工具中看起来像是原生的 console 方法但实际上禁止了所有控制台输出防止调试信息泄露或被人从控制台观察脚本行为。3. Cookie 读取函数_0x4a7a78function _0x4a7a78(cookieName) { var cookies document.cookie.split(; ); for (var i 0; i cookies.length; i) { var parts cookies[i].split(); if (cookieName parts[0]) return unescape(parts[1]); } return ; }简单地从document.cookie中解析并返回指定名称的 cookie 值。在后续流程中用于读取名为bc_bot_session的 cookie。4. 加密函数_0x26f755function _0x26f755(plaintext, keyStr) { var keyMd5 CryptoJS.MD5(keyStr).toString(); var key CryptoJS.enc.Utf8.parse(keyMd5.substring(0, 16)); var iv CryptoJS.enc.Utf8.parse(keyMd5.substring(16)); return CryptoJS.AES.encrypt(plaintext, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }).toString(); }依赖全局的CryptoJS库AES 加密CBC 模式Pkcs7 填充。先将密钥字符串进行MD5 哈希取结果的前 16 个字符作为 AES 密钥后 16 个字符作为 IV初始化向量。返回加密后的密文通常是 Base64 编码字符串。5. 指纹数据整理_0x44786bfunction _0x44786b(fingerprintResult) { let data { visitorId: fingerprintResult.visitorId, confidence: fingerprintResult.confidence.score }; // 提取 FingerprintJS 组件信息 let components fingerprintResult.components; if (components) { data.fontsLength ...; data.audio ...; data.colorGamut ...; data.canvas ...; // winding 等 data.touchSupport ...; data.cookiesEnabled ...; data.videoCard ...; data.pdfViewerEnabled ...; data.platform ...; // 等等 } // 提取 Botd 机器人检测信息 let botd fingerprintResult.botd; let botdComps botd.components; if (botdComps) { data.userAgent ...; data.windowSize ...; data.pluginsLength ...; data.webGL ...; data.webDriver ...; // 是否启用自动化工具如 Selenium data.android ...; data.distinctiveProps ...; data.browserKind ...; // ... } data.bot botd.bot; // 如果 botd 组件不存在且 bot 标志不为 true则强制标记为机器人 if (botd.bot ! true (botdComps undefined)) { data.bot true; } return data; }将 FingerprintJS v3 生成的庞大指纹对象精简成一个只包含关键字段的平面对象。同时合并 Botd (Bot Detection) 模块的检测结果。特别关注webDriver自动化驱动检测、bot标记等字段用于判断访问者是否为机器人。6. 加密并上报数据_0x4f90d3function _0x4f90d3(processedFp) { let sessionCookie _0x4a7a78(bc_bot_session); let visitorId processedFp.visitorId; let encrypted _0x26f755(JSON.stringify(processedFp), sessionCookie visitorId); const payload { fp: visitorId, enc: encrypted }; fetch(/cdn_cgi_bs_bot/api, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify(payload) }) .then(res res.json()) .then(data data.status 1) .catch(err console.error(Error:, err)); }从 cookie 读取bc_bot_session作为会话标识。用bc_bot_sessionvisitorId拼接后作为加密密钥对精简后的指纹数据进行 AES 加密。将visitorId明文和密文一起通过POST发送到/cdn_cgi_bs_bot/api。期望响应 JSON 中status为 1 表示成功。7. 主执行流程let botdResult; const botdPromise import(/cdn_cgi_bs_bot/static/fingerprintjs-botd-v1.js) .then(module module.load()); botdPromise .then(loaded { let result loaded.detect(); result.components loaded.components; result.detections loaded.detections; return result; }) .then(res { botdResult res; }) .catch(err console.error(err)); const fpPromise import(/cdn_cgi_bs_bot/static/fingerprintjs-v3.js) .then(module module.load()); fpPromise .then(fp fp.get()) .then(fpData { fpData.botd botdResult; // 将 botd 检测结果挂到指纹对象上 let processed _0x44786b(fpData); // 精简数据 _0x4f90d3(processed); // 加密并上报 });使用动态import()加载两个外部脚本fingerprintjs-botd-v1.js机器人检测库提供浏览器特征检测如 WebDriver、headless chrome 痕迹等。fingerprintjs-v3.jsFingerprintJS v3生成浏览器指纹Visitor ID。Botd 先执行load()和detect()结果暂存到变量botdResult。FingerprintJS 调用get()获取完整的浏览器指纹对象。将 Botd 结果合并进指纹对象再经过_0x44786b提取关键字段最后调用_0x4f90d3加密上报。整体目的这段脚本是Cloudflare 的反机器人/安全防护系统在客户端埋下的检测代码其主要功能为收集多维度的浏览器指纹Canvas、WebGL、字体、音频、硬件并发、插件、屏幕尺寸等。识别自动化工具与机器人如 Selenium WebDriver、Headless Chrome、Android 模拟器等。将收集到的数据用动态密钥加密密钥来自 Cookie 和指纹 ID后回传到 Cloudflare 的接口。抑制开发者工具的控制台输出增加逆向分析的难度。采用混淆和反调试技巧防止篡改和静态分析。最终服务端根据这些加密的指纹数据判断访问者是否为正常用户从而决定放行、拦截或提出人机验证挑战。再让我们看看fingerprintjs-botd-v1.js和fingerprintjs-v3.js是干什么的AI生成这两个脚本是Cloudflare机器人管理系统Bot Management中使用的客户端检测模块。fingerprintjs-v3.js负责生成浏览器指纹而fingerprintjs-botd-v1.js则用于检测自动化工具和机器人。fingerprintjs-v3.js浏览器指纹识别脚本fingerprintjs-v3.js是FingerprintJS v3.4.2开源库主要功能是生成一个独特的访问者IDVisitor ID。技术原理它通过收集浏览器的多种信号如Canvas渲染、WebGL、音频处理、字体列表、屏幕色深等利用MurmurHash3哈希算法生成一个紧凑的标识符。后续分析中提到的Picasso技术也是其指纹采集的一部分被用于生成信号。该ID在隐身模式下也能保持稳定但纯客户端版本准确率有限约为40%-60%。fingerprintjs-botd-v1.js机器人检测脚本fingerprintjs-botd-v1.js是Fingerprint BotD v1.9.1库专门用于识别访问者是否为自动化程序。检测机制它不仅检测通用的无头浏览器和自动化框架如Selenium、Playwright还会根据navigator.userAgent来判断浏览器内核如Chromium/Blink、WebKit、Gecko。高级检测它还会检查设备是否开启WebDriver模式并检查navigator.plugins等属性以区分真实浏览器和模拟浏览器的机器人。与Cloudflare的协同工作这两个脚本会被Cloudflare动态注入到HTML页面中。其生成的信号如JA3/JA4指纹会被纳入后台的机器人评分Bot Score系统用于区分人类与自动流量。默认情况下脚本每30分钟才执行一次。总结总的来说这两个脚本共同构建了一个双层检测体系第一个脚本用于识别谁在访问即生成设备指纹第二个脚本用于判断是不是真人即检测机器人。它们是Cloudflare机器人管理系统中不可或缺的一环。未登录无法复制解决这个就需要下断点跟踪了我们现在元素中找到所有的事件绑定这里面没有copy的绑定所以就只好看keydown了其实也可以全局搜索copy的但用前者却无意间发现了一个关键区别这个等会再说。