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

2023-03-06 11:52:24 +08:00
 Leon6868

有什么用?

做油猴插件时,有些功能需要通过覆盖源程序的代码实现,不过有些程序比较鸡贼,会通过调用函数的 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 均可用。

2011 次点击
所在节点    JavaScript
12 条回复
codehz
2023-03-06 12:06:05 +08:00
你 bind 一下就是[native code]了(
codehz
2023-03-06 12:09:54 +08:00
不过对于自定义函数确实需要 hack 一下(
然而,toLocaleString 是不是也得考虑下
Leon6868
2023-03-06 12:39:25 +08:00
@codehz #2 toLocalString 考虑了,在 chrome 和 Firefox 下都没问题。其实 toString 和 toLocalString 在实现上好像有关联,直接重写 toString 会导致 toLocalString 不可用(( 所以才写出那么奇怪的代码
codehz
2023-03-06 12:48:44 +08:00
这里为啥需要__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
2023-03-06 12:49:13 +08:00
@codehz 不知道有没有其他方法检测函数被修改,不过用这个代码的话 toString 和 toLocalString 是没法检测的了((也许?
Leon6868
2023-03-06 12:56:16 +08:00
@codehz #4 这个方法对付原生函数确实超级方便!(可是对自定义函数就会有 bug
3000codes
2023-03-06 13:42:06 +08:00
直接开启严格模式,在对需要冻结的对象,Object.freeze(obj)
3000codes
2023-03-06 13:43:50 +08:00
@3000codes 看错标题了,不好意思
codehz
2023-03-06 14:20:13 +08:00
@Leon6868 自定义函数有啥 bug
centralpark
2023-03-06 14:36:34 +08:00
其实这个问题还有一个更简单的解决方法:重新编译一下 Chrome 不就得了(逃
Leon6868
2023-03-06 19:13:00 +08:00
@codehz #9 自定义函数会返回“[native code]”
codehz
2023-03-06 20:42:08 +08:00
@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);
},
});
},
});

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/921522

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX