Javascript 如何访问被重写对象的内置方法?
一个网页正在将一个内置javascript方法设置为Javascript 如何访问被重写对象的内置方法?,javascript,object,overriding,userscripts,tampermonkey,Javascript,Object,Overriding,Userscripts,Tampermonkey,一个网页正在将一个内置javascript方法设置为null,我正试图找到一种方法来调用userscript中被重写的方法 考虑以下代码: // Overriding the native method to something else document.querySelectorAll = null; 现在,如果我尝试执行document.querySelectorAll(“#示例”),我将得到异常未捕获类型错误:null不是函数。原因是该方法已更改为null,不再可访问 我正在寻找一种方
null
,我正试图找到一种方法来调用userscript中被重写的方法
考虑以下代码:
// Overriding the native method to something else
document.querySelectorAll = null;
现在,如果我尝试执行document.querySelectorAll(“#示例”)
,我将得到异常未捕获类型错误:null不是函数。原因是该方法已更改为null
,不再可访问
我正在寻找一种方法,以某种方式恢复对userscript中方法的引用。问题是网站可以覆盖对任何内容的引用(甚至包括文档
、元素
和对象
构造函数)
由于网站还可以轻松地将引用设置为null
,因此我需要找到一种方法来访问querySelectorAll
方法,而网站将无法覆盖该方法
挑战在于任何方法,例如createElement
和getElementsByTagName
(除了它们的原型
s)都可以在页面上执行my userscript时被重写为null
我的问题是,如果构造函数方法也被重写,我如何访问文档
或HTMLDocument
构造函数方法
注:
由于Tampermonkey无法在文档开头运行我的脚本,因此我无法保存对我要使用的方法的引用,如下所示:
// the following code cannot be run at the beginning of the document
var _originalQuerySelectorAll = document.querySelectorAll;
至少有3种方法:
使用用户脚本沙盒。唉,由于Tampermonkey和Violentmonkey的设计缺陷/bug,目前这只适用于Greasemonkey(包括版本4+)。下面是更多
使用@在文档开始时运行
。但这在快速页面上也不起作用
删除功能覆盖。这通常是可行的,但可能会对目标页面产生更多干扰。如果页面更改函数的原型
,则可以阻止
另请参见,
请注意,下面的所有脚本和扩展示例都是完整的工作代码
您可以通过更改:
<代码>*://YOUR_SERVER.COM/YOUR_PATH/*
致:
<代码>https://output.jsbin.com/kobegen*
Userscript沙盒: 这是首选方法,适用于Firefox+Greasemonkey(包括Greasemonkey 4) 当将
@grant
设置为none以外的值时,脚本引擎应该在浏览器专门为此提供的沙箱中运行脚本
在适当的沙盒中,目标页面可以覆盖document.querySelectorAll
或它想要的其他本机函数,并且用户脚本将看到它自己的、完全未触及的实例
这应该始终有效:
// ==UserScript==
// @name _Unoverride built in functions
// @match *://YOUR_SERVER.COM/YOUR_PATH/*
// @grant GM_addStyle
// @grant GM.getValue
// ==/UserScript==
//- The @grant directives are needed to restore the proper sandbox.
console.log ("document.querySelectorAll: ", document.querySelectorAll);
和产量:
document.querySelectorAll:函数querySelectorAll(){[本机代码]}
然而,无论是在Chrome还是Firefox中,Tampermonkey和Violentmonkey都不能正确地进行沙箱操作。目标页面可以篡改Tampermonkey脚本看到的本机函数,甚至可以篡改Tampermonkey或Violentmonkey版本的沙盒。
这不仅仅是一个设计缺陷,它是一个安全缺陷,是潜在漏洞的载体 我们知道Firefox和Chrome不是罪魁祸首,因为(1)Greasemonkey-4正确地设置了沙箱,(2)Chrome扩展正确地设置了“孤立世界”。即此扩展: manifest.json:
{
"manifest_version": 2,
"content_scripts": [ {
"js": [ "Unoverride.js" ],
"matches": [ "*://YOUR_SERVER.COM/YOUR_PATH/*" ]
} ],
"description": "Unbuggers native function",
"name": "Native function restore slash use",
"version": "1"
}
console.log ("document.querySelectorAll: ", document.querySelectorAll);
Unoverride.js:
{
"manifest_version": 2,
"content_scripts": [ {
"js": [ "Unoverride.js" ],
"matches": [ "*://YOUR_SERVER.COM/YOUR_PATH/*" ]
} ],
"description": "Unbuggers native function",
"name": "Native function restore slash use",
"version": "1"
}
console.log ("document.querySelectorAll: ", document.querySelectorAll);
收益率:
document.querySelectorAll:函数querySelectorAll(){[本机代码]}
应该如此
使用
@在文档开始时运行:
理论上,在文档开始时运行脚本应该允许脚本在更改本机函数之前捕获它。
例如:
这有时在足够慢的页面和/或网络上起作用
但是,正如OP已经指出的,无论是Tampermonkey还是Violentmonkey实际上都不会在任何其他页面代码之前注入和运行,因此这种方法在快速页面上失败
请注意,清单中带有“run\u at”:“document\u start”
的Chrome扩展内容脚本在正确的时间和/或足够快的速度下运行
删除函数覆盖:
如果页面(温和地)覆盖了诸如document.querySelectorAll
之类的函数,则可以使用delete
清除覆盖,如下所示:
// ==UserScript==
// @name _Unoverride built in functions
// @match *://YOUR_SERVER.COM/YOUR_PATH/*
// @grant none
// ==/UserScript==
delete document.querySelectorAll;
console.log ("document.querySelectorAll: ", document.querySelectorAll);
这将产生:
document.querySelectorAll:函数querySelectorAll(){[本机代码]}
缺点是:
如果页面更改了原型,将无法工作。例如:
Document.prototype.querySelectorAll=null代码>
该页面可以查看或重新制作此类更改,尤其是如果您的脚本
火太快了
通过制作私人副本缓解第2项:
// ==UserScript==
// @name _Unoverride built in functions
// @match *://YOUR_SERVER.COM/YOUR_PATH/*
// @grant none
// ==/UserScript==
var foobarFunc = document.querySelectorAll;
delete document.querySelectorAll;
var _goodfunc = document.querySelectorAll;
var goodfunc = function (params) {return _goodfunc.call (document, params); };
console.log (`goodfunc ("body"): `, goodfunc("body") );
这将产生:
goodfunc(“主体”):节点列表0:body,长度:1
即使页面删除了文档,goodfunc()
也将继续工作(对于您的脚本)。querySelectorAll
Tampermonkey中的其他解决方案是通过iframe恢复原始内容-假设站点的允许,这通常是可行的
const builtin=new Proxy(document.createElement('iframe'){
获取(帧,p){
如果(!frame.parentNode){
frame.style.cssText='显示:无!重要';
document.documentElement.appendChild(框架);
}
返回frame.contentWindow[p];
}
});
用法:
console.log(内置的.document.queryselectoral.call(文档“*”);