mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-09-05 07:27:35 +08:00
149 lines
4.5 KiB
JavaScript
149 lines
4.5 KiB
JavaScript
"use strict";
|
|
|
|
const { PuppeteerExtraPlugin } = require("puppeteer-extra-plugin");
|
|
async function handle(p) {
|
|
await p.evaluateOnNewDocument(() => {
|
|
(() => {
|
|
"use strict";
|
|
/* -------------------------------------------------------
|
|
* 1. 保存原生 Function.prototype.toString
|
|
* ----------------------------------------------------- */
|
|
const nativeFunctionToString = Function.prototype.toString;
|
|
|
|
/* -------------------------------------------------------
|
|
* 2. WeakMap:函数 → 伪原生源码
|
|
* ----------------------------------------------------- */
|
|
const nativeSourceMap = new WeakMap();
|
|
|
|
/* -------------------------------------------------------
|
|
* 3. 注册伪原生源码
|
|
* ----------------------------------------------------- */
|
|
const registerNativeSource = (fn, source) => {
|
|
try {
|
|
nativeSourceMap.set(fn, source);
|
|
} catch (_) {}
|
|
};
|
|
|
|
/* -------------------------------------------------------
|
|
* 4. 劫持 Function.prototype.toString
|
|
* ----------------------------------------------------- */
|
|
Object.defineProperty(Function.prototype, "toString", {
|
|
configurable: true,
|
|
writable: true,
|
|
value: function toString() {
|
|
if (nativeSourceMap.has(this)) {
|
|
return nativeSourceMap.get(this);
|
|
}
|
|
return nativeFunctionToString.call(this);
|
|
},
|
|
});
|
|
|
|
/* -------------------------------------------------------
|
|
* 5. 伪装 Function.prototype.toString 自身
|
|
* ----------------------------------------------------- */
|
|
registerNativeSource(
|
|
Function.prototype.toString,
|
|
nativeFunctionToString.toString(),
|
|
);
|
|
|
|
/* -------------------------------------------------------
|
|
* 6. stealthify:包装函数但保持“原生外观”
|
|
* ----------------------------------------------------- */
|
|
const stealthify = (obj, prop, handler) => {
|
|
const original = obj[prop];
|
|
if (typeof original !== "function") return;
|
|
|
|
const wrapped = function (...args) {
|
|
return handler.call(this, original, args);
|
|
};
|
|
const namePropertyDescriptor = Object.getOwnPropertyDescriptor(
|
|
wrapped,
|
|
"name",
|
|
);
|
|
// 处理函数 name 属性
|
|
Object.defineProperty(wrapped, "name", {
|
|
...namePropertyDescriptor,
|
|
value: prop,
|
|
});
|
|
// 保留 prototype(某些函数有)
|
|
try {
|
|
Object.setPrototypeOf(wrapped, Object.getPrototypeOf(original));
|
|
} catch (_) {}
|
|
|
|
// 注册伪原生源码(直接复用原函数的 native 表现)
|
|
registerNativeSource(wrapped, nativeFunctionToString.call(original));
|
|
|
|
// 用 defineProperty 保持 descriptor 接近原生
|
|
const desc = Object.getOwnPropertyDescriptor(obj, prop);
|
|
Object.defineProperty(obj, prop, {
|
|
...desc,
|
|
value: wrapped,
|
|
});
|
|
};
|
|
|
|
/* -------------------------------------------------------
|
|
* 7. 示例:stealth console.log / debug / info
|
|
* ----------------------------------------------------- */
|
|
const filterConsoleArgs = (args) =>
|
|
args.map((arg) => {
|
|
if (arg && typeof arg === "object") {
|
|
// 防止 getter / Proxy / 大对象触发
|
|
return {};
|
|
}
|
|
return arg;
|
|
});
|
|
|
|
[
|
|
"log",
|
|
"debug",
|
|
"info",
|
|
"warn",
|
|
"error",
|
|
"dir",
|
|
"table",
|
|
"debug",
|
|
].forEach((name) => {
|
|
stealthify(console, name, (original, args) => {
|
|
// ❗不传递原始对象,避免 DevTools / CDP 展开
|
|
return original.apply(console, filterConsoleArgs(args));
|
|
});
|
|
});
|
|
|
|
/* -------------------------------------------------------
|
|
* 8. 防御性补丁(可选但强烈建议)
|
|
* ----------------------------------------------------- */
|
|
|
|
// 防止检测 toString 被替换
|
|
registerNativeSource(
|
|
registerNativeSource,
|
|
"function registerNativeSource() { [native code] }",
|
|
);
|
|
})();
|
|
});
|
|
}
|
|
|
|
class Plugin extends PuppeteerExtraPlugin {
|
|
constructor() {
|
|
super();
|
|
}
|
|
|
|
get name() {
|
|
return "laodeng";
|
|
}
|
|
|
|
async onBrowser(browser) {
|
|
const pages = await browser.pages();
|
|
for (const p of pages) {
|
|
await handle(p);
|
|
}
|
|
}
|
|
|
|
async onPageCreated(p) {
|
|
await handle(p);
|
|
}
|
|
}
|
|
|
|
module.exports = function (pluginConfig) {
|
|
return new Plugin(pluginConfig);
|
|
};
|