ksjsb/tools/jose_run.js
2026-07-30 20:25:56 +08:00

93 lines
4.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 在 Node 里跑 encrypt.js 的 webpack chunk拿到 window.Jose 并实测 $encrypt。
// encrypt.js = (window.webpackJsonp||[]).push([["encrypt"],{"088e":factory}])
// 我们 stub window + 拦截 push 取出 088e factory用 stub require 执行它。
const fs = require("fs");
const path = require("path");
const vm = require("vm");
const encPath = path.join(__dirname, "..", "out", "captcha_net",
"js_07_rm_static_captcha_js_encrypt_ee7d2a41_js.js");
const src = fs.readFileSync(encPath, "utf-8");
const win = {};
const ctx = {
window: win, self: win, console,
Uint8Array, ArrayBuffer, Uint32Array, Uint16Array, Int8Array, Int32Array,
Uint16Array, Float32Array, Float64Array, DataView, Buffer,
setTimeout, clearTimeout, setImmediate, Promise, Math, Date, JSON, Object, Array,
String, Number, Boolean, RegExp, Error, Function, Symbol, Reflect, Proxy, Map, Set, WeakMap, WeakSet,
parseInt, parseFloat, isNaN, isFinite, undefined,
btoa: (s) => Buffer.from(s, "binary").toString("base64"),
atob: (s) => Buffer.from(s, "base64").toString("binary"),
};
vm.createContext(ctx);
ctx.global = ctx;
ctx.window = ctx; // UMD 把 Jose 挂到第一参 window 上 -> 挂到 ctx
ctx.self = ctx;
try { vm.runInContext(src, ctx, { filename: "encrypt.js", timeout: 30000 }); }
catch (e) { console.log("[run-err]", e.message); }
console.log("webpackJsonp len=", (ctx.webpackJsonp || []).length);
// 取出 088e factory
let factory = null;
try {
const pushed = ctx.webpackJsonp[0]; // [["encrypt"], { "088e": factory }]
factory = pushed[1]["088e"];
console.log("got 088e factory:", typeof factory);
} catch (e) { console.log("[extract-err]", e.message); }
if (typeof factory === "function") {
// stub require
const requireStub = (id) => {
if (id === "b639") return { Buffer };
if (id === "dd40") return (x) => x; // identity wrapper
return {}; // core-js polyfills -> no-op
};
const mod = { exports: {} };
try {
factory(mod, mod.exports, requireStub);
console.log("[factory] ran ok. window.Jose type =", typeof ctx.Jose);
} catch (e) {
console.log("[factory-err]", e.message, "\n", e.stack.split("\n").slice(0, 6).join("\n"));
}
const Jose = ctx.Jose;
if (Jose) {
console.log("Jose type:", typeof Jose, "keys:", Object.keys(Jose));
const j = (typeof Jose === "function") ? new Jose() : Jose;
console.log("instance proto:", Object.getOwnPropertyNames(Object.getPrototypeOf(j)));
const rg = j.realm && j.realm.global;
if (rg) {
console.log("realm.global keys:", Object.keys(rg));
console.log("$encrypt type:", typeof rg["$encrypt"], " $decrypt type:", typeof rg["$decrypt"]);
console.log("has String?", typeof rg.String, " Math?", typeof rg.Math, " JSON?", typeof rg.JSON);
}
// 尝试把宿主 builtins 灌进 realm.global
if (rg) {
for (const k of ["String","Number","Boolean","Array","Object","Math","JSON","Date","parseInt","parseFloat","encodeURIComponent","decodeURIComponent","Error","RegExp","Map","Set","Uint8Array","ArrayBuffer","DataView"]) {
try { if (rg[k] === undefined) rg[k] = ctx[k]; } catch (_) {}
}
console.log("after seed: String?", typeof rg.String);
}
// 实测 $encrypt
const data = new Uint8Array([123, 34, 97, 34, 58, 49, 125]); // {"a":1}
const key = "c7b645db-65e8-401f-b38c-4c07c5fff247";
let out, errInfo;
const p = new Promise((res) => {
try {
j.call("$encrypt", [data, key, { suc: (v) => { out = v; res(); }, err: (e) => { errInfo = e; res(); } }]);
} catch (e) { errInfo = e; res(); }
});
Promise.race([p, new Promise((r) => setTimeout(() => r(), 4000))]).then(() => {
if (errInfo) console.log("[encrypt-err]", errInfo && errInfo.message ? errInfo.message : errInfo);
if (out) {
const b64 = Buffer.from(out).toString("base64");
console.log("verifyParam(b64) len=", b64.length, " head=", b64.slice(0, 80));
} else {
console.log("[no output]");
}
});
}
}