mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-06-28 02:41:47 +08:00
update laodeng
This commit is contained in:
@@ -1,125 +1,134 @@
|
||||
"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();
|
||||
// 定义脚本内容,避免重复定义
|
||||
const stealthScript = () => {
|
||||
"use strict";
|
||||
/* -------------------------------------------------------
|
||||
* 1. 保存原生 Function.prototype.toString
|
||||
* ----------------------------------------------------- */
|
||||
const nativeFunctionToString = Function.prototype.toString;
|
||||
|
||||
/* -------------------------------------------------------
|
||||
* 3. 注册伪原生源码
|
||||
* ----------------------------------------------------- */
|
||||
const registerNativeSource = (fn, source) => {
|
||||
try {
|
||||
nativeSourceMap.set(fn, source);
|
||||
} catch (_) {}
|
||||
};
|
||||
/* -------------------------------------------------------
|
||||
* 2. WeakMap:函数 → 伪原生源码
|
||||
* ----------------------------------------------------- */
|
||||
const nativeSourceMap = new WeakMap();
|
||||
|
||||
/* -------------------------------------------------------
|
||||
* 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);
|
||||
},
|
||||
});
|
||||
/* -------------------------------------------------------
|
||||
* 3. 注册伪原生源码
|
||||
* ----------------------------------------------------- */
|
||||
const registerNativeSource = (fn, source) => {
|
||||
try {
|
||||
nativeSourceMap.set(fn, source);
|
||||
} catch (_) {}
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------
|
||||
* 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] }",
|
||||
);
|
||||
})();
|
||||
/* -------------------------------------------------------
|
||||
* 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] }",
|
||||
);
|
||||
};
|
||||
|
||||
async function handle(p) {
|
||||
// 1. 立即执行一次(针对当前已有的文档,防止错过)
|
||||
try {
|
||||
await p.evaluate(stealthScript);
|
||||
} catch (e) {
|
||||
// 如果当前页面还没准备好,忽略错误
|
||||
}
|
||||
// 2. 注册为新文档脚本(针对未来的导航)
|
||||
await p.evaluateOnNewDocument(stealthScript);
|
||||
}
|
||||
|
||||
class Plugin extends PuppeteerExtraPlugin {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@geekgeekrun/puppeteer-extra-plugin-laodeng",
|
||||
"version": "0.0.1",
|
||||
"version": "0.0.2",
|
||||
"description": "laodeng",
|
||||
"main": "./index.js",
|
||||
"author": "geekgeekrun",
|
||||
|
||||
Reference in New Issue
Block a user