Firefox 不尊重 Greasemonkey 脚本中的 Object.defineProperty()?



我正在写一个用户脚本来阻止网站设置document.body.innerHTML,这是网站检测到广告块的典型标志:

(function() {
'use strict';
console.log("Loading ...");
Object.defineProperty(document.body, "innerHTML", {
set: function() {
console.log("malicious activity detected");
throw "Don't try to fool my adblock!";
}
});
console.log("Test setting document.body ...");
try {
document.body.innerHTML = "";
} catch (e) {
console.log(e);
}
}) ();

上面的用户脚本适用于Chrome+Tampermonkey。但它在Firefox+Greasemonkey-4上的行为很奇怪。

控制台中的输出为:

正在加载
测试设置文档.body…
检测到恶意活动
不要试图欺骗我的广告块!

因此用户脚本成功加载,setter也成功挂接。但当加载后,我在控制台中尝试:

document.body.innerHTML = ""

它只是设置innerHTML而没有抛出错误,就好像钩子还没有安装一样。我已经尝试了所有的@run-at选项,但都不起作用。


OTAH,如果我在控制台中使用Object.defineProperty(),那么它可以按预期工作。因此,我得出结论,Firefox不尊重用户脚本中的Object.defineProperty()

您也可以尝试访问此网站:https://connectwww.com.通过在Chrome中的Tampermonkey中安装上述用户脚本,成功拦截了网站上的广告块检测。但是用户脚本在Firefox+Greasemonkey上不起作用。

为什么Firefox不尊重用户脚本中的Object.defineProperty()?有什么变通办法吗

旁注:

一些知名的用户脚本,比如反广告块杀手,也适用于Chrome,但不适用于Firefox,我想这也是出于同样的原因。

Greasemonkey4即使在@grant none模式下也会对脚本进行沙盒处理(这是Greasemonkey4比Tampermonkey或Violentmonkey做得更好的唯一一件事。)

因此,您的脚本正在设置innerHTML的脚本范围/副本
在Tampermonkey中,它与目标页面作用域共享,但在Greasemonkey中这两个作用域被更恰当地分离。因此,页面作用域(和默认控制台)没有看到更改。

在这种情况下,我认为unsafeWindow方法无法工作必须注入覆盖代码

这是一个同时适用于Greasemonkey 4+和Tampermonkey的脚本(也应该适用于Violentmonkey,但我没有测试)。它适用于Chrome和Firefox:

// ==UserScript==
// @name     _Overriding Target page functions can be tricky with GM 4
// @match    *://YOUR_SERVER.COM/YOUR_PATH/*
// @grant    none
// @run-at   document-start
// ==/UserScript==
/* eslint-disable no-multi-spaces */
console.log("Loading ...");
function overrideIt () {
//-- Necessary check because of scope madness in TM, VM, etc.
if (document.body.innerHTML) {
Object.defineProperty (document.body, "innerHTML", {
set: function () {
var scopeStr = (typeof GM === "object"  &&  GM.info) ? "script" : "page";
console.log (`Malicious activity detected - ${scopeStr} scope`);
throw "Don't try to fool my adblock!";
}
} );
}
}
overrideIt ();
if (typeof unsafeWindow === "object") {
console.log ("unsafeWindow detected.");
addJS_Node (null, null, overrideIt);
}
console.log ("Test setting document.body ...");
try {
document.body.innerHTML = "";
} catch (e) {
console.log ("Caught: ", e);
}
//-- addJS_Node is a standard(ish) function
function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
var D                                   = document;
var scriptNode                          = D.createElement ('script');
if (runOnLoad) {
scriptNode.addEventListener ("load", runOnLoad, false);
}
scriptNode.type                         = "text/javascript";
if (text)       scriptNode.textContent  = text;
if (s_URL)      scriptNode.src          = s_URL;
if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
targ.appendChild (scriptNode);
}

相关内容

  • 没有找到相关文章

最新更新