mirror of
https://github.com/geekgeekrun/geekgeekrun.git
synced 2026-09-04 23:17:39 +08:00
update laodeng
This commit is contained in:
+123
-114
@@ -1,125 +1,134 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { PuppeteerExtraPlugin } = require("puppeteer-extra-plugin");
|
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 stealthScript = () => {
|
||||||
* ----------------------------------------------------- */
|
"use strict";
|
||||||
const nativeSourceMap = new WeakMap();
|
/* -------------------------------------------------------
|
||||||
|
* 1. 保存原生 Function.prototype.toString
|
||||||
|
* ----------------------------------------------------- */
|
||||||
|
const nativeFunctionToString = Function.prototype.toString;
|
||||||
|
|
||||||
/* -------------------------------------------------------
|
/* -------------------------------------------------------
|
||||||
* 3. 注册伪原生源码
|
* 2. WeakMap:函数 → 伪原生源码
|
||||||
* ----------------------------------------------------- */
|
* ----------------------------------------------------- */
|
||||||
const registerNativeSource = (fn, source) => {
|
const nativeSourceMap = new WeakMap();
|
||||||
try {
|
|
||||||
nativeSourceMap.set(fn, source);
|
|
||||||
} catch (_) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* -------------------------------------------------------
|
/* -------------------------------------------------------
|
||||||
* 4. 劫持 Function.prototype.toString
|
* 3. 注册伪原生源码
|
||||||
* ----------------------------------------------------- */
|
* ----------------------------------------------------- */
|
||||||
Object.defineProperty(Function.prototype, "toString", {
|
const registerNativeSource = (fn, source) => {
|
||||||
configurable: true,
|
try {
|
||||||
writable: true,
|
nativeSourceMap.set(fn, source);
|
||||||
value: function toString() {
|
} catch (_) {}
|
||||||
if (nativeSourceMap.has(this)) {
|
};
|
||||||
return nativeSourceMap.get(this);
|
|
||||||
}
|
|
||||||
return nativeFunctionToString.call(this);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -------------------------------------------------------
|
/* -------------------------------------------------------
|
||||||
* 5. 伪装 Function.prototype.toString 自身
|
* 4. 劫持 Function.prototype.toString
|
||||||
* ----------------------------------------------------- */
|
* ----------------------------------------------------- */
|
||||||
registerNativeSource(
|
Object.defineProperty(Function.prototype, "toString", {
|
||||||
Function.prototype.toString,
|
configurable: true,
|
||||||
nativeFunctionToString.toString(),
|
writable: true,
|
||||||
);
|
value: function toString() {
|
||||||
|
if (nativeSourceMap.has(this)) {
|
||||||
/* -------------------------------------------------------
|
return nativeSourceMap.get(this);
|
||||||
* 6. stealthify:包装函数但保持“原生外观”
|
}
|
||||||
* ----------------------------------------------------- */
|
return nativeFunctionToString.call(this);
|
||||||
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] }",
|
|
||||||
);
|
|
||||||
})();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------------------
|
||||||
|
* 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 {
|
class Plugin extends PuppeteerExtraPlugin {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@geekgeekrun/puppeteer-extra-plugin-laodeng",
|
"name": "@geekgeekrun/puppeteer-extra-plugin-laodeng",
|
||||||
"version": "0.0.1",
|
"version": "0.0.2",
|
||||||
"description": "laodeng",
|
"description": "laodeng",
|
||||||
"main": "./index.js",
|
"main": "./index.js",
|
||||||
"author": "geekgeekrun",
|
"author": "geekgeekrun",
|
||||||
|
|||||||
Reference in New Issue
Block a user