V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
Leon6868
V2EX  ›  JavaScript

防止 JS 通过 toString 检测到函数被覆盖

  •  2
     
  •   Leon6868 · 2023-03-06 11:52:24 +08:00 · 2001 次点击
    这是一个创建于 416 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有什么用?

    做油猴插件时,有些功能需要通过覆盖源程序的代码实现,不过有些程序比较鸡贼,会通过调用函数的 toString() 属性以检测函数是否覆盖 w(゚Д゚)w

    于是就有了这段代码,通过直接覆盖 Function.prototype.toString ,彻底阻断这种检测方式。

    Github

    https://github.com/SolomonLeon/toString_hack

    示例

    alert.toString() // 'function alert() { [native code] }'
    
    alert = disguisef(alert, ()=>{return "0"}) // 覆盖原函数
    
    alert.toString() // 'function alert() { [native code] }'
    alert.toString.toString() // 'function toString() { [native code] }'
    

    兼容

    chrome 和 firefox 均可用。

    12 条回复    2023-03-06 20:42:08 +08:00
    codehz
        1
    codehz  
       2023-03-06 12:06:05 +08:00 via iPhone
    你 bind 一下就是[native code]了(
    codehz
        2
    codehz  
       2023-03-06 12:09:54 +08:00 via iPhone
    不过对于自定义函数确实需要 hack 一下(
    然而,toLocaleString 是不是也得考虑下
    Leon6868
        3
    Leon6868  
    OP
       2023-03-06 12:39:25 +08:00
    @codehz #2 toLocalString 考虑了,在 chrome 和 Firefox 下都没问题。其实 toString 和 toLocalString 在实现上好像有关联,直接重写 toString 会导致 toLocalString 不可用(( 所以才写出那么奇怪的代码
    codehz
        4
    codehz  
       2023-03-06 12:48:44 +08:00 via iPhone
    这里为啥需要__to_string__绕一圈调用,不可以用 Reflect.apply(realToString, this, [])的方式调用吗,
    仔细想整个 disguisef 实现直接用 new Proxy(fn, { apply() { } })的方式做似乎就够了,hook 的地方直接 proxy call
    disguisef = (targetfn, realfn) => new Proxy(targetfn, { apply(target, thisArg, argumentsList) { return Reflect.apply(realfn, thisArg, argumentsList); } });
    Leon6868
        5
    Leon6868  
    OP
       2023-03-06 12:49:13 +08:00
    @codehz 不知道有没有其他方法检测函数被修改,不过用这个代码的话 toString 和 toLocalString 是没法检测的了((也许?
    Leon6868
        6
    Leon6868  
    OP
       2023-03-06 12:56:16 +08:00
    @codehz #4 这个方法对付原生函数确实超级方便!(可是对自定义函数就会有 bug
    3000codes
        7
    3000codes  
       2023-03-06 13:42:06 +08:00
    直接开启严格模式,在对需要冻结的对象,Object.freeze(obj)
    3000codes
        8
    3000codes  
       2023-03-06 13:43:50 +08:00
    @3000codes 看错标题了,不好意思
    codehz
        9
    codehz  
       2023-03-06 14:20:13 +08:00 via iPhone
    @Leon6868 自定义函数有啥 bug
    centralpark
        10
    centralpark  
       2023-03-06 14:36:34 +08:00
    其实这个问题还有一个更简单的解决方法:重新编译一下 Chrome 不就得了(逃
    Leon6868
        11
    Leon6868  
    OP
       2023-03-06 19:13:00 +08:00
    @codehz #9 自定义函数会返回“[native code]”
    codehz
        12
    codehz  
       2023-03-06 20:42:08 +08:00 via iPhone
    @Leon6868 哦,也好修,再套一层 proxy
    const disguisef = (targetfn, realfn) =>
    new Proxy(targetfn, {
    apply(target, thisArg, argumentsList) {
    return Reflect.apply(realfn, thisArg, argumentsList);
    },
    get() {
    return new Proxy(Reflect.get(...arguments), {
    apply(target, _, argumentsList) {
    return Reflect.apply(target, targetfn, argumentsList);
    },
    });
    },
    });
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5692 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 06:31 · PVG 14:31 · LAX 23:31 · JFK 02:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.