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.
- package/CHANGELOG.md +23 -0
- package/README.md +75 -94
- package/bench.ts +146 -0
- package/disassemble.ts +12 -0
- package/dist/build-runtime.js +41 -15
- package/dist/compiler.js +134 -60
- package/dist/disassembler.js +317 -0
- package/dist/index.js +7 -2
- package/dist/runtime.js +68 -46
- package/dist/template.js +116 -0
- package/dist/transforms/bytecode/aliasedOpcodes.js +4 -1
- package/dist/transforms/bytecode/controlFlowFlattening.js +451 -0
- package/dist/transforms/bytecode/dispatcher.js +13 -109
- package/dist/transforms/bytecode/macroOpcodes.js +2 -2
- package/dist/transforms/bytecode/resolveConstants.js +100 -0
- package/dist/transforms/bytecode/resolveRegisters.js +4 -0
- package/dist/transforms/bytecode/semanticOpcodes.js +162 -0
- package/dist/transforms/bytecode/specializedOpcodes.js +18 -10
- package/dist/transforms/bytecode/stringConcealing.js +110 -0
- package/dist/transforms/runtime/classObfuscation.js +43 -0
- package/dist/transforms/runtime/handlerTable.js +91 -0
- package/dist/transforms/runtime/semanticOpcodes.js +35 -0
- package/dist/transforms/runtime/specializedOpcodes.js +11 -5
- package/dist/types.js +1 -1
- package/dist/utils/ast-utils.js +14 -0
- package/dist/utils/op-utils.js +0 -2
- package/dist/utils/pass-utils.js +100 -0
- package/dist/utils/profile-utils.js +3 -0
- package/index.ts +22 -17
- package/jest.config.js +14 -2
- package/output.disassembled.js +41 -0
- package/package.json +2 -1
- package/src/build-runtime.ts +113 -78
- package/src/compiler.ts +2703 -2593
- package/src/disassembler.ts +329 -0
- package/src/index.ts +12 -2
- package/src/options.ts +7 -1
- package/src/runtime.ts +84 -51
- package/src/template.ts +125 -1
- package/src/transforms/bytecode/aliasedOpcodes.ts +4 -1
- package/src/transforms/bytecode/controlFlowFlattening.ts +566 -0
- package/src/transforms/bytecode/dispatcher.ts +19 -125
- package/src/transforms/bytecode/macroOpcodes.ts +2 -2
- package/src/transforms/bytecode/resolveRegisters.ts +5 -0
- package/src/transforms/bytecode/specializedOpcodes.ts +22 -11
- package/src/transforms/bytecode/stringConcealing.ts +130 -0
- package/src/transforms/runtime/classObfuscation.ts +59 -0
- package/src/transforms/runtime/specializedOpcodes.ts +14 -9
- package/src/types.ts +42 -1
- package/src/utils/ast-utils.ts +19 -0
- package/src/utils/op-utils.ts +0 -2
- package/src/utils/pass-utils.ts +126 -0
- package/src/utils/profile-utils.ts +3 -0
- package/tsconfig.json +1 -1
- package/src/transforms/bytecode/microOpcodes.ts +0 -291
- package/src/transforms/runtime/internalVariables.ts +0 -270
- package/src/transforms/runtime/microOpcodes.ts +0 -93
- /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
|
-
}
|
|
File without changes
|