Skip to content

Commit b1fcb1d

Browse files
authored
Merge pull request #109 from MichaelXF/dev
1.7.1
2 parents e96f582 + 8ebc6a6 commit b1fcb1d

16 files changed

+404
-34
lines changed

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
# `1.7.1`
2+
Updates
3+
4+
- Fixed [#107](https://github.com/MichaelXF/js-confuser/issues/107)
5+
- - RGF and Integrity clash issue fixed
6+
7+
- Fixed [#106](https://github.com/MichaelXF/js-confuser/issues/106)
8+
- - Object Extraction to properly handle `const` objects
9+
10+
- Fixed [#105](https://github.com/MichaelXF/js-confuser/issues/105)
11+
- - Duplicate Literals Removal updated to not cause this error
12+
13+
- Fixed [#103](https://github.com/MichaelXF/js-confuser/issues/103)
14+
- - Dispatcher will no longer apply to these types of functions to prevent this error
15+
16+
- Added documentation page for [ES5](https://github.com/MichaelXF/js-confuser/blob/master/docs/ES5.md)
17+
18+
- Rollup Plugin created: https://github.com/ayecue/rollup-js-confuser (Thanks @ayecue !)
19+
120
# `1.7.0`
221
Updates
322

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,6 @@ function iVQoGQD(...iVQoGQD){
737737
stringSplitting: 0.75,
738738

739739
// Use at own risk
740-
eval: false,
741740
rgf: false
742741
}
743742
```
@@ -828,7 +827,6 @@ These features are experimental or a security concern.
828827
```js
829828
{
830829
target: "node",
831-
eval: true, // (security concern)
832830
rgf: true, // (security concern)
833831

834832
// set to false for web-related scripts

docs/ControlFlowFlattening.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ while (mJMdMhJ + A1Nyvv + xDwpOk6 != 83) {
137137
}
138138
```
139139

140-
As seen in the example, your code will bee wrapped in a large, complicated switch statement. The makes the behavior of your program very hard to understand and is resistent to deobfuscators. This comes with a large performance reduction.
140+
As seen in the example, your code will be wrapped in a large, complicated switch statement. The makes the behavior of your program very hard to understand and is resistent to deobfuscators. This comes with a large performance reduction.
141141

142142
## Flattening Control Structures
143143

docs/ES5.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
## `ES5`
2+
3+
The ES5 option converts most ES6+ features into ES5 compatible code.
4+
5+
Option name: `es5`
6+
7+
Option values: `true/false`
8+
9+
Note: Does not cover all cases such as Promises or Generator functions. Use [Babel](https://babel.dev/).
10+
11+
The ES5 option is intended to undo any ES6 feature the obfuscator adds to your code. If you input ES5 code, and enable the `es5` option, you can be guaranteed to have ES5 compatible output.
12+
13+
## Example
14+
15+
```js
16+
// Input
17+
function print(...messages){
18+
console.log(...messages); // The spread operator (...)
19+
// was introduced in ES6!
20+
}
21+
22+
print("Hello", "World"); // "Hello World"
23+
24+
// Output
25+
var __p_2580918143;
26+
function print() {
27+
var __p_7607361496;
28+
var messages, __p_2591841272 = (__p_7607361496 = Array.prototype.slice.call(arguments), messages = __p_7607361496.slice(0));
29+
(__p_2580918143 = console).log.apply(__p_2580918143, [].concat(Array.prototype.slice.call(messages)));
30+
}
31+
print('Hello', 'World'); // "Hello World"
32+
```
33+
34+
## Polyfill Array Methods
35+
36+
When the ES5 option is enabled, array method polyfills will be injected to the top of your script.
37+
38+
```js
39+
if (!Array.prototype.forEach) {
40+
Array.prototype.forEach = function forEach(callback, thisArg) {
41+
if (typeof callback !== 'function') {
42+
throw new TypeError(callback + ' is not a function');
43+
}
44+
var array = this;
45+
thisArg = thisArg || this;
46+
for (var i = 0, l = array.length; i !== l; ++i) {
47+
callback.call(thisArg, array[i], i, array);
48+
}
49+
};
50+
}
51+
```
52+
53+
## Destructuring
54+
55+
The ES5 option supports transpiling the destructuring patterns.
56+
57+
```js
58+
// Input
59+
var {userName, email} = { userName: "John", email: "email@exampe.com" };
60+
61+
// Output
62+
var __p_7467473759;
63+
var userName, email, __p_4755992742 = (__p_7467473759 = {
64+
userName: 'John',
65+
email: 'email@exampe.com'
66+
}, userName = __p_7467473759.userName, email = __p_7467473759.email);
67+
```
68+
69+
## Spread Operator
70+
71+
The ES5 option supports transpiling the spread operator.
72+
73+
```js
74+
// Input
75+
array.push(...objects);
76+
77+
// Output
78+
var __p_6344935930;
79+
(__p_6344935930 = array).push.apply(__p_6344935930, [].concat(Array.prototype.slice.call(objects)));
80+
```
81+
82+
## Template String
83+
84+
The ES5 option supports transpiling template strings.
85+
86+
```js
87+
// Input
88+
var myString = `Hello ${userName}`;
89+
90+
// Output
91+
var myString = 'Hello ' + (userName + '');
92+
```
93+
94+
## Object getters/setters
95+
96+
The ES5 option supports transpiling getter and setter methods.
97+
98+
```js
99+
// Input
100+
var _name;
101+
var myObject = {
102+
get name(){
103+
return _name;
104+
},
105+
set name(newName){
106+
_name = newName;
107+
}
108+
};
109+
110+
// Output
111+
function __p_6886881506(base, computedProps, getters, setters) {
112+
for (var i = 0; i < computedProps.length; i++) {
113+
base[computedProps[i][0]] = computedProps[i][1];
114+
}
115+
var keys = Object.create(null);
116+
Object.keys(getters).forEach(function (key) {
117+
return keys[key] = 1;
118+
});
119+
Object.keys(setters).forEach(function (key) {
120+
return keys[key] = 1;
121+
});
122+
Object.keys(keys).forEach(function (key) {
123+
Object.defineProperty(base, key, {
124+
set: setters[key],
125+
get: getters[key],
126+
configurable: true
127+
});
128+
});
129+
return base;
130+
}
131+
var _name;
132+
var myObject = __p_6886881506({}, [], {
133+
'name': function () {
134+
return _name;
135+
}
136+
}, {
137+
'name': function (newName) {
138+
_name = newName;
139+
}
140+
});
141+
```
142+
143+
## Arrow Functions
144+
145+
The ES5 option converts arrow functions into regular functions.
146+
147+
```js
148+
// Input
149+
var print = message => console.log(message);
150+
151+
// Output
152+
var print = function (message) {
153+
return console.log(message);
154+
};
155+
```
156+
157+
## Const/Let
158+
159+
The ES5 option converts `const` and `let` to a regular `var` keyword.
160+
161+
```js
162+
// Input
163+
let myVar1 = true;
164+
const myVar2 = "String";
165+
166+
// Output
167+
var myVar1 = true;
168+
var myVar2 = 'String';
169+
```
170+
171+
## Classes
172+
173+
The ES5 option partially supports transpiling classes.
174+
175+
## Reserved Identifiers
176+
177+
The ES5 option will change any illegal uses of reserved identifiers.
178+
179+
```js
180+
// Input
181+
var myObject = {true: 1};
182+
myObject.for = true;
183+
184+
// Output
185+
var myObject = {"true": 1};
186+
myObject["for"] = true;
187+
```
188+
189+
## Features not supported
190+
191+
- Promises
192+
- Async / Await
193+
- Generator functions
194+
- Nullish coalescing
195+
- Optional chaining
196+
197+
Use [Babel](https://babel.dev/) to transpile these features. JS-Confuser will only support features the obfuscator may potentially add to your code.

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.7.0",
3+
"version": "1.7.1",
44
"description": "JavaScript Obfuscation Tool.",
55
"main": "dist/index.js",
66
"types": "index.d.ts",
@@ -22,7 +22,7 @@
2222
"author": "MichaelXF",
2323
"license": "MIT",
2424
"dependencies": {
25-
"acorn": "^8.8.2",
25+
"acorn": "^8.10.0",
2626
"escodegen": "^2.0.0"
2727
},
2828
"devDependencies": {

src/transforms/dispatcher.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,16 @@ export default class Dispatcher extends Transform {
157157
return "EXIT";
158158
}
159159
}
160+
161+
// Avoid functions with function expressions as they have a different scope
162+
if (
163+
(oo.type === "FunctionExpression" ||
164+
oo.type === "ArrowFunctionExpression") &&
165+
pp.find((x) => x == o.params)
166+
) {
167+
illegalFnNames.add(name);
168+
return "EXIT";
169+
}
160170
});
161171

162172
functionDeclarations[name] = [o, p];

src/transforms/extraction/duplicateLiteralsRemoval.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { ComputeProbabilityMap } from "../../probability";
2424
import { ok } from "assert";
2525
import { chance, choice, getRandomInteger } from "../../util/random";
2626
import { getBlock } from "../../traverse";
27+
import { getIdentifierInfo } from "../../util/identifiers";
2728

2829
/**
2930
* [Duplicate Literals Removal](https://docs.jscrambler.com/code-integrity/documentation/transformations/duplicate-literals-removal) replaces duplicate literals with a variable name.
@@ -221,7 +222,10 @@ export default class DuplicateLiteralsRemoval extends Transform {
221222

222223
transform(object: Node, parents: Node[]) {
223224
return () => {
224-
var value = object.value;
225+
if (object.type === "Identifier") {
226+
var info = getIdentifierInfo(object, parents);
227+
if (info.isLabel || info.spec.isDefined) return;
228+
}
225229
if (object.regex) {
226230
return;
227231
}

src/transforms/extraction/objectExtraction.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,10 @@ export default class ObjectExtraction extends Transform {
316316
...variableDeclarators
317317
);
318318

319+
if (declaration.kind === "const") {
320+
declaration.kind = "var";
321+
}
322+
319323
// update all identifiers that pointed to the old object
320324
objectDefChanges[name] &&
321325
objectDefChanges[name].forEach((change) => {

src/transforms/rgf.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
} from "../util/gen";
2121
import { getIdentifierInfo } from "../util/identifiers";
2222
import { prepend, getDefiningContext } from "../util/insert";
23+
import Integrity from "./lock/integrity";
2324
import Transform from "./transform";
2425

2526
/**
@@ -200,6 +201,14 @@ export default class RGF extends Transform {
200201

201202
if (obfuscator.options.lock) {
202203
delete obfuscator.options.lock.countermeasures;
204+
205+
// Integrity will not recursively apply to RGF'd functions. This is intended.
206+
var lockTransform = obfuscator.transforms["Lock"];
207+
if (lockTransform) {
208+
lockTransform.before = lockTransform.before.filter(
209+
(beforeTransform) => !(beforeTransform instanceof Integrity)
210+
);
211+
}
203212
}
204213

205214
var transforms = obfuscator.array.filter(

src/util/identifiers.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,14 @@ export function getIdentifierInfo(object: Node, parents: Node[]) {
9494
parents.find((x) => x.type == "VariableDeclaration") &&
9595
objectPatternCheck(object, parents);
9696

97+
var functionIndex = parents.findIndex((x) => isFunction(x));
98+
9799
// Assignment pattern check!
98100
if (isVariableDeclaration) {
99-
var slicedParents = parents.slice(0, varIndex - 1);
101+
var slicedParents = parents.slice(
102+
0,
103+
functionIndex != -1 ? Math.min(varIndex, functionIndex) : varIndex
104+
);
100105
var i = 0;
101106
for (var parent of slicedParents) {
102107
var childNode = slicedParents[i - 1] || object;
@@ -113,8 +118,6 @@ export function getIdentifierInfo(object: Node, parents: Node[]) {
113118
forIndex != -1 &&
114119
parents[forIndex].init == (parents[forIndex - 1] || object);
115120

116-
var functionIndex = parents.findIndex((x) => isFunction(x));
117-
118121
var isFunctionDeclaration =
119122
functionIndex != -1 &&
120123
parents[functionIndex].type == "FunctionDeclaration" &&

0 commit comments

Comments
 (0)