console.log不可用解决
这是因为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 Management(Cloudflare 的机器人管理服务)的一部分。
下面按执行顺序和功能模块,详细解释代码做了什么。
1. 自保护与反调试机制(开头两个闭包)
const _0x260d53 = function () { ... }();
const _0x4703da = _0x260d53(this, function () {
return _0x4703da.toString().search("(((.+)+)+)+$") ...
});
_0x4703da();
_0x260d53是一个单次执行封装器,它会返回一个函数,但内部函数只能被调用一次(通过闭包标志位_0x18bbbe控制)。这通常用于防止外部重复调用或调试器干扰。_0x4703da调用自身toString()并执行正则(((.+)+)+)+$搜索。这个正则是一个经典的ReDoS(正则拒绝服务)攻击模式,同时也可以用于检测代码是否被格式化或篡改——如果函数体被改动,search结果会不同,可能直接抛出异常,起到防逆向作用。
类似的第二个闭包 _0x228bed 和 _0x4c84d5 功能更具体,见下一条。
2. 劫持控制台方法(_0x4c84d5)
const _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 读取函数(_0x4a7a78)
function _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. 加密函数(_0x26f755)
function _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. 指纹数据整理(_0x44786b)
function _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. 加密并上报数据(_0x4f90d3)
function _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_session+visitorId拼接后作为加密密钥,对精简后的指纹数据进行 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.js:FingerprintJS 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开源库,主要功能是生成一个独特的"访问者ID"(Visitor 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 的,但用前者却无意间发现了一个关键区别,这个等会再说。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)