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

修改浏览器指纹属性时,如何让属性访问触发TypeError?

问题:修改浏览器指纹属性后如何保留原TypeError触发行为?

我正在开发一款修改浏览器指纹的工具,使用Object.defineProperty修改属性值后,访问该属性不会像原对象那样触发TypeError,这一特性会被安全系统识别出修改行为。

我的修改方式如下(Screen仅为示例,需支持多个属性的通用解决方案):

const proto = Screen.prototype;
const propName = 'availHeight';
const descriptors = Object.getOwnPropertyDescriptor(Screen.prototype, 'availHeight');
const overrideDescriptors = {
    get: () => 1000
}
Object.defineProperty(proto, propName, {
    ...descriptors,
    ...overrideDescriptors
});

原生行为(预期):

直接访问原型属性会抛出错误:

typeof Screen.prototype.availHeight; 
// Uncaught TypeError: Illegal invocation at <anonymous>:1:25

修改后的实际行为:

访问原型属性返回自定义值,无错误:

typeof Screen.prototype.availHeight; 
// 'number'

请问如何调整代码,才能让属性访问检查和原属性一致,触发TypeError?


解决方案

核心问题是原生属性的getter会校验调用时的this指向——只有当this是对应类的实例时才正常返回,否则抛出Illegal invocation错误。而你用箭头函数定义的getter会丢失this绑定,导致校验失效。

通用修改方案

修改getter函数为普通函数,在内部添加this实例校验,非实例时抛出与原生一致的错误:

const proto = Screen.prototype;
const propName = 'availHeight';
const descriptors = Object.getOwnPropertyDescriptor(proto, propName);
const overrideDescriptors = {
    // 使用普通函数保留this绑定
    get() {
        // 校验this是否为当前类的实例
        if (!(this instanceof proto.constructor)) {
            throw new TypeError('Illegal invocation');
        }
        // 实例访问时返回自定义值
        return 1000;
    }
};
Object.defineProperty(proto, propName, {
    ...descriptors,
    ...overrideDescriptors
});

批量处理工具函数

如果需要修改多个属性,可以封装通用工具函数简化操作:

function overrideFingerprintProperty(proto, propName, customValue) {
    const descriptors = Object.getOwnPropertyDescriptor(proto, propName);
    // 仅处理存在getter的属性
    if (!descriptors || typeof descriptors.get !== 'function') return;

    Object.defineProperty(proto, propName, {
        ...descriptors,
        get() {
            // 校验this是否为目标类的实例
            if (!(this instanceof proto.constructor)) {
                throw new TypeError('Illegal invocation');
            }
            return customValue;
        }
    });
}

// 使用示例
overrideFingerprintProperty(Screen.prototype, 'availHeight', 1000);
overrideFingerprintProperty(Screen.prototype, 'availWidth', 1920);
overrideFingerprintProperty(Navigator.prototype, 'userAgent', 'Mozilla/5.0 ...');

验证效果

  • 直接访问原型属性:Screen.prototype.availHeight → 抛出TypeError: Illegal invocation,与原生一致
  • 通过实例访问:window.screen.availHeight → 返回自定义值1000,实现指纹修改需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:45:42