Skip to content

Commit df987d8

Browse files
authored
Merge pull request #83 from MichaelXF/dev
1.5.9
2 parents 69813d3 + 4182c36 commit df987d8

40 files changed

+1072
-217
lines changed

CHANGELOG.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,40 @@
1+
# `1.5.9`
2+
Big update
3+
4+
This updates comes with many bug fixes:
5+
6+
- Fixed [#72](https://github.com/MichaelXF/js-confuser/issues/72)
7+
- - ES5 to handle Class Fields
8+
9+
Note: The `ES5` option is not meant to replace Babel. It is only intended to undo ES6 features the obfuscator may have added to your code.
10+
11+
- Fixed [#74](https://github.com/MichaelXF/js-confuser/issues/74)
12+
- - Anti Tooling to not break Symbols
13+
14+
- Fixed [#75](https://github.com/MichaelXF/js-confuser/issues/75)
15+
- - Minify to properly handle Object constructors
16+
17+
- Fixed [#76](https://github.com/MichaelXF/js-confuser/issues/76)
18+
- - Minify to not cause syntax errors when objects used `^`, `` ` ``, `[`, `]` as property keys
19+
20+
- Fixed [#77](https://github.com/MichaelXF/js-confuser/issues/77)
21+
- - Dispatcher to not break code that uses generic names like `toString` and `hasOwnProperty`
22+
23+
- Fixed [#78](https://github.com/MichaelXF/js-confuser/issues/78)
24+
- - Object Extraction to not error on objects with spread elements
25+
26+
- Fixed [#79](https://github.com/MichaelXF/js-confuser/issues/79)
27+
- - JsConfuser now supports `BigInt` literals
28+
29+
- Fixed [#80](https://github.com/MichaelXF/js-confuser/issues/80)
30+
- - Rename Variables to not break code that had `var` and `let` variables in the same scope
31+
32+
- Fixed [#81](https://github.com/MichaelXF/js-confuser/issues/81)
33+
- - Control Flow Flattening to not break `typeof` expressions
34+
35+
- Fixed [#82](https://github.com/MichaelXF/js-confuser/issues/82)
36+
- - String Concealing to not break class constructors
37+
138
# `1.5.8`
239
Several fixes
340

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "js-confuser",
3-
"version": "1.5.8",
3+
"version": "1.5.9",
44
"description": "JavaScript Obfuscation Tool.",
55
"main": "dist/index.js",
66
"types": "index.d.ts",

src/index.ts

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Obfuscator from "./obfuscator";
44
import Transform from "./transforms/transform";
55
import { remove$Properties } from "./util/object";
66
import presets from "./presets";
7+
import { performance } from "perf_hooks";
78

89
import * as assert from "assert";
910
import { correctOptions, ObfuscateOptions, validateOptions } from "./options";
@@ -85,8 +86,8 @@ var JsConfuser: IJsConfuser = async function (
8586
return result;
8687
} as any;
8788

88-
export var debugTransformations: IJsConfuserDebugTransformations =
89-
async function debugTransformations(
89+
export const debugTransformations: IJsConfuserDebugTransformations =
90+
async function (
9091
code: string,
9192
options: ObfuscateOptions
9293
): Promise<{ name: string; code: string; ms: number }[]> {
@@ -115,28 +116,65 @@ export var debugTransformations: IJsConfuserDebugTransformations =
115116
return frames;
116117
};
117118

118-
export var debugObfuscation: IJsConfuserDebugObfuscation =
119-
async function debugTransformations(
120-
code: string,
121-
options: ObfuscateOptions,
122-
callback: (name: string, complete: number, totalTransforms: number) => void
123-
): Promise<string> {
124-
validateOptions(options);
125-
options = await correctOptions(options);
119+
/**
120+
* This method is used by the obfuscator website to display a progress bar and additional information
121+
* about the obfuscation.
122+
*
123+
* @param code - Source code to obfuscate
124+
* @param options - Options
125+
* @param callback - Progress callback, called after each transformation
126+
* @returns
127+
*/
128+
export const debugObfuscation: IJsConfuserDebugObfuscation = async function (
129+
code: string,
130+
options: ObfuscateOptions,
131+
callback: (name: string, complete: number, totalTransforms: number) => void
132+
) {
133+
const startTime = performance.now();
126134

127-
var tree = parseSync(code);
128-
var obfuscator = new Obfuscator(options);
129-
var totalTransforms = obfuscator.array.length;
135+
validateOptions(options);
136+
options = await correctOptions(options);
130137

131-
obfuscator.on("debug", (name: string, tree: Node, i: number) => {
132-
callback(name, i, totalTransforms);
133-
});
138+
const beforeParseTime = performance.now();
134139

135-
await obfuscator.apply(tree, true);
140+
var tree = parseSync(code);
141+
142+
const parseTime = performance.now() - beforeParseTime;
143+
144+
var obfuscator = new Obfuscator(options);
145+
var totalTransforms = obfuscator.array.length;
146+
147+
var transformationTimes = Object.create(null);
148+
var currentTransformTime = performance.now();
149+
150+
obfuscator.on("debug", (name: string, tree: Node, i: number) => {
151+
var nowTime = performance.now();
152+
transformationTimes[name] = nowTime - currentTransformTime;
153+
currentTransformTime = nowTime;
154+
155+
callback(name, i, totalTransforms);
156+
});
157+
158+
await obfuscator.apply(tree, true);
159+
160+
const beforeCompileTime = performance.now();
161+
162+
var output = await compileJs(tree, options);
163+
164+
const compileTime = performance.now() - beforeCompileTime;
165+
166+
const endTime = performance.now();
136167

137-
var output = compileJs(tree, options);
138-
return output;
168+
return {
169+
obfuscated: output,
170+
transformationTimes: transformationTimes,
171+
obfuscationTime: endTime - startTime,
172+
parseTime: parseTime,
173+
compileTime: compileTime,
174+
totalTransforms: totalTransforms,
175+
totalPossibleTransforms: obfuscator.totalPossibleTransforms,
139176
};
177+
};
140178

141179
JsConfuser.obfuscate = obfuscate;
142180
JsConfuser.obfuscateAST = obfuscateAST;

src/obfuscator.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,22 @@ export default class Obfuscator extends EventEmitter {
4747
state: "transform" | "eval" = "transform";
4848
generated: Set<string>;
4949

50+
totalPossibleTransforms: number;
51+
5052
constructor(public options: ObfuscateOptions) {
5153
super();
5254

5355
this.varCount = 0;
5456
this.transforms = Object.create(null);
5557
this.generated = new Set();
58+
this.totalPossibleTransforms = 0;
5659

5760
this.push(new Preparation(this));
5861
this.push(new RenameLabels(this));
5962

6063
const test = <T>(map: ProbabilityMap<T>, ...transformers: any[]) => {
64+
this.totalPossibleTransforms += transformers.length;
65+
6166
if (isProbabilityMapProbable(map)) {
6267
// options.verbose && console.log("+ Added " + transformer.name);
6368

@@ -97,7 +102,7 @@ export default class Obfuscator extends EventEmitter {
97102
test(options.stack, Stack);
98103
test(true, AntiTooling);
99104
test(options.hideInitializingCode, HideInitializingCode);
100-
test(options.hexadecimalNumbers, HexadecimalNumbers);
105+
test(true, HexadecimalNumbers); // BigInt support is included
101106

102107
if (
103108
options.lock &&

src/options.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -867,8 +867,7 @@ export async function correctOptions(
867867
options.compact = true; // self defending forcibly enables this
868868
}
869869

870-
// options.globalVariables was never used.
871-
// GlobalConcealing implicitly determines a global to be a variable referenced but never defined or modified.
870+
// options.globalVariables outlines generic globals that should be present in the execution context
872871
if (!options.hasOwnProperty("globalVariables")) {
873872
options.globalVariables = new Set([]);
874873

@@ -908,6 +907,10 @@ export async function correctOptions(
908907
"Array",
909908
"Proxy",
910909
"Error",
910+
"TypeError",
911+
"ReferenceError",
912+
"RangeError",
913+
"EvalError",
911914
"setTimeout",
912915
"clearTimeout",
913916
"setInterval",
@@ -919,6 +922,11 @@ export async function correctOptions(
919922
"module",
920923
"isNaN",
921924
"isFinite",
925+
"Set",
926+
"Map",
927+
"WeakSet",
928+
"WeakMap",
929+
"Symbol",
922930
].forEach((x) => options.globalVariables.add(x));
923931
}
924932

src/order.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ export enum ObfuscateOrder {
4444

4545
MovedDeclarations = 26,
4646

47-
RenameVariables = 27,
47+
RenameLabels = 27,
4848

49-
RenameLabels = 28,
49+
Minify = 28,
5050

51-
Minify = 30,
51+
RenameVariables = 30,
5252

5353
ES5 = 31,
5454

src/transforms/antiTooling.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export default class AntiTooling extends Transform {
4545
exprs[0],
4646
ExpressionStatement(
4747
UnaryExpression(
48-
choice(["typeof", "void", "~", "!", "+"]),
48+
choice(["typeof", "void", "!"]),
4949
SequenceExpression(flattened)
5050
)
5151
)

src/transforms/controlFlowFlattening/expressionObfuscation.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ export default class ExpressionObfuscation extends Transform {
2020
if (stmt.type == "ExpressionStatement") {
2121
var expr = stmt.expression;
2222

23-
if (expr.type == "UnaryExpression" && exprs.length) {
23+
if (
24+
expr.type == "UnaryExpression" &&
25+
!(
26+
expr.operator === "typeof" && expr.argument.type === "Identifier"
27+
) &&
28+
exprs.length // typeof is special
29+
) {
2430
expr.argument = SequenceExpression([
2531
...exprs,
2632
{ ...expr.argument },
@@ -38,7 +44,13 @@ export default class ExpressionObfuscation extends Transform {
3844
stmt.test.type == "BinaryExpression" &&
3945
stmt.test.operator !== "**"
4046
) {
41-
if (stmt.test.left.type == "UnaryExpression") {
47+
if (
48+
stmt.test.left.type == "UnaryExpression" &&
49+
!(
50+
stmt.test.left.operator === "typeof" &&
51+
stmt.test.left.argument.type === "Identifier"
52+
) // typeof is special
53+
) {
4254
stmt.test.left.argument = SequenceExpression([
4355
...exprs,
4456
{ ...stmt.test.left.argument },

src/transforms/dispatcher.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,15 @@ export default class Dispatcher extends Transform {
9797
}
9898

9999
// Map of FunctionDeclarations
100-
var functionDeclarations: { [name: string]: Location } = {};
100+
var functionDeclarations: { [name: string]: Location } =
101+
Object.create(null);
101102

102103
// Array of Identifier nodes
103104
var identifiers: Location[] = [];
104105
var illegalFnNames: Set<string> = new Set();
105106

106107
// New Names for Functions
107-
var newFnNames: { [name: string]: string } = {}; // [old name]: randomized name
108+
var newFnNames: { [name: string]: string } = Object.create(null); // [old name]: randomized name
108109

109110
var context = isVarContext(object)
110111
? object
@@ -469,7 +470,7 @@ export default class Dispatcher extends Transform {
469470
}
470471

471472
var newName = newFnNames[o.name];
472-
if (!newName) {
473+
if (!newName || typeof newName !== "string") {
473474
return;
474475
}
475476

src/transforms/es5/antiClass.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,16 @@ export default class AntiClass extends Transform {
110110
);
111111
}
112112

113-
if (
113+
// Support class fields
114+
if (methodDefinition.type === "PropertyDefinition") {
115+
var assignmentExpression = AssignmentExpression(
116+
"=",
117+
key,
118+
value || Identifier("undefined")
119+
);
120+
121+
pushingTo.push(ExpressionStatement(assignmentExpression));
122+
} else if (
114123
methodDefinition.kind == "constructor" ||
115124
methodDefinition.kind == "method"
116125
) {

src/transforms/es5/antiDestructuring.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ export default class AntiDestructuring extends Transform {
266266
]);
267267

268268
if (object.type == "VariableDeclarator") {
269-
var i = getIndexDirect(object, parents);
269+
var i = getIndexDirect(object, parents[0]);
270270

271271
var extra = Array.from(names).map((x) => {
272272
return {

src/transforms/eval.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@ export default class Eval extends Transform {
2828
}
2929

3030
transform(object, parents) {
31+
// Don't apply to getter/setters or class methods
32+
if (parents[0]) {
33+
if (
34+
parents[0].type === "MethodDefinition" &&
35+
parents[0].value === object
36+
) {
37+
return;
38+
}
39+
40+
if (
41+
parents[0].type === "Property" &&
42+
parents[0].value === object &&
43+
(parents[0].kind !== "init" || parents[0].method)
44+
) {
45+
return;
46+
}
47+
}
48+
3149
if (
3250
!ComputeProbabilityMap(
3351
this.options.eval,

src/transforms/extraction/duplicateLiteralsRemoval.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ export default class DuplicateLiteralsRemoval extends Transform {
159159
var body = [];
160160
var thisShift = getRandomInteger(-250, 250);
161161
// the name of the getter
162-
getterName = this.getPlaceholder();
162+
getterName = this.getPlaceholder() + "_dLR_" + this.fnGetters.size;
163163

164164
if (basedOn) {
165165
var shift = this.fnShifts.get(basedOn);
@@ -268,20 +268,20 @@ export default class DuplicateLiteralsRemoval extends Transform {
268268
this.arrayExpression = ArrayExpression([]);
269269
}
270270

271-
var first = this.first.get(value);
272-
if (first) {
271+
var firstLocation = this.first.get(value);
272+
if (firstLocation) {
273273
this.first.set(value, null);
274274
var index = this.map.size;
275275

276276
ok(!this.map.has(value));
277277
this.map.set(value, index);
278278

279-
this.toCaller(first[0], first[1], index);
280-
281279
var pushing = clone(object);
282280
this.arrayExpression.elements.push(pushing);
283281

284282
ok(this.arrayExpression.elements[index] === pushing);
283+
284+
this.toCaller(firstLocation[0], firstLocation[1], index);
285285
}
286286

287287
var index = this.map.get(value);

0 commit comments

Comments
 (0)