jsarmor 1.0.6 → 2.0.0

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/cli/index.js CHANGED
@@ -1,177 +1,194 @@
1
- #!/usr/bin/env node
2
-
3
- import fs from "fs";
4
- import path from "path";
5
- import chalk from "chalk";
6
- import gradient from "gradient-string";
7
- import cliProgress from "cli-progress";
8
- import generate from "@babel/generator";
9
-
10
- import { parseCode } from "../core/parser.js";
11
- import { renameVariables } from "../core/renamer.js";
12
- import { encodeStrings } from "../core/stringArray.js";
13
- import { flattenControlFlow } from "../core/controlflow.js";
14
- import { unicodeEscape } from "../core/unicode.js";
15
- import { generateJunk } from "../core/junkcode.js";
16
-
17
- import { injectDeadCode, generateDeadRuntime } from "../core/deadcode.js";
18
-
19
- import { injectAntiDebug } from "../core/antidebug.js";
20
- import { antiBeautify } from "../core/beautifyGuard.js";
21
- import { selfDefend } from "../core/selfdefend.js";
22
-
23
- const neon = gradient(["#00ffff","#ff00ff","#00ff9f"]);
24
-
25
- try{
26
-
27
- const args = process.argv.slice(2);
28
-
29
- const command = args[0];
30
- const file = args[1];
31
-
32
- let outputName = "obf.js";
33
-
34
- const outIndex = args.indexOf("-o");
35
-
36
- if(outIndex !== -1 && args[outIndex+1]){
37
- outputName = args[outIndex+1];
38
- }
39
-
40
- if(!command || command === "help"){
41
-
42
- console.log(neon(`
43
- JSArmor - JavaScript Obfuscator
44
-
45
- Usage:
46
-
47
- jsarmor gen input.js
48
- jsarmor gen input.js -o output.js
49
-
50
- `));
51
-
52
- process.exit(0);
53
-
54
- }
55
-
56
- if(command !== "gen"){
57
-
58
- console.log(chalk.red("Unknown command"));
59
- console.log("Use: jsarmor gen input.js");
60
-
61
- process.exit(1);
62
-
63
- }
64
-
65
- if(!file){
66
-
67
- console.log(chalk.red("Please provide input file"));
68
- console.log("Usage: jsarmor gen input.js");
69
-
70
- process.exit(1);
71
-
72
- }
73
-
74
- if(!fs.existsSync(file)){
75
- console.log(chalk.red(`File not found: ${file}`));
76
- process.exit(1);
77
- }
78
-
79
- let code = fs.readFileSync(file,"utf8");
80
-
81
- let shebang = "";
82
-
83
- if(code.startsWith("#!")){
84
- const end = code.indexOf("\n");
85
- shebang = code.slice(0,end);
86
- code = code.slice(end);
87
- }
88
-
89
- console.log(
90
- neon(`┌──────────────────────────────┐
91
- │ NodeJS Obfuscator v3 │
92
- └──────────────────────────────┘`)
93
- );
94
-
95
- const bar = new cliProgress.SingleBar({
96
- format:"progress [{bar}] {percentage}% | {value}/{total}",
97
- barCompleteChar:"",
98
- barIncompleteChar:"░"
99
- });
100
-
101
- bar.start(6,0);
102
-
103
- const ast = parseCode(code);
104
- bar.increment();
105
-
106
- renameVariables(ast);
107
- bar.increment();
108
-
109
- const pool = encodeStrings(ast);
110
- bar.increment();
111
-
112
- /* dead code transform */
113
- injectDeadCode(ast);
114
- bar.increment();
115
-
116
- flattenControlFlow(ast);
117
- bar.increment();
118
-
119
- unicodeEscape(ast);
120
- bar.increment();
121
-
122
- bar.stop();
123
-
124
- const output = generate.default(ast,{
125
- jsescOption:{
126
- minimal:true
127
- }
128
- }).code;
129
-
130
- const runtimeJunk = generateDeadRuntime();
131
-
132
- const final =
133
- (shebang ? shebang + "\n" : "") +
134
- injectAntiDebug() +
135
- antiBeautify() +
136
- selfDefend() +
137
- `var _STRINGS=${JSON.stringify(pool)};\n` +
138
- runtimeJunk +
139
- generateJunk() +
140
- output;
141
-
142
- const distDir = path.join(process.cwd(),"dist");
143
-
144
- if(!fs.existsSync(distDir)){
145
- fs.mkdirSync(distDir,{recursive:true});
146
- }
147
-
148
- const outFile = path.join(distDir,"obf.js");
149
-
150
- fs.writeFileSync(outFile,final);
151
-
152
- console.log();
153
- console.log(chalk.green("✔ Parsing AST"));
154
- console.log(chalk.green("✔ Variables renamed"));
155
- console.log(chalk.green("✔ Strings encoded"));
156
- console.log(chalk.green("✔ Dead code injected"));
157
- console.log(chalk.green("✔ Control flow flattened"));
158
- console.log(chalk.green("✔ Unicode escape applied"));
159
- console.log();
160
- console.log(chalk.bold.green("✔ Obfuscation Complete"));
161
- console.log(chalk.cyan(`Output: ${outFile}`));
162
-
163
- const originalSize = code.length;
164
- const newSize = final.length;
165
-
166
- console.log(
167
- chalk.yellow(
168
- `Size: ${(originalSize/1024).toFixed(2)} KB → ${(newSize/1024).toFixed(2)} KB`
169
- )
170
- );
171
-
172
- }catch(err){
173
-
174
- console.log(chalk.red("Obfuscation failed"));
175
- console.error(err);
176
-
177
- }
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import chalk from "chalk";
6
+ import gradient from "gradient-string";
7
+ import cliProgress from "cli-progress";
8
+ import generate from "@babel/generator";
9
+
10
+ import { parseCode } from "../core/parser.js";
11
+ import { renameVariables } from "../core/renamer.js";
12
+ import { encodeStrings } from "../core/stringArray.js";
13
+ import { flattenControlFlow } from "../core/controlflow.js";
14
+ import { unicodeEscape } from "../core/unicode.js";
15
+ import { generateJunk } from "../core/junkcode.js";
16
+
17
+ import { injectDeadCode, generateDeadRuntime } from "../core/deadcode.js";
18
+
19
+ import { injectAntiDebug } from "../core/antidebug.js";
20
+ import { antiBeautify } from "../core/beautifyGuard.js";
21
+ import { selfDefend } from "../core/selfdefend.js";
22
+ import { unicodeIdentifiers } from "../core/unicodeIdentifier.js";
23
+ import { buildStringRuntime } from "../core/stringRuntime.js";
24
+ import { antiVM } from "../core/antivm.js";
25
+
26
+ import { watermark } from "../utils/watermark.js";
27
+
28
+ const neon = gradient(["#00ffff","#ff00ff","#00ff9f"]);
29
+
30
+ try{
31
+
32
+ const args = process.argv.slice(2);
33
+
34
+ const command = args[0];
35
+ const file = args[1];
36
+
37
+ let outputName = "obf.js";
38
+
39
+ const outIndex = args.indexOf("-o");
40
+
41
+ if(outIndex !== -1 && args[outIndex+1]){
42
+ outputName = args[outIndex+1];
43
+ }
44
+
45
+ let user = "";
46
+
47
+ const userIndex = args.indexOf("--user");
48
+
49
+ if(userIndex !== -1 && args[userIndex+1]){
50
+ user = args[userIndex+1];
51
+ }
52
+
53
+ if(!command || command === "help"){
54
+
55
+ console.log(neon(`
56
+ JSArmor - JavaScript Obfuscator
57
+
58
+ Usage:
59
+
60
+ jsarmor gen input.js
61
+ jsarmor gen input.js -o output.js
62
+
63
+ `));
64
+
65
+ process.exit(0);
66
+
67
+ }
68
+
69
+ if(command !== "gen"){
70
+
71
+ console.log(chalk.red("Unknown command"));
72
+ console.log("Use: jsarmor gen input.js");
73
+
74
+ process.exit(1);
75
+
76
+ }
77
+
78
+ if(!file){
79
+
80
+ console.log(chalk.red("Please provide input file"));
81
+ console.log("Usage: jsarmor gen input.js");
82
+
83
+ process.exit(1);
84
+
85
+ }
86
+
87
+ if(!fs.existsSync(file)){
88
+ console.log(chalk.red(`File not found: ${file}`));
89
+ process.exit(1);
90
+ }
91
+
92
+ let code = fs.readFileSync(file,"utf8");
93
+
94
+ let shebang = "";
95
+
96
+ if(code.startsWith("#!")){
97
+ const end = code.indexOf("\n");
98
+ shebang = code.slice(0,end);
99
+ code = code.slice(end);
100
+ }
101
+
102
+ console.log(
103
+ neon(`┌──────────────────────────────┐
104
+ │ JSArmor Version1.7 │
105
+ └──────────────────────────────┘`)
106
+ );
107
+ const bar = new cliProgress.SingleBar({
108
+ format:"progress [{bar}] {percentage}% | {value}/{total}",
109
+ barCompleteChar:"█",
110
+ barIncompleteChar:"░"
111
+ });
112
+
113
+ bar.start(7,0);
114
+
115
+ const ast = parseCode(code);
116
+ bar.increment();
117
+
118
+ renameVariables(ast);
119
+ bar.increment();
120
+
121
+ unicodeIdentifiers(ast);
122
+ bar.increment();
123
+
124
+ const pool = encodeStrings(ast);
125
+ bar.increment();
126
+
127
+ /* dead code transform */
128
+ injectDeadCode(ast);
129
+ bar.increment();
130
+
131
+ flattenControlFlow(ast);
132
+ bar.increment();
133
+
134
+ unicodeEscape(ast);
135
+ bar.increment();
136
+
137
+ bar.stop();
138
+
139
+ const output = generate.default(ast,{
140
+ jsescOption:{
141
+ minimal:true
142
+ }
143
+ }).code;
144
+
145
+ const runtimeJunk = generateDeadRuntime();
146
+
147
+ const final =
148
+ (shebang ? shebang + "\n" : "") +
149
+ watermark(user) +
150
+ injectAntiDebug() +
151
+ antiBeautify() +
152
+ antiVM() +
153
+ selfDefend() +
154
+ buildStringRuntime(pool) +
155
+ runtimeJunk +
156
+ generateJunk() +
157
+ output;
158
+
159
+ const distDir = path.join(process.cwd(),"dist");
160
+
161
+ if(!fs.existsSync(distDir)){
162
+ fs.mkdirSync(distDir,{recursive:true});
163
+ }
164
+
165
+ const outFile = path.join(distDir, outputName);
166
+
167
+ fs.writeFileSync(outFile,final);
168
+
169
+ console.log();
170
+ console.log(chalk.green("✔ Parsing AST"));
171
+ console.log(chalk.green("✔ Variables renamed"));
172
+ console.log(chalk.green("✔ Strings encoded"));
173
+ console.log(chalk.green("✔ Dead code injected"));
174
+ console.log(chalk.green(" Control flow flattened"));
175
+ console.log(chalk.green("✔ Unicode escape applied"));
176
+ console.log();
177
+ console.log(chalk.bold.green("✔ Obfuscation Complete"));
178
+ console.log(chalk.cyan(`Output: ${outFile}`));
179
+
180
+ const originalSize = code.length;
181
+ const newSize = final.length;
182
+
183
+ console.log(
184
+ chalk.yellow(
185
+ `Size: ${(originalSize/1024).toFixed(2)} KB → ${(newSize/1024).toFixed(2)} KB`
186
+ )
187
+ );
188
+
189
+ }catch(err){
190
+
191
+ console.log(chalk.red("Obfuscation failed"));
192
+ console.error(err);
193
+
194
+ }
package/core/antidebug.js CHANGED
@@ -1,15 +1,13 @@
1
- export function injectAntiDebug(){
2
-
3
- return `
4
-
5
- (function(){
6
- setInterval(function(){
7
- try{
8
- (function(){debugger})()
9
- }catch(e){}
10
- },2000)
11
- })();
12
-
13
- `;
14
-
15
- }
1
+ export function injectAntiDebug(){
2
+ return `
3
+
4
+ ;(function(){
5
+ setInterval(function(){
6
+ try{
7
+ debugger;
8
+ }catch(e){}
9
+ },3000)
10
+ })();
11
+
12
+ `;
13
+ }
package/core/antivm.js ADDED
@@ -0,0 +1,19 @@
1
+ export function antiVM(){
2
+ return `
3
+
4
+ ;(function(){
5
+
6
+ var s=(typeof navigator!="undefined"?navigator.userAgent:"node").toLowerCase()
7
+
8
+ if(
9
+ s.includes("vmware")||
10
+ s.includes("virtualbox")||
11
+ s.includes("qemu")
12
+ ){
13
+ console.warn("VM detected");
14
+ }
15
+
16
+ })()
17
+
18
+ `
19
+ }
@@ -1,21 +1,17 @@
1
1
  export function antiBeautify(){
2
-
3
2
  return `
4
3
 
5
- (function(){
4
+ ;(function(){
6
5
 
7
6
  const start=Date.now()
8
-
9
7
  debugger
10
-
11
8
  const end=Date.now()
12
9
 
13
- if(end-start>100){
14
- while(true){}
10
+ if(end-start>1000){
11
+ console.warn("Debug detected")
15
12
  }
16
13
 
17
14
  })();
18
15
 
19
16
  `;
20
-
21
17
  }
@@ -93,24 +93,13 @@ Function(path){
93
93
  });
94
94
 
95
95
  const whileLoop = t.whileStatement(
96
- t.booleanLiteral(true),
97
- t.blockStatement([
98
-
99
- t.switchStatement(
100
- t.identifier("_s"),
101
- cases
102
- ),
103
-
104
- t.ifStatement(
105
- t.binaryExpression(
106
- ">=",
107
- t.identifier("_s"),
108
- t.numericLiteral(body.length)
109
- ),
110
- t.breakStatement()
111
- )
112
-
113
- ])
96
+ t.binaryExpression("<", t.identifier("_s"), t.numericLiteral(body.length)),
97
+ t.blockStatement([
98
+ t.switchStatement(
99
+ t.identifier("_s"),
100
+ cases
101
+ )
102
+ ])
114
103
  );
115
104
 
116
105
  const newBody = [];
@@ -147,4 +136,4 @@ Function(path){
147
136
  }
148
137
  });
149
138
 
150
- }
139
+ }
package/core/deadcode.js CHANGED
@@ -1,7 +1,9 @@
1
- import traverse from "@babel/traverse";
1
+ import traverseModule from "@babel/traverse";
2
2
  import * as t from "@babel/types";
3
3
  import { randomInt } from "../utils/random.js";
4
4
 
5
+ const traverse = traverseModule.default;
6
+
5
7
  const patterns = [
6
8
 
7
9
  "var _a=Math.random();if(_a>2){console.log(_a)}",
@@ -17,7 +19,9 @@ const patterns = [
17
19
 
18
20
  ];
19
21
 
20
- for(let i=0;i<90;i++){
22
+ /* generate nhiều pattern */
23
+
24
+ for(let i=0;i<20;i++){
21
25
 
22
26
  patterns.push(`
23
27
  var _junk${i}=Math.random()*${randomInt(1,999)};
@@ -34,9 +38,11 @@ return patterns[Math.floor(Math.random()*patterns.length)];
34
38
 
35
39
  }
36
40
 
41
+ /* AST deadcode */
42
+
37
43
  export function injectDeadCode(ast){
38
44
 
39
- traverse.default(ast,{
45
+ traverse(ast,{
40
46
 
41
47
  BlockStatement(path){
42
48
 
@@ -76,14 +82,14 @@ path.node.body.unshift(fake);
76
82
 
77
83
  }
78
84
 
85
+ /* runtime deadcode */
86
+
79
87
  export function generateDeadRuntime(){
80
88
 
81
89
  let out="";
82
90
 
83
- for(let i=0;i<30;i++){
84
-
91
+ for(let i=0;i<10;i++){
85
92
  out+=randomPattern()+"\n";
86
-
87
93
  }
88
94
 
89
95
  return out;
package/core/junkcode.js CHANGED
@@ -1,18 +1,19 @@
1
- export function generateJunk() {
1
+ export function generateJunk(){
2
2
 
3
- const junk = [];
3
+ return `
4
4
 
5
- for (let i = 0; i < 20; i++) {
5
+ var _假=Math.random()
6
6
 
7
- junk.push(`
8
- var _junk${i} = Math.random() * ${i};
9
- if(_junk${i} > 9999){
10
- console.log(_junk${i});
7
+ function _伪(){
8
+ try{
9
+ return Function("return 1+1")()
10
+ }catch(e){}
11
11
  }
12
- `);
13
12
 
14
- }
13
+ if(_假>2){
14
+ console.log(_伪())
15
+ }
15
16
 
16
- return junk.join("\n");
17
+ `
17
18
 
18
19
  }
package/core/parser.js CHANGED
@@ -18,4 +18,4 @@ plugins:[
18
18
  ]
19
19
  });
20
20
 
21
- }
21
+ }
package/core/rc4.js CHANGED
@@ -1,42 +1,33 @@
1
1
  export function rc4(key, str){
2
2
 
3
- let s=[]
4
- let j=0
5
- let x
6
- let res=""
3
+ if(!key) throw new Error("RC4 key empty")
7
4
 
8
- for(let i=0;i<256;i++){
9
- s[i]=i
10
- }
11
-
12
- for(let i=0;i<256;i++){
13
-
14
- j=(j+s[i]+key.charCodeAt(i%key.length))%256
5
+ let s=[],j=0,x,res=""
15
6
 
16
- x=s[i]
17
- s[i]=s[j]
18
- s[j]=x
7
+ for(let i=0;i<256;i++) s[i]=i
19
8
 
9
+ for(let i=0;i<256;i++){
10
+ j=(j+s[i]+key.charCodeAt(i%key.length))&255
11
+ x=s[i]
12
+ s[i]=s[j]
13
+ s[j]=x
20
14
  }
21
15
 
22
16
  let i=0
23
17
  j=0
24
18
 
25
19
  for(let y=0;y<str.length;y++){
20
+ i=(i+1)&255
21
+ j=(j+s[i])&255
26
22
 
27
- i=(i+1)%256
28
- j=(j+s[i])%256
29
-
30
- x=s[i]
31
- s[i]=s[j]
32
- s[j]=x
23
+ x=s[i]
24
+ s[i]=s[j]
25
+ s[j]=x
33
26
 
34
- let k=s[(s[i]+s[j])%256]
35
-
36
- res+=String.fromCharCode(str.charCodeAt(y)^k)
27
+ let k=s[(s[i]+s[j])&255]
37
28
 
29
+ res += String.fromCharCode(str.charCodeAt(y) ^ k)
38
30
  }
39
31
 
40
32
  return res
41
-
42
33
  }