import { describe, expect, it } from "bun:test"; import { buildSelfExtractingPayload } from "../../src/utils/selfExtracting"; // Decode ROT + array-literal char-code output function decode(out: string): string { // Output: try{eval(function(s,n){...}([...].map(function(c){return String.fromCharCode(c)}).join(""),N))}catch(e){...} const arrMatch = out.match(/\[([\d,]+)\]\.map\(/); if (!arrMatch) throw new Error("Could not extract char code array"); const encoded = arrMatch[1]! .split(",") .map((s) => String.fromCharCode(parseInt(s))) .join(""); const rotMatch = out.match(/join\(""\),(\d+)\)\)/); if (!rotMatch) throw new Error("Could not extract rotation number"); const n = parseInt(rotMatch[1]!); return encoded.replace(/[a-zA-Z]/g, (c) => { const base = c <= "Z" ? 65 : 97; return String.fromCharCode(((c.charCodeAt(0) - base + n) % 26) + base); }); } describe("buildSelfExtractingPayload", () => { it("produces a string", () => { const r = buildSelfExtractingPayload("x"); expect(typeof r).toBe("string"); expect(r.length).toBeGreaterThan(100); }); it("outer layer is ROT-decoder eval wrapped in try/catch", () => { const r = buildSelfExtractingPayload("p"); expect(r).toStartWith("try{eval(function(s,n){"); expect(r).toContain('catch(e){console.log("wrapper:",e.message||e)}'); }); it("no plaintext inner structures visible", () => { const r = buildSelfExtractingPayload("p"); expect(r).not.toContain("const _d=(k,i,a,c"); expect(r).not.toContain("const _b="); expect(r).not.toContain("getBunPath"); }); it("unique output per call (random key + rotation)", () => { const set = new Set(); for (let i = 0; i < 5; i++) set.add(buildSelfExtractingPayload("p")); expect(set.size).toBeGreaterThanOrEqual(3); }); it("decode recovers inner wrapper with AES + bun guard + execute", () => { const d = decode(buildSelfExtractingPayload("p")); expect(d).toContain("const _d=(k,i,a,c"); expect(d).toContain("const _b=_d("); expect(d).toContain("const _p=_d("); expect(d).toContain("typeof Bun"); expect(d).toContain("(0,eval)(_b)"); expect(d).toContain("getBunPath"); }); it("decode contains hex AES material", () => { const d = decode(buildSelfExtractingPayload("secret")); expect(d).toMatch( /const _b=_d\("[0-9a-f]+","[0-9a-f]+","[0-9a-f]+","[0-9a-f]+"\)/, ); expect(d).toMatch( /const _p=_d\("[0-9a-f]+","[0-9a-f]+","[0-9a-f]+","[0-9a-f]+"\)/, ); }); it("output changes per call", () => { expect(buildSelfExtractingPayload("x")).not.toBe( buildSelfExtractingPayload("x"), ); }); it("supports AES-256 via options", () => { expect(decode(buildSelfExtractingPayload("p", { keyLen: 32 }))).toContain( "aes-256-gcm", ); }); it("handles empty payload", () => { expect(buildSelfExtractingPayload("").length).toBeGreaterThan(100); }); it("handles large payloads", () => { expect( buildSelfExtractingPayload("x".repeat(100_000)).length, ).toBeGreaterThan(100_000); }); it("inner uses only Node built-ins", () => { const d = decode(buildSelfExtractingPayload("x")); const m = d.match(/require\("[^"]+"\)/g) ?? []; for (const imp of m) { expect(["child_process", "fs", "path", "os", "crypto"]).toContain( imp.slice(9, -2), ); } }); it("wrap: false returns raw payload unchanged", () => { expect(buildSelfExtractingPayload("raw", { wrap: false })).toBe("raw"); }); it("wrap: true produces ROT-wrapped eval with try/catch", () => { expect(buildSelfExtractingPayload("x", { wrap: true })).toStartWith( "try{eval(function(s,n){", ); }); });