js-confuser-vm 0.0.2 → 0.0.4

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 (39) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/LICENSE +21 -21
  3. package/README.MD +370 -190
  4. package/babel-plugin-inline-runtime.cjs +34 -0
  5. package/babel.config.json +23 -24
  6. package/index.ts +34 -28
  7. package/jest-strip-types.js +10 -10
  8. package/jest.config.js +35 -18
  9. package/package.json +50 -48
  10. package/src/build-runtime.ts +57 -0
  11. package/src/compiler.ts +2069 -1677
  12. package/src/index.ts +14 -13
  13. package/src/minify.ts +21 -21
  14. package/src/options.ts +14 -10
  15. package/src/runtime.ts +771 -645
  16. package/src/transforms/bytecode/macroOpcodes.ts +177 -0
  17. package/src/transforms/bytecode/resolveContants.ts +62 -0
  18. package/src/transforms/bytecode/resolveLabels.ts +107 -0
  19. package/src/transforms/bytecode/selfModifying.ts +121 -0
  20. package/src/transforms/bytecode/specializedOpcodes.ts +118 -0
  21. package/src/transforms/runtime/macroOpcodes.ts +111 -0
  22. package/src/transforms/runtime/minify.ts +1 -0
  23. package/src/transforms/runtime/shuffleOpcodes.ts +24 -0
  24. package/src/transforms/runtime/specializedOpcodes.ts +146 -0
  25. package/src/transforms/utils/op-utils.ts +26 -0
  26. package/src/{random.ts → transforms/utils/random-utils.ts} +31 -31
  27. package/src/types.ts +33 -0
  28. package/src/utilts.ts +3 -3
  29. package/tsconfig.json +12 -12
  30. package/dist/compiler.js +0 -1505
  31. package/dist/index.js +0 -9
  32. package/dist/minify.js +0 -18
  33. package/dist/minify_empty_externs.js +0 -4
  34. package/dist/options.js +0 -1
  35. package/dist/random.js +0 -27
  36. package/dist/runtime.js +0 -620
  37. package/dist/runtimeObf.js +0 -36
  38. package/dist/utilts.js +0 -3
  39. package/src/runtimeObf.ts +0 -48
package/babel.config.json CHANGED
@@ -1,24 +1,23 @@
1
- {
2
- "presets": [
3
- [
4
- "@babel/preset-env",
5
- {
6
- "targets": {
7
- "node": "18"
8
- },
9
- "modules": false
10
- }
11
- ],
12
- [
13
- "@babel/preset-typescript"
14
- ]
15
- ],
16
- "plugins": [
17
- [
18
- "replace-import-extension",
19
- {
20
- "extMapping": { ".ts": ".js" }
21
- }
22
- ]
23
- ]
24
- }
1
+ {
2
+ "presets": [
3
+ [
4
+ "@babel/preset-env",
5
+ {
6
+ "targets": {
7
+ "node": "18"
8
+ },
9
+ "modules": false
10
+ }
11
+ ],
12
+ ["@babel/preset-typescript"]
13
+ ],
14
+ "plugins": [
15
+ "./babel-plugin-inline-runtime.cjs",
16
+ [
17
+ "replace-import-extension",
18
+ {
19
+ "extMapping": { ".ts": ".js" }
20
+ }
21
+ ]
22
+ ]
23
+ }
package/index.ts CHANGED
@@ -1,28 +1,34 @@
1
- import JsConfuserVM from "./src/index.ts";
2
- import { readFileSync, writeFileSync } from "fs";
3
-
4
- async function main() {
5
- // Compile and write the output to a file
6
- const sourceCode = readFileSync("input.js", "utf-8");
7
- const { code: output } = await JsConfuserVM.obfuscate(sourceCode, {
8
- minify: true,
9
- encodeBytecode: true,
10
- randomizeOpcodes: true,
11
- selfModifying: true,
12
- shuffleOpcodes: true,
13
- timingChecks: true,
14
- });
15
-
16
- writeFileSync("output.js", output, "utf-8");
17
- console.log(output);
18
-
19
- // Eval the code like our test suite does
20
- var window = { TEST_OUTPUT: null };
21
- eval(output);
22
- console.log(window.TEST_OUTPUT);
23
-
24
- // Minify using Google Closure Compiler (optional)
25
- // import("./minify.js");
26
- }
27
-
28
- main();
1
+ import JsConfuserVM from "./src/index.ts";
2
+ import { readFileSync, writeFileSync } from "fs";
3
+
4
+ async function main() {
5
+ // Compile and write the output to a file
6
+ const sourceCode = readFileSync("input.js", "utf-8");
7
+
8
+ const { code: orginalOutput } = await JsConfuserVM.obfuscate(sourceCode, {});
9
+
10
+ const { code: output } = await JsConfuserVM.obfuscate(sourceCode, {
11
+ target: "browser", // or "node"
12
+ // randomizeOpcodes: true, // randomize the opcode numbers?
13
+ // shuffleOpcodes: true, // shuffle order of opcode handlers in the runtime?
14
+ // encodeBytecode: true, // encode bytecode? when off, comments for instructions are added
15
+ // selfModifying: true, // do self-modifying bytecode for function bodies?
16
+ // macroOpcodes: true, // create combined opcodes for repeated instruction sequences?
17
+ // specializedOpcodes: true, // create specialized opcodes for commonly used opcode+operand pairs?
18
+ // timingChecks: true, // add timing checks to detect debuggers?
19
+ // minify: true, // pass final output through Google Closure Compiler? (
20
+ });
21
+
22
+ writeFileSync("output.original.js", orginalOutput, "utf-8");
23
+ writeFileSync("output.js", output, "utf-8");
24
+
25
+ // Eval the code like our test suite does
26
+ var window = { TEST_OUTPUT: null };
27
+ eval(output);
28
+ console.log(window.TEST_OUTPUT);
29
+
30
+ // Minify using Google Closure Compiler (optional)
31
+ // import("./minify.js");
32
+ }
33
+
34
+ main();
@@ -1,10 +1,10 @@
1
- import { stripTypeScriptTypes } from 'node:module';
2
-
3
- export default {
4
- process(code, filePath) {
5
- if (filePath.endsWith('.ts')) {
6
- return { code: stripTypeScriptTypes(code) };
7
- }
8
- return { code };
9
- },
10
- };
1
+ import { stripTypeScriptTypes } from 'node:module';
2
+
3
+ export default {
4
+ process(code, filePath) {
5
+ if (filePath.endsWith('.ts')) {
6
+ return { code: stripTypeScriptTypes(code) };
7
+ }
8
+ return { code };
9
+ },
10
+ };
package/jest.config.js CHANGED
@@ -1,18 +1,35 @@
1
- const OPTIONS_MATRIX = [
2
- { displayName: "default", VM_OPTIONS: {} },
3
- { displayName: "randomizeOpcodes", VM_OPTIONS: { randomizeOpcodes: true } },
4
- { displayName: "shuffleOpcodes", VM_OPTIONS: { shuffleOpcodes: true } },
5
- { displayName: "encodeBytecode", VM_OPTIONS: { encodeBytecode: true } },
6
- { displayName: "selfModifying", VM_OPTIONS: { selfModifying: true } },
7
- { displayName: "timingChecks", VM_OPTIONS: { timingChecks: true } },
8
- ];
9
-
10
- export default {
11
- projects: OPTIONS_MATRIX.map(({ displayName, VM_OPTIONS }) => ({
12
- displayName,
13
- extensionsToTreatAsEsm: [".ts"],
14
- moduleFileExtensions: ["ts", "js", "json"],
15
- transform: { "\\.ts$": "./jest-strip-types.js" },
16
- globals: { VM_OPTIONS },
17
- })),
18
- };
1
+ const OPTIONS_MATRIX = [
2
+ { displayName: "default", VM_OPTIONS: {} },
3
+ { displayName: "randomizeOpcodes", VM_OPTIONS: { randomizeOpcodes: true } },
4
+ { displayName: "shuffleOpcodes", VM_OPTIONS: { shuffleOpcodes: true } },
5
+ { displayName: "encodeBytecode", VM_OPTIONS: { encodeBytecode: true } },
6
+ { displayName: "selfModifying", VM_OPTIONS: { selfModifying: true } },
7
+ { displayName: "timingChecks", VM_OPTIONS: { timingChecks: true } },
8
+ { displayName: "macroOpcodes", VM_OPTIONS: { macroOpcodes: true } },
9
+ {
10
+ displayName: "specializedOpcodes",
11
+ VM_OPTIONS: { specializedOpcodes: true },
12
+ },
13
+ {
14
+ displayName: "all",
15
+ VM_OPTIONS: {
16
+ randomizeOpcodes: true,
17
+ shuffleOpcodes: true,
18
+ encodeBytecode: true,
19
+ selfModifying: true,
20
+ timingChecks: true,
21
+ macroOpcodes: true,
22
+ specializedOpcodes: true,
23
+ },
24
+ },
25
+ ];
26
+
27
+ export default {
28
+ projects: OPTIONS_MATRIX.map(({ displayName, VM_OPTIONS }) => ({
29
+ displayName,
30
+ extensionsToTreatAsEsm: [".ts"],
31
+ moduleFileExtensions: ["ts", "js", "json"],
32
+ transform: { "\\.ts$": "./jest-strip-types.js" },
33
+ globals: { VM_OPTIONS },
34
+ })),
35
+ };
package/package.json CHANGED
@@ -1,48 +1,50 @@
1
- {
2
- "name": "js-confuser-vm",
3
- "version": "0.0.2",
4
- "main": "dist/index.js",
5
- "scripts": {
6
- "build": "babel src --out-dir dist --extensions '.ts,.js'",
7
- "index": "NODE_OPTIONS=\"--disable-warning=ExperimentalWarning\" node index.ts",
8
- "test": "NODE_OPTIONS=\"--experimental-vm-modules --experimental-strip-types --disable-warning=ExperimentalWarning\" jest --coverage --coverageReporters=html --selectProjects default",
9
- "test-all": "NODE_OPTIONS=\"--experimental-vm-modules --experimental-strip-types --disable-warning=ExperimentalWarning\" jest --coverage --coverageReporters=html",
10
- "test262": "NODE_OPTIONS=\"--experimental-vm-modules --experimental-strip-types --disable-warning=ExperimentalWarning\" node test262-scripts/run-test262.ts",
11
- "prepublishOnly": "npm run build && npm run test"
12
- },
13
- "type": "module",
14
- "keywords": [
15
- "vm",
16
- "virtual machine",
17
- "obfuscator",
18
- "obfuscation",
19
- "uglify",
20
- "code protection",
21
- "javascript obfuscator",
22
- "js obfuscator"
23
- ],
24
- "author": "MichaelXF",
25
- "license": "MIT",
26
- "description": "",
27
- "dependencies": {
28
- "@babel/generator": "^7.29.1",
29
- "@babel/parser": "^7.29.0",
30
- "@babel/traverse": "^7.29.0",
31
- "@babel/types": "^7.29.0",
32
- "google-closure-compiler": "^20260216.0.0",
33
- "json5": "^2.2.3"
34
- },
35
- "devDependencies": {
36
- "@babel/cli": "^7.28.6",
37
- "@babel/core": "^7.29.0",
38
- "@babel/preset-env": "^7.29.0",
39
- "@babel/preset-typescript": "^7.28.5",
40
- "@types/node": "^25.3.0",
41
- "babel-plugin-module-resolver": "^5.0.2",
42
- "babel-plugin-replace-import-extension": "^1.1.5",
43
- "jest": "^30.2.0"
44
- },
45
- "engines": {
46
- "node": ">=18.0.0"
47
- }
48
- }
1
+ {
2
+ "name": "js-confuser-vm",
3
+ "version": "0.0.4",
4
+ "main": "dist/index.js",
5
+ "scripts": {
6
+ "build": "babel src --out-dir dist --extensions '.ts,.js'",
7
+ "index": "cross-env NODE_OPTIONS=\"--disable-warning=ExperimentalWarning\" node index.ts",
8
+ "test": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --experimental-strip-types --disable-warning=ExperimentalWarning\" jest --coverage --coverageReporters=html --selectProjects default",
9
+ "test-all": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --experimental-strip-types --disable-warning=ExperimentalWarning\" jest --coverage --coverageReporters=html",
10
+ "test262": "cross-env NODE_OPTIONS=\"--experimental-vm-modules --experimental-strip-types --disable-warning=ExperimentalWarning\" node test262-scripts/run-test262.ts",
11
+ "prepublishOnly": "npm run build && npm run test",
12
+ "set-env": ""
13
+ },
14
+ "type": "module",
15
+ "keywords": [
16
+ "vm",
17
+ "virtual machine",
18
+ "obfuscator",
19
+ "obfuscation",
20
+ "uglify",
21
+ "code protection",
22
+ "javascript obfuscator",
23
+ "js obfuscator"
24
+ ],
25
+ "author": "MichaelXF",
26
+ "license": "MIT",
27
+ "description": "",
28
+ "dependencies": {
29
+ "@babel/generator": "^7.29.1",
30
+ "@babel/parser": "^7.29.0",
31
+ "@babel/traverse": "^7.29.0",
32
+ "@babel/types": "^7.29.0",
33
+ "google-closure-compiler": "^20260216.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@babel/cli": "^7.28.6",
37
+ "@babel/core": "^7.29.0",
38
+ "@babel/preset-env": "^7.29.0",
39
+ "@babel/preset-typescript": "^7.28.5",
40
+ "@types/node": "^25.3.0",
41
+ "babel-plugin-module-resolver": "^5.0.2",
42
+ "babel-plugin-replace-import-extension": "^1.1.5",
43
+ "cross-env": "^10.1.0",
44
+ "glob": "^13.0.6",
45
+ "jest": "^30.2.0"
46
+ },
47
+ "engines": {
48
+ "node": ">=18.0.0"
49
+ }
50
+ }
@@ -0,0 +1,57 @@
1
+ import { generate } from "@babel/generator";
2
+ import { parse, type ParseResult } from "@babel/parser";
3
+ import type * as t from "@babel/types";
4
+ import type { Options } from "./options.ts";
5
+ import { applyMacroOpcodes } from "./transforms/runtime/macroOpcodes.ts";
6
+ import { applyShuffleOpcodes } from "./transforms/runtime/shuffleOpcodes.ts";
7
+ import { applyMinify } from "./transforms/runtime/minify.ts";
8
+ import { Compiler } from "./compiler.ts";
9
+ import { applySpecializedOpcodes } from "./transforms/runtime/specializedOpcodes.ts";
10
+ import type * as b from "./types.ts";
11
+
12
+ export async function obfuscateRuntime(
13
+ runtime: string,
14
+ bytecode: b.Bytecode,
15
+ options: Options,
16
+ compiler?: Compiler,
17
+ ) {
18
+ let ast: t.File;
19
+ try {
20
+ ast = parse(runtime, { sourceType: "unambiguous" });
21
+ } catch (error) {
22
+ throw new Error("VM-Runtime final parsing failed", { cause: error });
23
+ }
24
+
25
+ // Macro opcode cases must be applied BEFORE shuffleOpcodes
26
+ if (options.specializedOpcodes) {
27
+ applySpecializedOpcodes(ast, bytecode, compiler);
28
+ }
29
+
30
+ // Macro opcode cases must be applied BEFORE shuffleOpcodes
31
+ if (options.macroOpcodes && Object.keys(compiler.MACRO_OPS).length > 0) {
32
+ applyMacroOpcodes(ast, compiler);
33
+ }
34
+
35
+ // Shuffle opcode handle order
36
+ if (options.shuffleOpcodes) {
37
+ applyShuffleOpcodes(ast);
38
+ }
39
+
40
+ let generated: string;
41
+ try {
42
+ generated = generate(ast).code;
43
+ } catch (error) {
44
+ throw new Error("VM-Runtime final generation failed", { cause: error });
45
+ }
46
+
47
+ // Minify code?
48
+ if (options.minify) {
49
+ try {
50
+ generated = await applyMinify(generated);
51
+ } catch (error) {
52
+ throw new Error("VM-Runtime final minification failed", { cause: error });
53
+ }
54
+ }
55
+
56
+ return generated;
57
+ }