// ==UserScript==
// @name 浏览器功能包
// @namespace http://tampermonkey.net/
// @version 0.2.3
// @description 修改浏览器的一些配置,使脚本可以作弊
// @author Tenfond
// @match *://*/*
// @grant none
// @license MIT
// @run-at document-start
// ==/UserScript==
(function () {
try {
const timers = {
"Timeout": {},
"Interval": {}
},
setTimeout = window.setTimeout,
setInterval = window.setInterval,
clearTimeout = window.clearTimeout,
clearInterval = window.clearInterval;
window.setTimeout = function (handler, timeout, ...arguments) {
const handle = setTimeout.apply(this, [handler, timeout].concat(arguments));
timers["Timeout"][handle] = {
"handler": handler,
"timeout": timeout,
"arguments": arguments
};
return handle;
};
window.setInterval = function (handler, timeout, ...arguments) {
const handle = setInterval.apply(this, [handler, timeout].concat(arguments));
timers["Interval"][handle] = {
"handler": handler,
"timeout": timeout,
"arguments": arguments
};
return handle;
};
window.getAllTimeout = function () {
return timers["Timeout"];
};
window.getAllInterval = function () {
return timers["Interval"];
};
window.getTimeout = function (handle) {
return timers["Timeout"][handle];
};
window.getInterval = function (handle) {
return timers["Interval"][handle];
};
window.clearTimeout = function (handle) {
clearTimeout.apply(this, arguments);
delete timers["Timeout"][handle];
};
window.clearInterval = function (handle) {
clearInterval.apply(this, arguments);
delete timers["Interval"][handle];
};
} catch (e) {
console.error(e.message);
}
// event 可信任事件
(function () {
function tamper(event) {
return {
"isTrusted": true,
get altitudeAngle() {
return event["altitudeAngle"];
},
get azimuthAngle() {
return event["azimuthAngle"];
},
"getCoalescedEvents": function getCoalescedEvents() {
return event["getCoalescedEvents"].apply(event, arguments);
},
"getPredictedEvents": function getPredictedEvents() {
return event["getPredictedEvents"].apply(event, arguments);
},
get height() {
return event["height"];
},
get isPrimary() {
return event["isPrimary"];
},
get pointerId() {
return event["pointerId"];
},
get pointerType() {
return event["pointerType"];
},
get pressure() {
return event["pressure"];
},
get tangentialPressure() {
return event["tangentialPressure"];
},
get tiltX() {
return event["tiltX"];
},
get tiltY() {
return event["tiltY"];
},
get twist() {
return event["twist"];
},
get width() {
return event["width"];
},
"constructor": event["constructor"],
"__proto__": event["__proto__"],
get altKey() {
return event["altKey"];
},
get bubbles() {
return event["bubbles"];
},
get button() {
return event["button"];
},
get buttons() {
return event["buttons"];
},
get cancelBubble() {
return event["cancelBubble"];
},
get cancelable() {
return event["cancelable"];
},
get clientX() {
return event["clientX"];
},
get clientY() {
return event["clientY"];
},
get composed() {
return event["composed"];
},
get ctrlKey() {
return event["ctrlKey"];
},
get currentTarget() {
return event["currentTarget"];
},
get defaultPrevented() {
return event["defaultPrevented"];
},
get detail() {
return event["detail"];
},
get eventPhase() {
return event["eventPhase"];
},
get fromElement() {
return event["fromElement"];
},
get layerX() {
return event["layerX"];
},
get layerY() {
return event["layerY"];
},
get metaKey() {
return event["metaKey"];
},
get movementX() {
return event["movementX"];
},
get movementY() {
return event["movementY"];
},
get offsetX() {
return event["offsetX"];
},
get offsetY() {
return event["offsetY"];
},
get pageX() {
return event["pageX"];
},
get pageY() {
return event["pageY"];
},
get path() {
return event["path"];
},
get relatedTarget() {
return event["relatedTarget"];
},
get returnValue() {
return event["returnValue"];
},
get screenX() {
return event["screenX"];
},
get screenY() {
return event["screenY"];
},
get shiftKey() {
return event["shiftKey"];
},
get sourceCapabilities() {
return event["sourceCapabilities"]
},
get srcElement() {
return event["srcElement"];
},
get target() {
return event["target"];
},
get timeStamp() {
return event["timeStamp"];
},
get toElement() {
return event["toElement"];
},
get type() {
return event["type"];
},
get view() {
return event["view"];
},
get which() {
return event["which"];
},
get x() {
return event["x"];
},
get y() {
return event["y"];
},
"composedPath": function composedPath() {
return event["composedPath"].apply(event, arguments);
},
"preventDefault": function preventDefault() {
return event["preventDefault"].apply(event, arguments);
},
"stopImmediatePropagation": function stopImmediatePropagation() {
return event["stopImmediatePropagation"].apply(event, arguments);
},
"stopPropagation": function stopPropagation() {
return event["stopPropagation"].apply(event, arguments);
}
};
}
try {
const addEventListener = EventTarget.prototype.addEventListener;
Object.defineProperty(EventTarget.prototype, "addEventListener", {
value: function (type, callback, options = false) {
return addEventListener.apply(this, [type, type === "click" ? function () {
if (arguments.length > 0 && arguments[0].constructor.name === "PointerEvent")
arguments[0] = tamper(arguments[0]);
return callback.apply(this, arguments);
} : callback, options]);
},
writable: false,
enumerable: true,
configurable: false
});
} catch (e) {
console.error(e.message);
}
})();
// 定义 location.hashCode 获取 href的hash值
(function () {
try {
Object.defineProperty(location, "hashCode", {
enumerable: true,
configurable: false,
get: function () {
let code = 0;
for (const v of location.href) {
code += (code << 7) + v.charCodeAt(0);
}
// 返回值在 JavaScript 中的取值范围 [-2147483648,4294967294]
return code;
}
});
} catch (e) {
console.error(e.message);
}
let hashCode = location.hashCode, onchange = null;
try {
Object.defineProperty(location, "onchange", {
enumerable: true,
configurable: false,
get: function () {
return onchange;
},
set: function (handler) {
if (typeof handler === "function" || Boolean(handler) === false) {
onchange = handler;
} else {
console.error("Uncaught (in onchange) TypeError: " + handler + " is not a function.")
}
}
});
setInterval(function () {
if (hashCode !== location.hashCode) {
hashCode = location.hashCode;
if (typeof onchange === "function") onchange();
}
}, 500);
} catch (e) {
console.error(e.message);
}
})();
window.searchToJSON = function searchToJSON(search) {
if (search) {
return JSON.parse("{\"" + decodeURIComponent(search.substring(1)
.replace(new RegExp("\"", "g"), '\\"')
.replace(new RegExp("&", "g"), '","')
.replace(new RegExp("=", "g"), '":"')) + "\"}");
} else {
return null;
}
}
window.hrefToLocation = function hrefToLocation(href) {
let location = {href: href}, c = 0, start = 0, port, search;
for (let i = 0; i < href.length; i++) {
if (href[i] === "/") {
if (++c === 1) {
location.protocol = href.substring(start, i);
} else if (c === 3) {
location.host = href.substring(start, i);
location.origin = href.substring(0, i);
if (port) {
location.port = href.substring(port, i);
} else {
location.hostname = location.host;
location.port = "";
}
}
if (c <= 3) {
start = i + 1;
}
} else if (href[i] === ":" && c === 2) {
location.hostname = href.substring(start + 1, i);
port = i + 1;
} else if (href[i] === "?" && !search) {
location.pathname = href.substring(start - 1, i);
search = i;
} else if (href[i] === "#" && !location.hash) {
location.hash = href.substring(i);
if (search) {
location.search = href.substring(search, i);
} else {
location.search = "";
location.pathname = href.substring(start - 1, i);
}
break;
}
}
if (typeof location.host === "undefined") {
if (c < 2) {
location.host = location.hostname = location.port = location.origin = "";
} else if (c === 2) {
location.host = href.substring(start);
location.origin = href;
if (typeof location.hostname === "undefined") {
location.hostname = location.host;
location.port = "";
} else {
location.port = href.substring(port);
}
}
location.pathname = location.hash = "";
} else if (typeof location.pathname === "undefined") {
location.pathname = href.substring(start - 1);
location.search = location.hash = "";
} else if (typeof location.search === "undefined") {
if (search) {
location.search = href.substring(search);
} else {
location.search = "";
}
location.hash = "";
} else if (typeof location.hash === "undefined") {
location.hash = "";
}
return location;
}
window.xmlHttpRequest = function xmlHttpRequest(handler = {}) {
function xhrToArgs(xhr) {
if (xhr.constructor.name === "XMLHttpRequest") return {
// "onabort": xhr["onabort"],
// "onerror": xhr["onerror"],
// "onload": xhr["onload"],
// "onloadend": xhr["onloadend"],
// "onloadstart": xhr["onloadstart"],
// "onprogress": xhr["onprogress"],
// "onreadystatechange": xhr["onreadystatechange"],
// "ontimeout": xhr["ontimeout"],
"abort": function () {
return xhr["abort"]();
},
"finalUrl": xhr["responseURL"],
"responseHeaders": (function () {
const headers = {};
xhr["getAllResponseHeaders"]().split("\r\n").forEach(function (header) {
header = header.split(": ");
headers[header[0]] = header[1];
});
return headers;
})(),
"getResponseHeader": function (name) {
return xhr["getResponseHeader"](name);
},
"overrideMimeType": function (mime) {
return xhr["overrideMimeType"](mime);
},
"responseType": xhr["responseType"],
"response": xhr["response"],
"responseText": (function () {
try {
return xhr["responseText"];
} catch (e) {
console.error(e.message);
return e;
}
})(),
"responseXML": (function () {
try {
return xhr["responseXML"];
} catch (e) {
console.error(e.message);
return e;
}
})(),
"readyState": xhr["readyState"],
"status": xhr["status"],
"statusText": xhr["statusText"],
"timeout": xhr["timeout"],
// "upload": xhr["upload"],
// "withCredentials": xhr["withCredentials"]
}; else return xhr.constructor.name;
}
if (typeof handler === "string") handler = {url: handler};
const request = new XMLHttpRequest();
if (handler.onreadystatechange) request.onreadystatechange = function (event) {
return handler.onreadystatechange(xhrToArgs(request), event);
};
request.open(handler.method ? handler.method.toUpperCase() : "GET", handler.url ? handler.url : location.href, handler.async ? handler.async : true, handler.user ? handler.user : null, handler.password ? handler.password : null);
if (handler.headers) for (let header in handler.headers) request.setRequestHeader(header, handler.headers[header]);
if (handler.onabort) request.onabort = function (event) {
return handler.onabort(xhrToArgs(request), event);
};
if (handler.onerror) request.onerror = function (event) {
return handler.onerror(xhrToArgs(request), event);
};
if (handler.onload) request.onload = function (event) {
return handler.onload(xhrToArgs(request), event);
};
if (handler.onloadend) request.onloadend = function (event) {
return handler.onloadend(xhrToArgs(request), event);
};
if (handler.onloadstart) request.onloadstart = function (event) {
return handler.onloadstart(xhrToArgs(request), event);
};
if (handler.onprogress) request.onprogress = function (event) {
return handler.onprogress(xhrToArgs(request), event);
};
if (handler.ontimeout) request.ontimeout = function (event) {
return handler.ontimeout(xhrToArgs(request), event);
};
if (handler.responseType) request.responseType = handler.responseType;
if (handler.overrideMimeType) request.setRequestHeader("Content-Type", handler.overrideMimeType);
if (handler.data) {
request.send(JSON.stringify(handler.data));
} else {
request.send();
}
return request;
}
window.ready = function ready(handler, readyState = "interactive") {
// "loading": 表示文档还在加载中,即处于“正在加载”状态。
// "interactive": 文档已经结束了“正在加载”状态,DOM 元素可以被访问。但是像图像,样式表和框架等资源依然还在加载。
// "complete": 页面所有内容都已被完全加载。
let intervalId = setInterval(function (states = ["loading", "interactive", "complete"]) {
if (states.indexOf(document.readyState.toLowerCase()) >= states.indexOf(readyState.toLowerCase())) {
clearInterval(intervalId);
if (typeof handler === "function") {
handler();
} else {
console.error("Uncaught (in ready) TypeError: " + handler + " is not a function.");
}
}
});
}
/**
梅森旋转算法中用到的变量如下所示:
w:长度 生成的随机数的二进制长度
n:寄存器长度 参与旋转的随机数个数(旋转的深度)
m:周期参数,用作第三阶段的偏移量 旋转算法参与旋转的中间项
r:低位掩码/低位要提取的位数 内存界限值 2 的 r 次方 - 1 x⃗ (u)kx→k(u) 和 x⃗ (l)k+1x→k+1(l) 的切分位置
a:旋转矩阵的参数 旋转算法异或基数 矩阵 AA 的最后一行
f:初始化梅森旋转链所需参数 旋转链异或值膨化量
u,s,t,l: 整数参数,移位运算的移动距离
d,b,c: 比特遮罩
s,t:TGFSR的位移量
b,c:TGFSR的掩码
u,d,l:额外梅森旋转所需的掩码和位移量
MT19937-32的参数列表如下:
(w, n, m, r) = (32, 624, 397, 31)
a = 9908B0DF(16)
f = 1812433253
(u, d) = (11, FFFFFFFF16)
(s, b) = (7, 9D2C568016)
(t, c) = (15, EFC6000016)
l = 18
*/
window.MT = (function () {
// 新方案定义私有变量。修复部分浏览器不支持 # 定义private私有变量
const $n = Symbol(), $m = Symbol(), $r = Symbol(),
$a = Symbol(),
$u = Symbol(), $d = Symbol(),
$s = Symbol(), $b = Symbol(),
$t = Symbol(), $c = Symbol(),
$l = Symbol(),
$index = Symbol(), $LinkedList = Symbol();
// 旋转算法处理旋转链
function generate(MT) {
for (let i = 0n; i < MT[$n]; i++) {
const lower_mask = -(1n << MT[$r]);
const upper_mask = ~lower_mask;
const y = (MT[$LinkedList][i] & upper_mask) + (MT[$LinkedList][(i + 1n) % MT[$n]] & lower_mask);
let yA = y >> 1n;
if ((y % 2n) !== 0n) {
yA = yA ^ MT[$a];
}
MT[$LinkedList][i] = MT[$LinkedList][(i + MT[$m]) % MT[$n]] ^ yA;
}
}
class MT {
constructor(
seed = Date.now(),
w = 32, n = 624, m = 397, r = 31,
a = 0x9908B0DF, f = 1812433253,
u = 11, d = 0xFFFFFFFF,
s = 7, b = 0x9D2C5680,
t = 15, c = 0xEFC60000,
l = 18) {
w = BigInt(w);
this[$n] = BigInt(n);
this[$m] = BigInt(m);
this[$r] = BigInt(r);
this[$a] = BigInt(a);
f = BigInt(f);
this[$u] = BigInt(u);
this[$d] = BigInt(d);
this[$s] = BigInt(s);
this[$b] = BigInt(b);
this[$t] = BigInt(t);
this[$c] = BigInt(c);
this[$l] = BigInt(l);
this[$index] = 0n;
this[$LinkedList] = [BigInt(seed)];
// 对数组其他元素进行初始化
for (let i = 1n; i < this[$n]; i++) {
this[$LinkedList][i] = (f * (this[$LinkedList][i - 1n] ^ (this[$LinkedList][i - 1n] >> (w - 2n))) + i & (1n << w) - 1n);
}
}
// 获取随机数
next() {
if (this[$index] === 0n) generate(this);
let y = this[$LinkedList][this[$index]];
y = (y ^ ((y >> this[$u]) & this[$d]));
y = (y ^ ((y << this[$s]) & this[$b]));
y = (y ^ ((y << this[$t]) & this[$c]));
y = (y ^ (y >> this[$l]));
this[$index] = (this[$index] + 1n) % this[$n];
if (y <= 9007199254740992n) y = parseInt(y.toString());
return y;
}
}
return MT;
})();
// 未经许可禁止抄袭算法,可以私用。
window.Key = (function () {
// 定义private私有变量
const $pwd = Symbol();
// 自定义加密算法,以防数据包被破解。
class Key {
// _pwd; // 火狐v68版本貌似不支持这种方式声明变量。
constructor(pwd = "Tenfond") {
// num,密码偏移量
// key,排列长度偏移量
// charCode,防止内存频繁运动,定义在外部
let key = 7n;
if (typeof pwd === "string") {
for (let i = 0; i < pwd.length; i++) {
key = key * 31n + BigInt(pwd[i].charCodeAt(0));
}
pwd = key;
key = key & 0xFFFFFFFFFFFFn;
} else if ((typeof pwd).match(new RegExp("(number|'bigint')"))) {
// 如果密码是数值型就使用此方法作为 密码偏移量 和 排列长度偏移量
pwd = BigInt(Math.round(pwd));
key = (key * 31n + pwd) & 0xFFFFFFFFFFFFn;
} else {
// 如果类型不匹配就直接提出错误
console.error("Unsupported type '" + (typeof pwd) + "'. It only supports 'string' 'number' 'bigint'.");
}
// 让排列长度偏移量取第一个数字。加上密码转换成字符字符串的方式
this[$pwd] = (pwd >= 0n ? pwd % 8n + 2n : -(pwd % 8n) + 2n).toString() + key.toString(36);
}
encrypt(string) {
if (typeof string === "string" && string.length > 0) {
// subStart 排列长度的起始位置。subLength 排列长度。
let subStart = string.length, subLength = parseInt(this[$pwd][0]),
// encryptPool 加密池,即去除的排列长度存放在这里。result 加密后的结果。
encryptPool = [], result = "";
// stringKey 加密种子。
const MTSeed = new MT(subStart + parseInt(this[$pwd].substring(1), 36));
// 获取加密池。
while (subStart > subLength) {
subStart -= subLength;
encryptPool.push(string.substring(subStart, subStart + subLength));
}
encryptPool.push(string.substring(0, subStart));
// 对加密池进行加密,并将加密的字符的结果放入 result 中。
for (let i = 0, j; i < subLength; i++) {
for (j = 0; j < encryptPool.length; j++) {
const char = encryptPool[j][i];
if (char) {
let key = (char.charCodeAt(0) + MTSeed.next()) % 0x100000000;
key = [Math.floor(key / 0x10000), key % 0x10000];
result += i * j % 2 === 0 ? String.fromCharCode(key[0]) + String.fromCharCode(key[1]) : String.fromCharCode(key[1]) + String.fromCharCode(key[0]);
} else {
break;
}
}
}
// 返回加密结果
return result;
} else {
// 如果加密字符串不存在就返回string
return string;
}
}
/* 假设有7个字符
加密前 - 排列
( 1 ) ( 2 3 4 ) ( 5 6 7 )
加密中 - 排列
︵ ︵ ︵
5 2 1
6 3 ︶
7 4
︶ ︶
加密后 - 排列
( 5 2 1 ) ( 6 3 ) ( 7 4 )
解密中 - 排列
︵ ︵ ︵
5 6 7
2 3 4
1 ︶ ︶
︶
解密后 - 排列
1 2 3 4 5 6 7
*/
decrypt(string) {
if (typeof string === "string" && string.length > 0) {
// subStart 排列长度的起始位置。desubLength 反向取加密池的长度。
let subStart = 0,
desubLength = Math.ceil(string.length / 2 / parseInt(this[$pwd][0])),
// decryptPool 解密池。result 解密后的结果。
decryptPool = [], result = "";
// stringKey 加密种子。
const MTSeed = new MT(string.length / 2 + parseInt(this[$pwd].substring(1), 36));
(function (MT, desubLength) {
//NullCount 加密池中没有空位的池数
const NullCount = string.length / 2 % parseInt(MT[$pwd][0]);
// 获取解密池
while (string.length / 2 - subStart > desubLength) {
decryptPool.push(string.substring(subStart * 2, (subStart + desubLength) * 2));
subStart += desubLength;
if (decryptPool.length === NullCount) desubLength--;
}
decryptPool.push(string.substring(subStart * 2));
})(this, desubLength);
// 对解密池进行解密 并将解密结果 加入到 result(结果) 中
string = [];
for (let i = 0, j; i < decryptPool.length; i++) {
for (j = 0; j < desubLength; j++) {
const char = i * j % 2 === 0 ?
decryptPool[i][j * 2] + decryptPool[i][j * 2 + 1] :
decryptPool[i][j * 2 + 1] + decryptPool[i][j * 2];
if (char) {
if (typeof string[j] === "undefined") string[j] = [];
string[j][i] = String.fromCharCode((char.charCodeAt(0) * 65536 + char.charCodeAt(1) + 0x100000000 - MTSeed.next()) % 65536);
}
}
}
for (let i = string.length - 1; i >= 0; i--) {
result += string[i].join("");
}
// 返回解密结果
return result;
} else {
// 如果解密字符串不存在就返回string
return string;
}
}
// encrypt 既可以用作加密 也可以用作解密,decrypt 既可以用作解密 也可以用作加密。
}
return Key;
})();
})();