js-confuser-vm 0.1.0 → 0.1.1

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 (58) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +75 -94
  3. package/bench.ts +146 -0
  4. package/disassemble.ts +12 -0
  5. package/dist/build-runtime.js +41 -15
  6. package/dist/compiler.js +134 -60
  7. package/dist/disassembler.js +317 -0
  8. package/dist/index.js +7 -2
  9. package/dist/runtime.js +68 -46
  10. package/dist/template.js +116 -0
  11. package/dist/transforms/bytecode/aliasedOpcodes.js +4 -1
  12. package/dist/transforms/bytecode/controlFlowFlattening.js +451 -0
  13. package/dist/transforms/bytecode/dispatcher.js +13 -109
  14. package/dist/transforms/bytecode/macroOpcodes.js +2 -2
  15. package/dist/transforms/bytecode/resolveConstants.js +100 -0
  16. package/dist/transforms/bytecode/resolveRegisters.js +4 -0
  17. package/dist/transforms/bytecode/semanticOpcodes.js +162 -0
  18. package/dist/transforms/bytecode/specializedOpcodes.js +18 -10
  19. package/dist/transforms/bytecode/stringConcealing.js +110 -0
  20. package/dist/transforms/runtime/classObfuscation.js +43 -0
  21. package/dist/transforms/runtime/handlerTable.js +91 -0
  22. package/dist/transforms/runtime/semanticOpcodes.js +35 -0
  23. package/dist/transforms/runtime/specializedOpcodes.js +11 -5
  24. package/dist/types.js +1 -1
  25. package/dist/utils/ast-utils.js +14 -0
  26. package/dist/utils/op-utils.js +0 -2
  27. package/dist/utils/pass-utils.js +100 -0
  28. package/dist/utils/profile-utils.js +3 -0
  29. package/index.ts +22 -17
  30. package/jest.config.js +14 -2
  31. package/output.disassembled.js +41 -0
  32. package/package.json +2 -1
  33. package/src/build-runtime.ts +113 -78
  34. package/src/compiler.ts +2703 -2593
  35. package/src/disassembler.ts +329 -0
  36. package/src/index.ts +12 -2
  37. package/src/options.ts +7 -1
  38. package/src/runtime.ts +84 -51
  39. package/src/template.ts +125 -1
  40. package/src/transforms/bytecode/aliasedOpcodes.ts +4 -1
  41. package/src/transforms/bytecode/controlFlowFlattening.ts +566 -0
  42. package/src/transforms/bytecode/dispatcher.ts +19 -125
  43. package/src/transforms/bytecode/macroOpcodes.ts +2 -2
  44. package/src/transforms/bytecode/resolveRegisters.ts +5 -0
  45. package/src/transforms/bytecode/specializedOpcodes.ts +22 -11
  46. package/src/transforms/bytecode/stringConcealing.ts +130 -0
  47. package/src/transforms/runtime/classObfuscation.ts +59 -0
  48. package/src/transforms/runtime/specializedOpcodes.ts +14 -9
  49. package/src/types.ts +42 -1
  50. package/src/utils/ast-utils.ts +19 -0
  51. package/src/utils/op-utils.ts +0 -2
  52. package/src/utils/pass-utils.ts +126 -0
  53. package/src/utils/profile-utils.ts +3 -0
  54. package/tsconfig.json +1 -1
  55. package/src/transforms/bytecode/microOpcodes.ts +0 -291
  56. package/src/transforms/runtime/internalVariables.ts +0 -270
  57. package/src/transforms/runtime/microOpcodes.ts +0 -93
  58. /package/src/transforms/bytecode/{resolveContants.ts → resolveConstants.ts} +0 -0
@@ -1,93 +0,0 @@
1
- import * as t from "@babel/types";
2
- import traverseImport from "@babel/traverse";
3
- import { ok } from "assert";
4
- import { Compiler } from "../../compiler.ts";
5
- import { applyInternalVariablesToSwitchCase } from "./internalVariables.ts";
6
-
7
- const traverse = (traverseImport.default ||
8
- traverseImport) as typeof traverseImport.default;
9
-
10
- // Extract the real statement list from a SwitchCase consequent.
11
- function extractCaseBody(switchCase: t.SwitchCase): t.Statement[] {
12
- let stmts: t.Statement[];
13
- if (
14
- switchCase.consequent.length === 1 &&
15
- t.isBlockStatement(switchCase.consequent[0])
16
- ) {
17
- stmts = (switchCase.consequent[0] as t.BlockStatement).body;
18
- } else {
19
- stmts = switchCase.consequent as t.Statement[];
20
- }
21
- return stmts.filter((s) => !t.isBreakStatement(s) && !t.isEmptyStatement(s));
22
- }
23
-
24
- // Append a generated switch case for every entry in compiler.MICRO_OPS.
25
- // applyInteralVariablesToRuntime must run before this so that the source
26
- // case bodies are already using this._internals[index] instead of local vars.
27
- // Must be called BEFORE applyShuffleOpcodes so the new cases get shuffled.
28
- export function applyMicroOpcodes(ast: t.File, compiler: Compiler): void {
29
- if (!compiler.MICRO_OPS || Object.keys(compiler.MICRO_OPS).length === 0) {
30
- return;
31
- }
32
-
33
- let switchStatement: t.SwitchStatement | null = null;
34
- traverse(ast, {
35
- SwitchStatement(path) {
36
- if (path.node.leadingComments?.some((c) => c.value.includes("@SWITCH"))) {
37
- switchStatement = path.node;
38
- path.stop();
39
- }
40
- },
41
- });
42
-
43
- ok(switchStatement, "Could not find @SWITCH statement for micro opcodes");
44
-
45
- // Build opName → SwitchCase from existing cases.
46
- const nameToCaseMap = new Map<string, t.SwitchCase>();
47
- for (const sc of (switchStatement as t.SwitchStatement).cases) {
48
- const test = sc.test;
49
- if (
50
- test &&
51
- t.isMemberExpression(test) &&
52
- t.isIdentifier(test.object, { name: "OP" }) &&
53
- t.isIdentifier(test.property)
54
- ) {
55
- nameToCaseMap.set((test.property as t.Identifier).name, sc);
56
- }
57
- }
58
-
59
- for (const [microOpStr, info] of Object.entries(compiler.MICRO_OPS)) {
60
- const microOpCode = Number(microOpStr);
61
- const { originalOp, stmtIndex } = info;
62
-
63
- const originalName = compiler.OP_NAME[originalOp];
64
- if (!originalName) continue;
65
-
66
- const originalCase = nameToCaseMap.get(originalName);
67
- if (!originalCase) continue;
68
-
69
- // Extract and clone all non-break statements from the original case body.
70
- const allStmts = extractCaseBody(originalCase);
71
- if (stmtIndex >= allStmts.length) continue;
72
-
73
- const rawStmt = t.cloneNode(allStmts[stmtIndex], true) as t.Statement;
74
-
75
- const newCase = t.switchCase(t.numericLiteral(microOpCode), [
76
- t.blockStatement([rawStmt, t.breakStatement()]),
77
- ]);
78
-
79
- // Apply internal-variable substitution — this may replace rawStmt in the
80
- // block body (var decl → assignment), so add the comment afterwards on
81
- // whatever the first statement of the block actually is.
82
- applyInternalVariablesToSwitchCase(newCase, compiler, microOpCode);
83
-
84
- const blockBody = (newCase.consequent[0] as t.BlockStatement).body;
85
- const firstStmt = blockBody[0];
86
- if (firstStmt) {
87
- const microName = compiler.OP_NAME[microOpCode] ?? `MICRO_${microOpCode}`;
88
- t.addComment(firstStmt, "leading", ` ${microName}`, true);
89
- }
90
-
91
- (switchStatement as t.SwitchStatement).cases.push(newCase);
92
- }
93
- }