65 lines
2.9 KiB
JavaScript
65 lines
2.9 KiB
JavaScript
// 修正跨 realm 陷阱:沙箱不注入外层内置,让 context 自带 intrinsic。
|
||
const fs = require("fs"), vm = require("vm"), path = require("path");
|
||
const src = fs.readFileSync(path.join("out/captcha_net", "js_07_rm_static_captcha_js_encrypt_ee7d2a41_js.js"), "utf-8");
|
||
|
||
// 只放非内置的宿主能力;String/Object/Promise/Uint8Array 等由 context 自己生成
|
||
const sandbox = {
|
||
console,
|
||
setTimeout, clearTimeout, setImmediate, queueMicrotask,
|
||
Buffer,
|
||
btoa: (s) => Buffer.from(s, "binary").toString("base64"),
|
||
atob: (s) => Buffer.from(s, "base64").toString("binary"),
|
||
};
|
||
vm.createContext(sandbox); // 此时 sandbox 拥有自己的 intrinsic (String/Object/Uint8Array/Promise...)
|
||
sandbox.window = sandbox;
|
||
sandbox.self = sandbox;
|
||
sandbox.global = sandbox;
|
||
|
||
try { vm.runInContext(src, sandbox, { filename: "encrypt.js", timeout: 30000 }); }
|
||
catch (e) { console.log("[run-err]", e.message); }
|
||
|
||
const f = sandbox.webpackJsonp[0][1]["088e"];
|
||
const rq = (id) => id === "b639" ? { Buffer } : id === "dd40" ? (x) => x : {};
|
||
const m = { exports: {} };
|
||
try { f(m, m.exports, rq); } catch (e) { console.log("[factory-err]", e.message); }
|
||
|
||
const Jose = sandbox.Jose;
|
||
const j = (typeof Jose === "function") ? new Jose() : Jose;
|
||
console.log("Jose ok:", !!j, "call:", typeof j.call);
|
||
|
||
// 在沙箱内构造 Uint8Array(同 realm)
|
||
const KEY = "c7b645db-65e8-401f-b38c-4c07c5fff247";
|
||
vm.runInContext('(function(){globalThis.__makeU8=function(s){return new Uint8Array(Array.prototype.map.call(s,c=>c.charCodeAt(0)));};globalThis.__b64=function(u){var s="";for(var i=0;i<u.length;i++)s+=String.fromCharCode(u[i]);return btoa(s);};})()', sandbox);
|
||
|
||
// 整个调用在沙箱内执行(cb 也同 realm),外部轮询
|
||
function runInBox(label, fnName, inputExpr) {
|
||
sandbox.__done = null;
|
||
sandbox.__res = null;
|
||
const script = `
|
||
(function(){
|
||
var KEY=${JSON.stringify(KEY)};
|
||
globalThis.__done=null; globalThis.__res=null;
|
||
try {
|
||
Jose.call(${JSON.stringify(fnName)}, [
|
||
${inputExpr},
|
||
KEY,
|
||
{ suc: function(v){ try{globalThis.__res=__b64(v);}catch(e){globalThis.__res='(b64fail)'+(v&&v.length);} globalThis.__done='ok'; },
|
||
err: function(e){ globalThis.__res='ERR:'+(e&&e.message||e); globalThis.__done='err'; } }
|
||
]);
|
||
} catch(e){ globalThis.__res='THROW:'+(e&&e.message||e); globalThis.__done='throw'; }
|
||
})();
|
||
`;
|
||
try { vm.runInContext(script, sandbox); } catch (e) { console.log(`[${label} script-err]`, e.message); return; }
|
||
// 轮询
|
||
const t0 = Date.now();
|
||
const iv = setInterval(() => {
|
||
if (sandbox.__done || Date.now() - t0 > 4000) {
|
||
clearInterval(iv);
|
||
console.log(`${label}: done=${sandbox.__done} res=${String(sandbox.__res).slice(0, 110)}`);
|
||
}
|
||
}, 50);
|
||
}
|
||
|
||
runInBox("$encrypt U8+key", "$encrypt", "__makeU8('{\"a\":1}')");
|
||
setTimeout(() => runInBox("$encrypt str+key", "$encrypt", "'{\"a\":1}'"), 4500);
|