js-confuser 1.2.1 → 1.4.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 +171 -0
- package/README.md +7 -6
- package/dist/options.js +5 -1
- package/dist/parser.js +1 -2
- package/dist/presets.js +2 -2
- package/dist/transforms/calculator.js +48 -60
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +482 -95
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -0
- package/dist/transforms/controlFlowFlattening/{switchCaseObfucation.js → switchCaseObfuscation.js} +2 -2
- package/dist/transforms/deadCode.js +1 -1
- package/dist/transforms/dispatcher.js +14 -13
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -10
- package/dist/transforms/flatten.js +5 -1
- package/dist/transforms/hideInitializingCode.js +17 -2
- package/dist/transforms/identifier/globalConcealing.js +46 -25
- package/dist/transforms/identifier/movedDeclarations.js +69 -68
- package/dist/transforms/identifier/renameVariables.js +22 -98
- package/dist/transforms/identifier/variableAnalysis.js +133 -0
- package/dist/transforms/label.js +11 -2
- package/dist/transforms/lock/antiDebug.js +32 -13
- package/dist/transforms/lock/lock.js +13 -2
- package/dist/transforms/minify.js +117 -120
- package/dist/transforms/opaquePredicates.js +4 -2
- package/dist/transforms/preparation/preparation.js +8 -0
- package/dist/transforms/renameLabels.js +17 -3
- package/dist/transforms/rgf.js +8 -3
- package/dist/transforms/shuffle.js +25 -9
- package/dist/transforms/stack.js +5 -9
- package/dist/transforms/string/encoding.js +209 -0
- package/dist/transforms/string/stringCompression.js +10 -10
- package/dist/transforms/string/stringConcealing.js +94 -65
- package/dist/transforms/string/stringSplitting.js +7 -7
- package/dist/transforms/transform.js +10 -0
- package/dist/traverse.js +1 -35
- package/dist/util/gen.js +3 -1
- package/dist/util/identifiers.js +9 -19
- package/dist/util/insert.js +6 -40
- package/dist/util/scope.js +17 -0
- package/package.json +2 -2
- package/src/options.ts +19 -3
- package/src/parser.ts +1 -2
- package/src/presets.ts +2 -2
- package/src/transforms/calculator.ts +87 -91
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +742 -142
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +6 -0
- package/src/transforms/controlFlowFlattening/{switchCaseObfucation.ts → switchCaseObfuscation.ts} +6 -2
- package/src/transforms/deadCode.ts +8 -0
- package/src/transforms/dispatcher.ts +29 -14
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +43 -19
- package/src/transforms/flatten.ts +15 -2
- package/src/transforms/hideInitializingCode.ts +432 -406
- package/src/transforms/identifier/globalConcealing.ts +148 -46
- package/src/transforms/identifier/movedDeclarations.ts +78 -101
- package/src/transforms/identifier/renameVariables.ts +21 -96
- package/src/transforms/identifier/variableAnalysis.ts +124 -0
- package/src/transforms/label.ts +20 -2
- package/src/transforms/lock/antiDebug.ts +69 -26
- package/src/transforms/lock/lock.ts +37 -3
- package/src/transforms/minify.ts +154 -130
- package/src/transforms/opaquePredicates.ts +25 -3
- package/src/transforms/preparation/preparation.ts +8 -1
- package/src/transforms/renameLabels.ts +26 -3
- package/src/transforms/rgf.ts +6 -1
- package/src/transforms/shuffle.ts +87 -29
- package/src/transforms/stack.ts +6 -8
- package/src/transforms/string/encoding.ts +310 -0
- package/src/transforms/string/stringCompression.ts +37 -24
- package/src/transforms/string/stringConcealing.ts +157 -160
- package/src/transforms/string/stringSplitting.ts +12 -8
- package/src/transforms/transform.ts +15 -2
- package/src/traverse.ts +1 -31
- package/src/util/gen.ts +5 -3
- package/src/util/identifiers.ts +20 -20
- package/src/util/insert.ts +12 -78
- package/src/util/scope.ts +9 -0
- package/test/{transforms/compare.test.ts → compare.test.ts} +2 -2
- package/test/index.test.ts +109 -1
- package/test/templates/template.test.ts +14 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +392 -10
- package/test/transforms/dispatcher.test.ts +30 -0
- package/test/transforms/flatten.test.ts +28 -0
- package/test/transforms/hideInitializingCode.test.ts +336 -336
- package/test/transforms/identifier/globalConcealing.test.ts +1 -2
- package/test/transforms/identifier/movedDeclarations.test.ts +137 -112
- package/test/transforms/identifier/renameVariables.test.ts +124 -13
- package/test/transforms/lock/antiDebug.test.ts +43 -0
- package/test/transforms/lock/selfDefending.test.ts +68 -0
- package/test/transforms/minify.test.ts +137 -0
- package/test/transforms/renameLabels.test.ts +33 -0
- package/test/transforms/rgf.test.ts +29 -0
- package/test/transforms/string/stringSplitting.test.ts +33 -0
- package/test/util/identifiers.test.ts +105 -17
- package/dist/util/expr.js +0 -60
- package/src/util/expr.ts +0 -56
package/src/util/insert.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ok } from "assert";
|
|
2
|
-
import { getBlock, isBlock
|
|
3
|
-
import { Node
|
|
2
|
+
import { getBlock, isBlock } from "../traverse";
|
|
3
|
+
import { Node } from "./gen";
|
|
4
4
|
import { getIdentifierInfo, validateChain } from "./identifiers";
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -125,35 +125,18 @@ export function getDefiningContext(o: Node, p: Node[]): Node {
|
|
|
125
125
|
return getVarContext(o, p);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
export function getReferencingContexts(
|
|
128
|
+
export function getReferencingContexts(
|
|
129
|
+
o: Node,
|
|
130
|
+
p: Node[],
|
|
131
|
+
info?: ReturnType<typeof getIdentifierInfo>
|
|
132
|
+
): Node[] {
|
|
129
133
|
validateChain(o, p);
|
|
130
134
|
ok(o.type == "Identifier");
|
|
131
135
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
var assignmentPatternIndex = p.findIndex(
|
|
136
|
-
(x) => x.type == "AssignmentPattern"
|
|
137
|
-
);
|
|
138
|
-
if (assignmentPatternIndex != -1) {
|
|
139
|
-
if (
|
|
140
|
-
p[assignmentPatternIndex].right == (p[assignmentPatternIndex - 1] || o)
|
|
141
|
-
) {
|
|
142
|
-
var sliced = p.slice(assignmentPatternIndex);
|
|
143
|
-
var fnIndex = sliced.findIndex((x) => isFunction(x));
|
|
144
|
-
var associatedFn = sliced[fnIndex];
|
|
145
|
-
if (
|
|
146
|
-
fnIndex !== -1 &&
|
|
147
|
-
sliced[fnIndex].params == (sliced[fnIndex - 1] || o)
|
|
148
|
-
) {
|
|
149
|
-
if (associatedFn == getVarContext(o, p)) {
|
|
150
|
-
return isLexContext(associatedFn.body)
|
|
151
|
-
? [associatedFn, associatedFn.body]
|
|
152
|
-
: [associatedFn];
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
136
|
+
if (!info) {
|
|
137
|
+
info = getIdentifierInfo(o, p);
|
|
156
138
|
}
|
|
139
|
+
ok(info.spec.isReferenced);
|
|
157
140
|
|
|
158
141
|
return [getVarContext(o, p), getLexContext(o, p)];
|
|
159
142
|
}
|
|
@@ -314,11 +297,11 @@ export function isForInitialize(o, p): "initializer" | "left-hand" | false {
|
|
|
314
297
|
);
|
|
315
298
|
if (forIndex !== -1) {
|
|
316
299
|
if (p[forIndex].type == "ForStatement") {
|
|
317
|
-
if (p[forIndex].init == p[forIndex - 1] || o) {
|
|
300
|
+
if (p[forIndex].init == (p[forIndex - 1] || o)) {
|
|
318
301
|
return "initializer";
|
|
319
302
|
}
|
|
320
303
|
} else {
|
|
321
|
-
if (p[forIndex].left == p[forIndex - 1] || o) {
|
|
304
|
+
if (p[forIndex].left == (p[forIndex - 1] || o)) {
|
|
322
305
|
return "left-hand";
|
|
323
306
|
}
|
|
324
307
|
}
|
|
@@ -326,52 +309,3 @@ export function isForInitialize(o, p): "initializer" | "left-hand" | false {
|
|
|
326
309
|
|
|
327
310
|
return false;
|
|
328
311
|
}
|
|
329
|
-
|
|
330
|
-
export function isInBranch(object: Node, parents: Node[], context: Node) {
|
|
331
|
-
ok(object);
|
|
332
|
-
ok(parents);
|
|
333
|
-
ok(context);
|
|
334
|
-
|
|
335
|
-
ok(parents.includes(context));
|
|
336
|
-
|
|
337
|
-
var definingContext =
|
|
338
|
-
parents[0].type == "FunctionDeclaration" && parents[0].id == object
|
|
339
|
-
? getVarContext(parents[0], parents.slice(1))
|
|
340
|
-
: getVarContext(object, parents);
|
|
341
|
-
|
|
342
|
-
var contextIndex = parents.findIndex((x) => x === context);
|
|
343
|
-
var slicedParents = parents.slice(0, contextIndex);
|
|
344
|
-
|
|
345
|
-
ok(!slicedParents.includes(object), "slicedParents includes object");
|
|
346
|
-
|
|
347
|
-
var slicedTypes = new Set(slicedParents.map((x) => x.type));
|
|
348
|
-
|
|
349
|
-
var isBranch = definingContext !== context;
|
|
350
|
-
if (!isBranch) {
|
|
351
|
-
if (
|
|
352
|
-
[
|
|
353
|
-
"IfStatement",
|
|
354
|
-
"ForStatement",
|
|
355
|
-
"ForInStatement",
|
|
356
|
-
"ForOfStatement",
|
|
357
|
-
"WhileStatement",
|
|
358
|
-
"DoWhileStatement",
|
|
359
|
-
"SwitchStatement",
|
|
360
|
-
"ConditionalExpression",
|
|
361
|
-
"LogicalExpression",
|
|
362
|
-
"TryStatement",
|
|
363
|
-
"ChainExpression",
|
|
364
|
-
"BinaryExpression",
|
|
365
|
-
"FunctionExpression",
|
|
366
|
-
"FunctionDeclaration",
|
|
367
|
-
"ArrowFunctionExpression",
|
|
368
|
-
"ClassExpression",
|
|
369
|
-
"ClassDeclaration",
|
|
370
|
-
].find((x) => slicedTypes.has(x))
|
|
371
|
-
) {
|
|
372
|
-
isBranch = true;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
return isBranch;
|
|
377
|
-
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { isBlock } from "../traverse";
|
|
2
|
+
|
|
3
|
+
export function isLexicalScope(object) {
|
|
4
|
+
return isBlock(object) || object.type == "SwitchCase";
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function getLexicalScope(object, parents) {
|
|
8
|
+
return [object, ...parents].find((node) => isLexicalScope(node));
|
|
9
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { isIndependent } from "
|
|
1
|
+
import { isIndependent } from "../src/util/compare";
|
|
2
2
|
import {
|
|
3
3
|
ArrayExpression,
|
|
4
4
|
FunctionExpression,
|
|
5
5
|
Identifier,
|
|
6
6
|
Literal,
|
|
7
|
-
} from "
|
|
7
|
+
} from "../src/util/gen";
|
|
8
8
|
|
|
9
9
|
describe("isIndependent", () => {
|
|
10
10
|
it("should return true for literals", () => {
|
package/test/index.test.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import JsConfuser
|
|
1
|
+
import JsConfuser, {
|
|
2
|
+
debugObfuscation,
|
|
3
|
+
debugTransformations,
|
|
4
|
+
} from "../src/index";
|
|
2
5
|
|
|
3
6
|
it("should be a function", async () => {
|
|
4
7
|
expect(typeof JsConfuser).toBe("function");
|
|
@@ -126,3 +129,108 @@ it("should error when invalid endDate is passed in", async () => {
|
|
|
126
129
|
return await JsConfuser("5+5", invalid);
|
|
127
130
|
}).rejects.toThrow();
|
|
128
131
|
});
|
|
132
|
+
|
|
133
|
+
it("should error when source code is not a string", async () => {
|
|
134
|
+
await expect(async () => {
|
|
135
|
+
return await JsConfuser({} as any, {
|
|
136
|
+
target: "node",
|
|
137
|
+
preset: "low",
|
|
138
|
+
});
|
|
139
|
+
}).rejects.toThrow();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("should error when invalid source code is passed in", async () => {
|
|
143
|
+
await expect(async () => {
|
|
144
|
+
return await JsConfuser("#?!if?//for:;1(function:class{))]][]", {
|
|
145
|
+
target: "node",
|
|
146
|
+
preset: "low",
|
|
147
|
+
});
|
|
148
|
+
}).rejects.toThrow();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe("obfuscateAST", () => {
|
|
152
|
+
test("Variant #1: Mutate AST", async () => {
|
|
153
|
+
var AST = {
|
|
154
|
+
type: "Program",
|
|
155
|
+
body: [
|
|
156
|
+
{
|
|
157
|
+
type: "ExpressionStatement",
|
|
158
|
+
expression: { type: "Literal", value: true },
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
};
|
|
162
|
+
var before = JSON.stringify(AST);
|
|
163
|
+
|
|
164
|
+
JsConfuser.obfuscateAST(AST, { target: "node", es5: true });
|
|
165
|
+
|
|
166
|
+
var after = JSON.stringify(AST);
|
|
167
|
+
|
|
168
|
+
// Same object reference
|
|
169
|
+
expect(AST === AST).toStrictEqual(true);
|
|
170
|
+
|
|
171
|
+
// Different string
|
|
172
|
+
expect(before !== after).toStrictEqual(false);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("Variant #2: Error on invalid parameters", async () => {
|
|
176
|
+
await expect(async () => {
|
|
177
|
+
return await JsConfuser.obfuscateAST("string", {
|
|
178
|
+
target: "node",
|
|
179
|
+
preset: "low",
|
|
180
|
+
});
|
|
181
|
+
}).rejects.toThrow();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("Variant #3: Error on invalid AST", async () => {
|
|
185
|
+
await expect(async () => {
|
|
186
|
+
var invalidAST = {
|
|
187
|
+
type: "NotProgram",
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
return await JsConfuser.obfuscateAST(invalidAST, {
|
|
191
|
+
target: "node",
|
|
192
|
+
preset: "low",
|
|
193
|
+
});
|
|
194
|
+
}).rejects.toThrow();
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
describe("debugTransformations", () => {
|
|
199
|
+
test("Variant #1: Return array of objects containing `name`, `code`, and `ms` properties", async () => {
|
|
200
|
+
var frames = await debugTransformations(`console.log(1)`, {
|
|
201
|
+
target: "node",
|
|
202
|
+
preset: "low",
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
expect(Array.isArray(frames)).toStrictEqual(true);
|
|
206
|
+
expect(frames.length).toBeTruthy();
|
|
207
|
+
|
|
208
|
+
frames.forEach((frame) => {
|
|
209
|
+
expect(typeof frame.name).toStrictEqual("string");
|
|
210
|
+
expect(typeof frame.code).toStrictEqual("string");
|
|
211
|
+
expect(typeof frame.ms).toStrictEqual("number");
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe("debugObfuscation", () => {
|
|
217
|
+
test("Variant #1: Return array of objects containing code, ms, and name properties", async () => {
|
|
218
|
+
var called = false;
|
|
219
|
+
|
|
220
|
+
var callback = (name, complete, totalTransforms) => {
|
|
221
|
+
expect(typeof name).toStrictEqual("string");
|
|
222
|
+
expect(typeof complete).toStrictEqual("number");
|
|
223
|
+
expect(typeof totalTransforms).toStrictEqual("number");
|
|
224
|
+
|
|
225
|
+
called = true;
|
|
226
|
+
};
|
|
227
|
+
var output = await debugObfuscation(
|
|
228
|
+
`console.log(1)`,
|
|
229
|
+
{ target: "node", preset: "low" },
|
|
230
|
+
callback
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
expect(typeof output).toStrictEqual("string");
|
|
234
|
+
expect(called).toStrictEqual(true);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Template from "../../src/templates/template";
|
|
2
|
+
|
|
3
|
+
describe("Template", () => {
|
|
4
|
+
test("Variant #1: Error when invalid code passed in", () => {
|
|
5
|
+
var _consoleError = console.error;
|
|
6
|
+
console.error = null;
|
|
7
|
+
|
|
8
|
+
expect(() => {
|
|
9
|
+
Template(`#&!#Ylet{}class)--1]?|:!@#`).compile();
|
|
10
|
+
}).toThrow();
|
|
11
|
+
|
|
12
|
+
console.error = _consoleError;
|
|
13
|
+
});
|
|
14
|
+
});
|