reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,253 @@
#!/usr/bin/env node
'use strict';
const fs = require('fs');
const path = require('path');
function parseArgs(argv) {
const args = { param: 'sign', apiPattern: '/api/', types: 'fetch,xhr,urlsearchparams,cookie,storage,time-random,dynamic-code,websocket,postmessage', out: '' };
for (let i = 2; i < argv.length; i++) {
const a = argv[i];
if (a === '--param') args.param = argv[++i] || 'sign';
else if (a === '--api-pattern') args.apiPattern = argv[++i] || '/api/';
else if (a === '--types') args.types = argv[++i] || args.types;
else if (a === '--out') args.out = argv[++i] || '';
else if (a === '--help' || a === '-h') args.help = true;
else throw new Error(`未知参数:${a}`);
}
return args;
}
function usage() {
return `用法:
node scripts/generate_hook_templates.js --param sign --api-pattern /api/ --types fetch,xhr,cookie,storage
node scripts/generate_hook_templates.js --param a_bogus --api-pattern /web/api --out case/hooks/hooks.js`;
}
function q(v) { return JSON.stringify(String(v)); }
function section(name, code) { return `\n// ===== ${name} =====\n${code.trim()}\n`; }
function snippets(ctx) {
return {
fetch: section('fetch 请求写入定位', `
(() => {
const targetParam = ${q(ctx.param)};
const apiKeyword = ${q(ctx.apiPattern)};
const rawFetch = window.fetch;
window.fetch = function patchedFetch(input, init) {
const url = typeof input === "string" ? input : (input && input.url) || "";
const body = init && init.body;
if (String(url).includes(apiKeyword) || String(url).includes(targetParam) || String(body || "").includes(targetParam)) {
console.group("[fetch 命中]", url);
console.log("input =", input);
console.log("init =", init);
console.trace("fetch 调用栈");
console.groupEnd();
debugger;
}
return rawFetch.apply(this, arguments);
};
})();`),
xhr: section('XMLHttpRequest 请求写入定位', `
(() => {
const targetParam = ${q(ctx.param)};
const apiKeyword = ${q(ctx.apiPattern)};
const rawOpen = XMLHttpRequest.prototype.open;
const rawSend = XMLHttpRequest.prototype.send;
const rawSetHeader = XMLHttpRequest.prototype.setRequestHeader;
XMLHttpRequest.prototype.open = function patchedOpen(method, url) {
this.__reverse_method = method;
this.__reverse_url = String(url || "");
return rawOpen.apply(this, arguments);
};
XMLHttpRequest.prototype.setRequestHeader = function patchedSetRequestHeader(name, value) {
if (String(name).includes(targetParam) || String(value).includes(targetParam)) {
console.group("[XHR Header 命中]", this.__reverse_url);
console.log(name, value);
console.trace("setRequestHeader 调用栈");
console.groupEnd();
debugger;
}
return rawSetHeader.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function patchedSend(body) {
const url = this.__reverse_url || "";
if (url.includes(apiKeyword) || url.includes(targetParam) || String(body || "").includes(targetParam)) {
console.group("[XHR send 命中]", this.__reverse_method, url);
console.log("body =", body);
console.trace("send 调用栈");
console.groupEnd();
debugger;
}
return rawSend.apply(this, arguments);
};
})();`),
urlsearchparams: section('URLSearchParams 与 FormData 参数写入定位', `
(() => {
const targetParam = ${q(ctx.param)};
for (const Ctor of [window.URLSearchParams, window.FormData].filter(Boolean)) {
for (const method of ["append", "set"]) {
const raw = Ctor.prototype[method];
if (typeof raw !== "function") continue;
Ctor.prototype[method] = function patchedParamWrite(name, value) {
if (String(name) === targetParam || String(value).includes(targetParam)) {
console.group("[" + Ctor.name + "." + method + " 命中]", name);
console.log("value =", value);
console.trace("参数写入调用栈");
console.groupEnd();
debugger;
}
return raw.apply(this, arguments);
};
}
}
})();`),
cookie: section('Cookie 读写定位', `
(() => {
const targetParam = ${q(ctx.param)};
const desc = Object.getOwnPropertyDescriptor(Document.prototype, "cookie");
if (!desc || !desc.set || !desc.get) return;
Object.defineProperty(document, "cookie", {
configurable: true,
enumerable: desc.enumerable,
get() {
const value = desc.get.call(document);
if (String(value).includes(targetParam)) console.trace("document.cookie 读取命中");
return value;
},
set(value) {
if (String(value).includes(targetParam)) {
console.group("[cookie 写入命中]");
console.log(value);
console.trace("cookie 写入调用栈");
console.groupEnd();
debugger;
}
return desc.set.call(document, value);
}
});
})();`),
storage: section('Storage 读写定位', `
(() => {
const keys = [${q(ctx.param)}, "token", "device", "fingerprint"];
for (const storageName of ["localStorage", "sessionStorage"]) {
const storage = window[storageName];
if (!storage) continue;
for (const method of ["getItem", "setItem", "removeItem"]) {
const raw = storage[method];
storage[method] = function patchedStorage(key, value) {
if (keys.some(k => String(key).includes(k))) {
console.group("[" + storageName + "." + method + " 命中]", key);
console.log("value =", value);
console.trace("Storage 调用栈");
console.groupEnd();
}
return raw.apply(this, arguments);
};
}
}
})();`),
'time-random': section('时间与随机数定位', `
(() => {
const rawDateNow = Date.now;
Date.now = function patchedDateNow() {
const ret = rawDateNow.apply(this, arguments);
console.log("[Date.now]", ret);
console.trace("Date.now 调用栈");
return ret;
};
const rawRandom = Math.random;
Math.random = function patchedMathRandom() {
const ret = rawRandom.apply(this, arguments);
console.log("[Math.random]", ret);
console.trace("Math.random 调用栈");
return ret;
};
if (window.crypto && crypto.getRandomValues) {
const rawGetRandomValues = crypto.getRandomValues;
crypto.getRandomValues = function patchedGetRandomValues(arr) {
const ret = rawGetRandomValues.apply(this, arguments);
console.log("[crypto.getRandomValues]", Array.from(arr));
console.trace("crypto.getRandomValues 调用栈");
return ret;
};
}
})();`),
'dynamic-code': section('动态代码定位', `
(() => {
const rawEval = window.eval;
window.eval = function patchedEval(code) {
console.log("[eval]", String(code).slice(0, 500));
console.trace("eval 调用栈");
debugger;
return rawEval.apply(this, arguments);
};
const rawFunction = window.Function;
window.Function = new Proxy(rawFunction, {
construct(target, args) {
console.log("[new Function]", args);
console.trace("new Function 调用栈");
debugger;
return Reflect.construct(target, args);
},
apply(target, thisArg, args) {
console.log("[Function]", args);
console.trace("Function 调用栈");
debugger;
return Reflect.apply(target, thisArg, args);
}
});
})();`),
websocket: section('WebSocket 定位', `
(() => {
if (!window.WebSocket) return;
const rawWS = window.WebSocket;
window.WebSocket = new Proxy(rawWS, {
construct(target, args) {
console.log("[WebSocket 创建]", args);
console.trace("WebSocket 调用栈");
return Reflect.construct(target, args);
}
});
})();`),
postmessage: section('postMessage 定位', `
(() => {
const rawPostMessage = window.postMessage;
if (!rawPostMessage) return;
window.postMessage = function patchedPostMessage(message, targetOrigin, transfer) {
console.log("[postMessage]", message, targetOrigin);
console.trace("postMessage 调用栈");
return rawPostMessage.apply(this, arguments);
};
})();`),
};
}
function build(args) {
const map = snippets({ param: args.param, apiPattern: args.apiPattern });
const chosen = args.types.split(',').map(s => s.trim().toLowerCase()).filter(Boolean);
const unknown = chosen.filter(t => !map[t]);
if (unknown.length) throw new Error(`未知 Hook 类型:${unknown.join(', ')}`);
return `// Web JS 逆向定位 Hook 模板
// 目标参数:${args.param}
// API 关键字:${args.apiPattern}
// 使用后请及时移除;只用于授权调试和调用栈定位。
${chosen.map(t => map[t]).join('\n')}`;
}
try {
const args = parseArgs(process.argv);
if (args.help) { console.log(usage()); process.exit(0); }
const content = build(args);
if (args.out) {
fs.mkdirSync(path.dirname(path.resolve(args.out)), { recursive: true });
fs.writeFileSync(args.out, content, 'utf8');
console.log(`已写入 Hook 模板:${path.resolve(args.out)}`);
} else {
process.stdout.write(content);
}
} catch (err) {
console.error(err.message || String(err));
console.error(usage());
process.exit(1);
}