Skip to content

Commit 2ec449a

Browse files
authored
Merge pull request #65 from MichaelXF/dev
1.5.6
2 parents 126f0b4 + 825f7d4 commit 2ec449a

File tree

10 files changed

+308
-72
lines changed

10 files changed

+308
-72
lines changed

CHANGELOG.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,26 @@
1+
# `1.5.6`
2+
Website changed and RGF fixes
3+
4+
The website is back at a different domain now: [https://master--hungry-shannon-c1ce6b.netlify.app/](https://master--hungry-shannon-c1ce6b.netlify.app/)
5+
6+
This update focuses on fixing RGF bugs
7+
8+
- Fixed [#64](https://github.com/MichaelXF/js-confuser/issues/64)
9+
- - RGF to properly handle Arrow functions and function expressions
10+
11+
- RGF will no longer change getter/setter methods
12+
13+
- RGF will no longer change class methods
14+
15+
- RGF now works when using `mangled` variable names
16+
17+
- Minify will remove unreachable code following a Throw statement
18+
119
# `1.5.5`
220
Updates
321

422
- Fixed [#53](https://github.com/MichaelXF/js-confuser/issues/53)
5-
- - Shuffle to not use common varialbe names like `x`
23+
- - Shuffle to not use common variable names like `x`
624

725
- Fixed [#60](https://github.com/MichaelXF/js-confuser/issues/60)
826
- - Rename Variables to properly handle function parameters
@@ -447,7 +465,7 @@ Available now on NPM: https://www.npmjs.com/package/js-confuser
447465
# `1.1.7`
448466
Website is Live
449467

450-
- [JsConfuser.com](https://jsconfuser.com) is live!
468+
- [https://master--hungry-shannon-c1ce6b.netlify.app/](https://master--hungry-shannon-c1ce6b.netlify.app/) is live!
451469
- Check out the [js-confuser-website](https://github.com/MichaelXF/js-confuser-website) repo for more info
452470

453471
- **⚠️ Breaking change**: `Rename Globals` is now enabled by default

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# JS Confuser
22

3-
JS-Confuser is a JavaScript obfuscation tool to make your programs _impossible_ to read. [Try the web version](https://jsconfuser.com).
3+
JS-Confuser is a JavaScript obfuscation tool to make your programs _impossible_ to read. [Try the web version](https://master--hungry-shannon-c1ce6b.netlify.app/).
44

5-
[![NPM](https://img.shields.io/badge/NPM-%23000000.svg?style=for-the-badge&logo=npm&logoColor=white)](https://npmjs.com/package/js-confuser) [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/MichaelXF/js-confuser) [![Netlify](https://img.shields.io/badge/netlify-%23000000.svg?style=for-the-badge&logo=netlify&logoColor=#00C7B7)](https://jsconfuser.com)
5+
[![NPM](https://img.shields.io/badge/NPM-%23000000.svg?style=for-the-badge&logo=npm&logoColor=white)](https://npmjs.com/package/js-confuser) [![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)](https://github.com/MichaelXF/js-confuser) [![Netlify](https://img.shields.io/badge/netlify-%23000000.svg?style=for-the-badge&logo=netlify&logoColor=#00C7B7)](https://master--hungry-shannon-c1ce6b.netlify.app/)
66

77
## Key features
88

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "js-confuser",
3-
"version": "1.5.5",
3+
"version": "1.5.6",
44
"description": "JavaScript Obfuscation Tool.",
55
"main": "dist/index.js",
66
"types": "index.d.ts",
@@ -45,7 +45,7 @@
4545
"bugs": {
4646
"url": "https://github.com/MichaelXF/js-confuser/issues"
4747
},
48-
"homepage": "https://jsconfuser.com",
48+
"homepage": "https://master--hungry-shannon-c1ce6b.netlify.app/",
4949
"jest": {
5050
"coverageReporters": [
5151
"html"

src/transforms/flatten.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ export default class Flatten extends Transform {
328328
var pop = CallExpression(
329329
MemberExpression(
330330
MemberExpression(Identifier(resultName), Identifier(propName), false),
331-
Identifier("pop"),
332-
false
331+
Literal("pop"),
332+
true
333333
),
334334
[]
335335
);

src/transforms/identifier/variableAnalysis.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,10 @@ export default class VariableAnalysis extends Transform {
9393
ok(definingContexts.length);
9494

9595
definingContexts.forEach((definingContext) => {
96-
ok(
97-
isContext(definingContext),
98-
`${definingContext.type} is not a context`
99-
);
96+
// ok(
97+
// isContext(definingContext),
98+
// `${definingContext.type} is not a context`
99+
// );
100100

101101
if (isDefined) {
102102
// Add to defined Map

src/transforms/minify.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ export default class Minify extends Transform {
6161

6262
body.forEach((stmt, i) => {
6363
if (
64-
stmt.type == "ReturnStatement" ||
65-
stmt.type == "BreakStatement" ||
66-
stmt.type == "ContinueStatement"
64+
stmt.type === "ReturnStatement" ||
65+
stmt.type === "BreakStatement" ||
66+
stmt.type === "ContinueStatement" ||
67+
stmt.type === "ThrowStatement"
6768
) {
6869
if (earlyReturn > i + 1) {
6970
earlyReturn = i + 1;
@@ -156,7 +157,7 @@ export default class Minify extends Transform {
156157
) {
157158
lastDec = x;
158159
} else {
159-
lastDec.declarations.push(...x.declarations);
160+
lastDec.declarations.push(...clone(x.declarations));
160161
remove.unshift(i);
161162
}
162163
} else {

src/transforms/rgf.ts

Lines changed: 125 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import Template from "../templates/template";
77
import traverse, { walk } from "../traverse";
88
import {
99
ArrayExpression,
10+
AssignmentExpression,
1011
CallExpression,
12+
ConditionalExpression,
13+
ExpressionStatement,
1114
FunctionExpression,
1215
Identifier,
1316
Literal,
@@ -28,6 +31,7 @@ import {
2831
isFunction,
2932
prepend,
3033
} from "../util/insert";
34+
import { getRandomString } from "../util/random";
3135
import Transform from "./transform";
3236

3337
/**
@@ -70,6 +74,8 @@ export default class RGF extends Transform {
7074
}[] = [];
7175
var queue: Location[] = [];
7276
var names = new Map<string, number>();
77+
var referenceSignatures: { [name: string]: string } = {};
78+
7379
var definingNodes = new Map<string, Node>();
7480

7581
walk(contextObject, contextParents, (object, parents) => {
@@ -81,6 +87,25 @@ export default class RGF extends Transform {
8187
!object.generator &&
8288
getVarContext(parents[0], parents.slice(1)) === contextObject
8389
) {
90+
// Discard getter/setter methods
91+
if (parents[0].type === "Property" && parents[0].value === object) {
92+
if (
93+
parents[0].method ||
94+
parents[0].kind === "get" ||
95+
parents[0].kind === "set"
96+
) {
97+
return;
98+
}
99+
}
100+
101+
// Discard class methods
102+
if (
103+
parents[0].type === "MethodDefinition" &&
104+
parents[0].value === object
105+
) {
106+
return;
107+
}
108+
84109
var defined = new Set<string>(),
85110
referenced = new Set<string>();
86111

@@ -177,6 +202,8 @@ export default class RGF extends Transform {
177202
var index = names.size;
178203

179204
names.set(object.id.name, index);
205+
referenceSignatures[index] = getRandomString(10);
206+
180207
definingNodes.set(object.id.name, object.id);
181208
}
182209
}
@@ -186,7 +213,8 @@ export default class RGF extends Transform {
186213
return;
187214
}
188215

189-
var referenceArray = this.generateIdentifier();
216+
// An array containing all the function declarations
217+
var referenceArray = "_" + getRandomString(10);
190218

191219
walk(contextObject, contextParents, (o, p) => {
192220
if (o.type == "Identifier" && !reservedIdentifiers.has(o.name)) {
@@ -204,27 +232,50 @@ export default class RGF extends Transform {
204232
if (pointingTo == shouldBe) {
205233
this.log(o.name, "->", `${referenceArray}[${index}]`);
206234

207-
this.replace(
208-
o,
209-
FunctionExpression(
210-
[],
211-
[
212-
ReturnStatement(
213-
CallExpression(
214-
MemberExpression(
215-
Identifier(referenceArray),
216-
Literal(index),
217-
true
218-
),
219-
[
235+
var memberExpression = MemberExpression(
236+
Identifier(referenceArray),
237+
Literal(index),
238+
true
239+
);
240+
241+
// Allow re-assignment to the RGF function
242+
if (
243+
p[0] &&
244+
p[0].type === "AssignmentExpression" &&
245+
p[0].left === o
246+
) {
247+
// fn = ...
248+
249+
this.replace(o, memberExpression);
250+
} else {
251+
// fn()
252+
// fn
253+
254+
// In most cases the identifier is being used like this (call expression, or referenced to be called later)
255+
// Replace it with a simple wrapper function that will pass on the reference array
256+
257+
var conditionalExpression = ConditionalExpression(
258+
Template(
259+
`typeof ${referenceArray}[${index}] === "function" && ${referenceArray}[${index}]["${
260+
referenceSignatures[index] || "_"
261+
}"]`
262+
).single().expression,
263+
FunctionExpression(
264+
[],
265+
[
266+
ReturnStatement(
267+
CallExpression(memberExpression, [
220268
Identifier(referenceArray),
221269
SpreadElement(Identifier("arguments")),
222-
]
223-
)
224-
),
225-
]
226-
)
227-
);
270+
])
271+
),
272+
]
273+
),
274+
memberExpression
275+
);
276+
277+
this.replace(o, conditionalExpression);
278+
}
228279
}
229280
}
230281
}
@@ -243,6 +294,7 @@ export default class RGF extends Transform {
243294
var name = object?.id?.name;
244295
var hasName = !!name;
245296
var params = object.params.map((x) => x.name) || [];
297+
var signature = referenceSignatures[names.get(name)];
246298

247299
var embeddedName = name || this.getPlaceholder();
248300

@@ -280,11 +332,11 @@ export default class RGF extends Transform {
280332
CallExpression(
281333
MemberExpression(
282334
Identifier(embeddedName),
283-
Identifier("call"),
284-
false
335+
Literal("call"),
336+
true
285337
),
286338
[
287-
ThisExpression(),
339+
Identifier("undefined"),
288340
SpreadElement(
289341
Template(
290342
`Array.prototype.slice.call(arguments, 1)`
@@ -322,8 +374,38 @@ export default class RGF extends Transform {
322374
Literal(toString),
323375
]);
324376

325-
if (hasName) {
326-
arrayExpression.elements[names.get(name)] = newFunction;
377+
function applySignature(fn) {
378+
if (!signature) {
379+
return fn;
380+
}
381+
382+
// This code marks the function object with a unique property
383+
return CallExpression(
384+
FunctionExpression(
385+
[],
386+
[
387+
VariableDeclaration(VariableDeclarator("fn", fn)),
388+
ExpressionStatement(
389+
AssignmentExpression(
390+
"=",
391+
MemberExpression(
392+
Identifier("fn"),
393+
Literal(signature),
394+
true
395+
),
396+
Literal(true)
397+
)
398+
),
399+
ReturnStatement(Identifier("fn")),
400+
]
401+
),
402+
[]
403+
);
404+
}
405+
406+
if (object.type === "FunctionDeclaration") {
407+
arrayExpression.elements[names.get(name)] =
408+
applySignature(newFunction);
327409

328410
if (Array.isArray(parents[0])) {
329411
parents[0].splice(parents[0].indexOf(object), 1);
@@ -336,7 +418,24 @@ export default class RGF extends Transform {
336418
);
337419
}
338420
} else {
339-
this.replace(object, newFunction);
421+
// The wrapper function passes the reference array around
422+
var wrapperFunction = FunctionExpression(
423+
[],
424+
[
425+
ReturnStatement(
426+
CallExpression(
427+
MemberExpression(newFunction, Literal("call"), true),
428+
[
429+
Identifier("undefined"),
430+
Identifier(referenceArray),
431+
SpreadElement(Identifier("arguments")),
432+
]
433+
)
434+
),
435+
]
436+
);
437+
438+
this.replace(object, applySignature(wrapperFunction));
340439
}
341440
});
342441
};

src/transforms/string/stringSplitting.ts

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,11 @@ export default class StringSplitting extends Transform {
2525
this.vars = [];
2626
}
2727

28-
apply(tree) {
29-
super.apply(tree);
30-
31-
if (this.vars.length) {
32-
shuffle(this.adders);
33-
shuffle(this.vars);
34-
35-
var body: Node[] = tree.body;
36-
37-
this.adders.forEach((nodes) => {
38-
nodes.forEach((x) => body.unshift(x));
39-
});
40-
41-
var variableDeclaration = {
42-
type: "VariableDeclaration",
43-
declarations: [],
44-
kind: "var",
45-
};
46-
this.vars.forEach((node) => variableDeclaration.declarations.push(node));
47-
48-
body.unshift(variableDeclaration);
49-
}
50-
}
51-
5228
match(object: Node, parents: Node[]) {
5329
return (
5430
object.type == "Literal" &&
5531
typeof object.value === "string" &&
32+
object.value.length >= 8 &&
5633
!isModuleSource(object, parents) &&
5734
!isDirective(object, parents)
5835
);
@@ -87,7 +64,6 @@ export default class StringSplitting extends Transform {
8764
var last = chunks.pop();
8865
chunks.forEach((chunk, i) => {
8966
if (i == 0) {
90-
ok(i == 0);
9167
parent = binaryExpression = BinaryExpression(
9268
"+",
9369
Literal(chunk),

0 commit comments

Comments
 (0)