93 lines
4.0 KiB
JavaScript
93 lines
4.0 KiB
JavaScript
// 在 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]");
|
||
}
|
||
});
|
||
}
|
||
}
|