You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript如何无感知封装全局函数?为何MediaSource封装会被检测?

JavaScript函数封装检测原理与无感知封装实现方案

一、网站检测函数封装的常用手段

  • 检测toString()返回值:浏览器内置的原生方法调用toString()时,会固定返回function 方法名() { [native code] }格式的结果,而自定义的封装函数toString()会返回编写的函数源码内容,二者差异非常明显,是最常用的检测手段。
  • 校验函数基础属性:原生方法的name(函数名)、length(形参个数)都是固定值,比如MediaSource.prototype.addSourceBuffer的length为1,如果封装函数形参不匹配、name属性不对,会直接被识别。
  • 对比属性描述符:通过Object.getOwnPropertyDescriptor获取方法的writable、enumerable、configurable配置,原生方法的这些配置是固定的,如果直接用赋值的方式重写方法,属性描述符会发生变化,也会触发检测。
  • 引用对比校验:部分站点会在页面初始化阶段提前缓存原生方法的引用,或者动态创建iframe获取内置原生方法,和当前页面的方法进行引用对比,不一致就判定被篡改。

二、无感知全局函数封装实现方式

针对上述检测手段,逐个做兼容处理即可绕过检测,修改后的封装代码如下:

// 1. 提前缓存原生方法与原始属性描述符
const nativeAddSourceBuffer = window.MediaSource.prototype.addSourceBuffer;
const nativeDescriptor = Object.getOwnPropertyDescriptor(window.MediaSource.prototype, 'addSourceBuffer');

// 2. 定义封装函数,形参数量、顺序和原生保持完全一致
function wrappedAddSourceBuffer(mime) {
    // 此处添加你的自定义逻辑,比如捕获流数据等
    console.log('addSourceBuffer调用,MIME类型:', mime);
    // 调用原生逻辑保证功能正常
    return nativeAddSourceBuffer.call(this, mime);
}

// 3. 覆写封装函数的toString方法,返回和原生完全一致的结果
wrappedAddSourceBuffer.toString = function() {
    return 'function addSourceBuffer() { [native code] }';
};

// 4. 用原始属性描述符覆写方法,避免描述符差异被检测
Object.defineProperty(window.MediaSource.prototype, 'addSourceBuffer', {
    ...nativeDescriptor,
    value: wrappedAddSourceBuffer
});

注意事项

  • 如果使用脚本注入的方式实现封装,需要将脚本运行时机设置为页面所有代码加载之前(比如Tampermonkey的run-at: document-start),避免站点提前缓存了原生方法的引用导致封装失效。
  • 不要给封装函数添加自定义的可枚举属性,避免被遍历检测到异常。
  • 极少数站点会hookFunction.prototype.toString做二次校验,遇到这类情况提前缓存原生的toString方法使用即可。

内容的提问来源于stack exchange,提问作者user16387400

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 00:24:02