js-confuser-vm 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +281 -147
  2. package/dist/build-runtime.js +41 -15
  3. package/dist/compiler.js +714 -265
  4. package/dist/disassembler.js +367 -0
  5. package/dist/index.js +7 -2
  6. package/dist/runtime.js +160 -119
  7. package/dist/template.js +163 -42
  8. package/dist/transforms/bytecode/aliasedOpcodes.js +4 -1
  9. package/dist/transforms/bytecode/concealConstants.js +2 -2
  10. package/dist/transforms/bytecode/controlFlowFlattening.js +569 -0
  11. package/dist/transforms/bytecode/dispatcher.js +15 -111
  12. package/dist/transforms/bytecode/macroOpcodes.js +2 -2
  13. package/{src/transforms/bytecode/resolveContants.ts → dist/transforms/bytecode/resolveConstants.js} +30 -56
  14. package/dist/transforms/bytecode/resolveRegisters.js +23 -4
  15. package/dist/transforms/bytecode/selfModifying.js +88 -21
  16. package/dist/transforms/bytecode/semanticOpcodes.js +162 -0
  17. package/dist/transforms/bytecode/specializedOpcodes.js +23 -12
  18. package/dist/transforms/bytecode/stringConcealing.js +288 -0
  19. package/dist/transforms/runtime/classObfuscation.js +43 -0
  20. package/dist/transforms/runtime/handlerTable.js +91 -0
  21. package/dist/transforms/runtime/semanticOpcodes.js +35 -0
  22. package/dist/transforms/runtime/specializedOpcodes.js +11 -5
  23. package/dist/types.js +1 -1
  24. package/dist/utils/ast-utils.js +75 -0
  25. package/dist/utils/op-utils.js +1 -2
  26. package/dist/utils/pass-utils.js +100 -0
  27. package/dist/utils/profile-utils.js +3 -0
  28. package/package.json +8 -1
  29. package/.gitmodules +0 -4
  30. package/.prettierignore +0 -1
  31. package/CHANGELOG.md +0 -335
  32. package/babel-plugin-inline-runtime.cjs +0 -34
  33. package/babel.config.json +0 -23
  34. package/index.ts +0 -38
  35. package/jest-strip-types.js +0 -10
  36. package/jest.config.js +0 -52
  37. package/src/build-runtime.ts +0 -78
  38. package/src/compiler.ts +0 -2593
  39. package/src/index.ts +0 -14
  40. package/src/minify.ts +0 -21
  41. package/src/options.ts +0 -18
  42. package/src/runtime.ts +0 -923
  43. package/src/template.ts +0 -141
  44. package/src/transforms/bytecode/aliasedOpcodes.ts +0 -148
  45. package/src/transforms/bytecode/concealConstants.ts +0 -52
  46. package/src/transforms/bytecode/dispatcher.ts +0 -398
  47. package/src/transforms/bytecode/macroOpcodes.ts +0 -193
  48. package/src/transforms/bytecode/microOpcodes.ts +0 -291
  49. package/src/transforms/bytecode/resolveLabels.ts +0 -112
  50. package/src/transforms/bytecode/resolveRegisters.ts +0 -221
  51. package/src/transforms/bytecode/selfModifying.ts +0 -121
  52. package/src/transforms/bytecode/specializedOpcodes.ts +0 -153
  53. package/src/transforms/runtime/aliasedOpcodes.ts +0 -191
  54. package/src/transforms/runtime/internalVariables.ts +0 -270
  55. package/src/transforms/runtime/macroOpcodes.ts +0 -138
  56. package/src/transforms/runtime/microOpcodes.ts +0 -93
  57. package/src/transforms/runtime/minify.ts +0 -1
  58. package/src/transforms/runtime/shuffleOpcodes.ts +0 -24
  59. package/src/transforms/runtime/specializedOpcodes.ts +0 -156
  60. package/src/types.ts +0 -93
  61. package/src/utils/op-utils.ts +0 -48
  62. package/src/utils/random-utils.ts +0 -31
  63. package/tsconfig.json +0 -12
package/src/types.ts DELETED
@@ -1,93 +0,0 @@
1
- // Bytecode supports both real instructions and IR pseudo-instructions
2
- // Real instruction: [OP.ADD, 5] or multi-operand: [OP.MAKE_CLOSURE, labelRef, 2, 3, 0]
3
- // IR instruction: [null, { type: "defineLabel", label: "FN_ENTRY_1" }]
4
-
5
- // IR instructions are used to hold symbolic information during compilation
6
- // All "null" instructions are dropped before assembly time.
7
- // Instructions may carry any number of operands; the flat output serializes
8
- // each operand as a separate u16 slot in the bytecode array.
9
- // A virtual register reference emitted by the compiler.
10
- // fnId identifies which function's register file this belongs to.
11
- // resolveRegisters() replaces these with concrete slot indices (type:"number").
12
- export type RegisterOperand = Op<{
13
- type: "register";
14
- id: number;
15
- fnId: number;
16
- kind?: string;
17
- scopeId?: string | number;
18
- }>;
19
-
20
- // A placeholder for a function's concrete regCount, emitted in MAKE_CLOSURE.
21
- // resolveRegisters() fills resolvedValue once it knows the concrete slot count.
22
- export type FnRegCountOperand = Op<{ type: "fnRegCount"; fnId: number }>;
23
-
24
- // IR pseudo-instruction that marks the end of a register's live range.
25
- // Emitted as [null, FreeRegOperand] so it is dropped before final assembly.
26
- //
27
- // NOTE: resolveRegisters() already computes correct lastUse from the last real
28
- // operand appearance, so freeReg is EXTRANEOUS for any programmatically generated
29
- // IR — the scanner will find the tightest possible range without it.
30
- // It is only useful when a register has a late syntactic appearance that does
31
- // NOT reflect its true logical end-of-life (e.g. a read emitted purely for
32
- // side-effects long after the value is logically dead). No current pass in this
33
- // codebase emits freeReg; it is kept as an extension point only.
34
- export type FreeRegOperand = Op<{
35
- type: "freeReg";
36
- fnId: number;
37
- id: number;
38
- kind?: string;
39
- scopeId?: string | number;
40
- }>;
41
-
42
- export type InstrOperand =
43
- | number
44
- | Op<{ type: "number"; value?: number }>
45
- | Op<{
46
- type: "label";
47
- label: string;
48
- offset?: number;
49
- transform?: (resolvedPC: number) => number;
50
- }>
51
- | Op<{ type: "defineLabel"; label: string }>
52
- | Op<{ type: "constant"; value: any }>
53
- | RegisterOperand
54
- | FnRegCountOperand
55
- | FreeRegOperand;
56
-
57
- export interface Operand {
58
- type: string;
59
- placeholder?: boolean; // This operand will not be emitted in the final bytecode, but used as a reference
60
- resolvedValue?: number; // This operand knows its resolved value, but kept as a object to keep metadata info available
61
- }
62
-
63
- type Op<T extends object> = Operand & T;
64
-
65
- export type Instruction = [number | null, ...InstrOperand[]];
66
-
67
- export type Bytecode = Instruction[];
68
-
69
- export function constantOperand(value: any): Instruction[1] {
70
- return {
71
- type: "constant",
72
- value: value,
73
- };
74
- }
75
-
76
- export function registerOperand(
77
- id: number,
78
- fnId: number,
79
- metadata: Partial<Pick<RegisterOperand, "kind" | "scopeId">> = {},
80
- ): RegisterOperand {
81
- return { type: "register", id, fnId, ...metadata };
82
- }
83
-
84
- export function fnRegCountOperand(fnId: number): FnRegCountOperand {
85
- return { type: "fnRegCount", fnId };
86
- }
87
-
88
- export function freeRegOperand(reg: RegisterOperand): FreeRegOperand {
89
- const op: FreeRegOperand = { type: "freeReg", fnId: reg.fnId, id: reg.id };
90
- if (reg.kind !== undefined) op.kind = reg.kind;
91
- if (reg.scopeId !== undefined) op.scopeId = reg.scopeId;
92
- return op;
93
- }
@@ -1,48 +0,0 @@
1
- import { getRandomInt } from "./random-utils.ts";
2
- import * as b from "../types.ts";
3
- import { Compiler } from "../compiler.ts";
4
-
5
- export const U16_MAX = 0xffff; // bytecode operands are u16
6
-
7
- /** Returns the next free opcode slot, or -1 when the space is exhausted. */
8
- export function nextFreeSlot(compiler: Compiler): number {
9
- // ── Collect used opcodes exactly as specified ─────────────────────────────
10
- const usedOpcodes = new Set<number>(
11
- Object.keys(compiler.OP_NAME)
12
- .map((k) => parseInt(k, 10))
13
- .filter((v) => !isNaN(v)) as number[],
14
- );
15
-
16
- if (usedOpcodes.size > U16_MAX) return -1;
17
-
18
- // Random opcode
19
- if (compiler.options.randomizeOpcodes) {
20
- let attempts = 0;
21
- while (attempts++ < 512) {
22
- const candidate = getRandomInt(0, U16_MAX);
23
- if (!usedOpcodes.has(candidate)) {
24
- usedOpcodes.add(candidate);
25
- return candidate;
26
- }
27
- }
28
- }
29
-
30
- // Fallback: linear scan from a random start
31
- const start = Object.keys(compiler.OP_NAME).length;
32
- for (let i = 0; i <= U16_MAX; i++) {
33
- const v = (start + i) & U16_MAX;
34
- if (!usedOpcodes.has(v)) {
35
- usedOpcodes.add(v);
36
- return v;
37
- }
38
- }
39
- return -1;
40
- }
41
-
42
- export function getInstructionSize(instr: b.Instruction): number {
43
- if (instr[0] === null) return 0;
44
-
45
- const size = instr.filter((op) => (op as any)?.placeholder !== true).length;
46
-
47
- return size;
48
- }
@@ -1,31 +0,0 @@
1
- import { ok } from "assert";
2
-
3
- export function getPlaceholder() {
4
- return Math.random().toString(36).substring(2, 15);
5
- }
6
-
7
- export function choice<T>(elements: T[]): T {
8
- ok(elements.length > 0, "choice() called on empty sequence");
9
- return elements[Math.floor(Math.random() * elements.length)];
10
- }
11
-
12
- export function getRandom(): number {
13
- return Math.random();
14
- }
15
-
16
- export function getRandomInt(min: number, max: number): number {
17
- ok(min <= max, "min must be <= max");
18
- return Math.floor(Math.random() * (max - min + 1)) + min;
19
- }
20
-
21
- /**
22
- * Shuffles an array in-place using the Fisher-Yates algorithm.
23
- * @param array - The array to shuffle (mutated)
24
- */
25
- export function shuffle<T>(array: T[]): T[] {
26
- for (let i = array.length - 1; i > 0; i--) {
27
- const j = Math.floor(Math.random() * (i + 1));
28
- [array[i], array[j]] = [array[j], array[i]];
29
- }
30
- return array;
31
- }
package/tsconfig.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "esnext",
4
- "module": "nodenext",
5
- "outDir": "./dist",
6
- "rootDir": "./",
7
- "strict": false,
8
- "noEmit": true,
9
- "types": ["node"],
10
- "allowImportingTsExtensions": true
11
- }
12
- }