Skip to content

Commit c5e5ec5

Browse files
authored
Merge pull request #135 from MichaelXF/dev
1.7.3
2 parents 5616830 + f35bfec commit c5e5ec5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2252
-394
lines changed

.github/workflows/node.js.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515

1616
strategy:
1717
matrix:
18-
node-version: [14.15, 16.10, 18.0]
18+
node-version: [14.15, 16.10, 18.0, 20.16]
1919
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
2020

2121
steps:

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,5 @@ ES6.output.js
122122
.vscode/
123123

124124
src/dev.ts
125+
126+
.DS_Store

CHANGELOG.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,38 @@
1+
# `1.7.3`
2+
Tamper Protection
3+
4+
### `Tamper Protection`
5+
6+
Tamper Protection safeguards the runtime behavior from being altered by JavaScript pitfalls.
7+
8+
[Learn more here.](/docs/TamperProtection.md)
9+
10+
---
11+
12+
- Rename Variables improvements:
13+
14+
- A new exposed function, `__JS_CONFUSER_VAR__`, can be used to access renamed variables. [Learn more here](/docs/RenameVariables.md).
15+
16+
17+
```js
18+
// Input
19+
var name = "John Doe";
20+
eval("console.log(" + __JS_CONFUSER_VAR__(name) + ")");
21+
22+
// Output
23+
var CA1HU0 = 'John Doe';
24+
eval('console.log(' + 'CA1HU0' + ')');
25+
```
26+
27+
- Improved the `Zero Width` identifier generator (Thanks @doctor8296!)
28+
29+
- Pad the `String Concealing` array with more fake strings
30+
31+
- Improve `String Compression`
32+
33+
- New Web UI sneak peak: https://new--confuser.netlify.app/
34+
35+
136
# `1.7.2`
237
Updates
338

README.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ var qFaI6S = function () {
183183
qFaI6S();
184184
```
185185

186+
[Learn mode here.](https://github.com/MichaelXF/js-confuser/blob/master/docs/RenameVariables.md)
187+
186188
### `renameGlobals`
187189

188190
Renames top-level variables, turn this off for web-related scripts. Enabled by default. (`true/false`)
@@ -390,6 +392,8 @@ Use a number to control the percentage of strings.
390392

391393
String Encoding transforms a string into an encoded representation. (`true/false/0-1`)
392394

395+
**⚠️ Warning: Significantly increases file size! It is not recommended for most use cases.**
396+
393397
Use a number to control the percentage of strings.
394398

395399
`"console"` -> `'\x63\x6f\x6e\x73\x6f\x6c\x65'`
@@ -577,9 +581,16 @@ Creates a calculator function to handle arithmetic and logical expressions. (`tr
577581

578582
Adds `debugger` statements throughout the code. Additionally adds a background function for DevTools detection. (`true/false/0-1`)
579583

580-
### `lock.context`
584+
### `lock.tamperProtection`
581585

582-
Properties that must be present on the `window` object (or `global` for NodeJS). (`string[]`)
586+
Tamper Protection safeguards the runtime behavior from being altered by JavaScript pitfalls. (`true/false`)
587+
588+
**⚠️ Tamper Protection requires eval and ran in a non-strict mode environment!**
589+
590+
- **This can break your code.**
591+
- **Due to the security concerns of arbitrary code execution, you must enable this yourself.**
592+
593+
[Learn more here](https://github.com/MichaelXF/js-confuser/blob/master/TamperProtection.md).
583594

584595
### `lock.startDate`
585596

@@ -629,10 +640,14 @@ Integrity ensures the source code is unchanged. (`true/false/0-1`)
629640

630641
A custom callback function to invoke when a lock is triggered. (`string/false`)
631642

632-
[Learn more about the countermeasures function](https://github.com/MichaelXF/js-confuser/blob/master/docs/Countermeasures.md).
643+
[Learn more here.](https://github.com/MichaelXF/js-confuser/blob/master/docs/Countermeasures.md)
633644

634645
Otherwise, the obfuscator falls back to crashing the process.
635646

647+
### `lock.context`
648+
649+
Properties that must be present on the `window` object (or `global` for NodeJS). (`string[]`)
650+
636651
### `movedDeclarations`
637652

638653
Moves variable declarations to the top of the context. (`true/false`)
@@ -785,6 +800,7 @@ You must enable locks yourself, and configure them to your needs.
785800
lock: {
786801
integrity: true,
787802
selfDefending: true,
803+
tamperProtection: true,
788804
domainLock: ["mywebsite.com"],
789805
osLock: ["windows", "linux"],
790806
browserLock: ["firefox"],
@@ -813,7 +829,7 @@ These features are experimental or a security concern.
813829
// set to false for web-related scripts
814830
renameGlobals: false,
815831

816-
// experimental
832+
// custom implementation
817833
identifierGenerator: function(){
818834
return "myvar_" + (counter++);
819835
},

docs/Countermeasures.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## `Countermeasures`
22

3-
[Countermeasures](https://docs.jscrambler.com/code-integrity/documentation/client-side-countermeasures) is a property on the `lock` object, determining the response to a triggered lock.
3+
Countermeasures is a property on the `lock` object, determining the response to a triggered lock.
44

55
For instance, the `domainLock` determines the current domain is invalid.
66

@@ -21,12 +21,13 @@ For instance, the `domainLock` determines the current domain is invalid.
2121

2222
## Crash Process
2323

24-
The default behavior is to crash the process. This depends on the `target` property.
24+
The default behavior is to crash the process This is done by an infinite loop to ensure the process becomes useless.
2525

26-
- `node` -> `process.exit();`
27-
- `browser` -> `document.documentElement.innerHTML = '';`
28-
29-
This is followed by an infinite loop as a fallback measure to ensure the process becomes useless.
26+
```js
27+
while(true) {
28+
// ...
29+
}
30+
```
3031

3132
## Custom Callback
3233

@@ -61,3 +62,9 @@ Try setting your machine time to the past or before the allowed range.
6162
#### Integrity:
6263

6364
Try changing a string within your code.
65+
66+
### See also
67+
68+
- [Integrity](Integrity.md)
69+
- [Tamper Protection](TamperProtection.md)
70+

docs/Integrity.md

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
## `Integrity`
22

3-
JSConfuser can detect changes to the source and prevent execution.
3+
JS-Confuser can detect changes to the source code and terminate execution.
44

5-
If the code is determined modified, the tampered code will not run.
5+
- **⚠️ This can break your code!**
66

7-
## Usage
7+
Option name: `lock.integrity`
8+
9+
Option values: `true/false`
10+
11+
### Usage
812

913
```js
1014
var JsConfuser = require("js-confuser");
1115

12-
JsConfuser.obfuscate("console.log(1)", {
16+
var sourceCode = "console.log(1)"
17+
18+
JsConfuser.obfuscate(sourceCode, {
1319
target: "browser",
1420
lock: {
1521
integrity: true,
@@ -19,35 +25,22 @@ JsConfuser.obfuscate("console.log(1)", {
1925
});
2026
```
2127

22-
## CLI Usage
23-
24-
```shell
25-
<coming soon>
26-
```
27-
28-
## Example
28+
### Example
2929

3030
Consider the following code:
3131

3232
```js
3333
console.log(1)
34-
```
35-
36-
The output:
3734

38-
```
39-
> 1
35+
// 1
4036
```
4137

4238
The obfuscated code (from Usage):
4339

4440
```js
4541
(function(){var jXwFUz=Math.imul||function(jXwFUz,m9pBnlk){m9pBnlk|=0;var n1mfO$O=(jXwFUz&4194303)*m9pBnlk;if(jXwFUz&4290772992)n1mfO$O+=(jXwFUz&4290772992)*m9pBnlk|0;return n1mfO$O|0};function m9pBnlk(n1mfO$O,humOEA){var DGCgjl=3735928559^humOEA;var S$63Fy1=1103547991^humOEA;for(var Lop2FFS=0,GC2VbAQ;Lop2FFS<n1mfO$O.length;Lop2FFS++){GC2VbAQ=n1mfO$O.charCodeAt(Lop2FFS);DGCgjl=jXwFUz(DGCgjl^GC2VbAQ,2654435761);S$63Fy1=jXwFUz(S$63Fy1^GC2VbAQ,1597334677)}DGCgjl=jXwFUz(DGCgjl^DGCgjl>>>16,2246822507)^jXwFUz(S$63Fy1^S$63Fy1>>>13,3266489909);S$63Fy1=jXwFUz(S$63Fy1^S$63Fy1>>>16,2246822507)^jXwFUz(DGCgjl^DGCgjl>>>13,3266489909);return 4294967296*(2097151&S$63Fy1)+(DGCgjl>>>0)}function n1mfO$O(jXwFUz){return jXwFUz.toString().replace(/ |\n|;|,|\{|\}|\(|\)/g,'')}function y3EzuX9(){console['log'](1)}var yzLesc=m9pBnlk(n1mfO$O(y3EzuX9),957);if(yzLesc==0x7a77799eaf937){return y3EzuX9.apply(this,arguments)}}())
46-
```
4742

48-
The output:
49-
```
50-
> 1
43+
// 1
5144
```
5245
5346
Since only Integrity is enabled, it's pretty easy to find the original code: `console['log'](1)`.
@@ -58,18 +51,32 @@ Let's try to change the `console['log'](1)` to `console['log'](2)`:
5851
(function(){var jXwFUz=Math.imul||function(jXwFUz,m9pBnlk){m9pBnlk|=0;var n1mfO$O=(jXwFUz&4194303)*m9pBnlk;if(jXwFUz&4290772992)n1mfO$O+=(jXwFUz&4290772992)*m9pBnlk|0;return n1mfO$O|0};function m9pBnlk(n1mfO$O,humOEA){var DGCgjl=3735928559^humOEA;var S$63Fy1=1103547991^humOEA;for(var Lop2FFS=0,GC2VbAQ;Lop2FFS<n1mfO$O.length;Lop2FFS++){GC2VbAQ=n1mfO$O.charCodeAt(Lop2FFS);DGCgjl=jXwFUz(DGCgjl^GC2VbAQ,2654435761);S$63Fy1=jXwFUz(S$63Fy1^GC2VbAQ,1597334677)}DGCgjl=jXwFUz(DGCgjl^DGCgjl>>>16,2246822507)^jXwFUz(S$63Fy1^S$63Fy1>>>13,3266489909);S$63Fy1=jXwFUz(S$63Fy1^S$63Fy1>>>16,2246822507)^jXwFUz(DGCgjl^DGCgjl>>>13,3266489909);return 4294967296*(2097151&S$63Fy1)+(DGCgjl>>>0)}function n1mfO$O(jXwFUz){return jXwFUz.toString().replace(/ |\n|;|,|\{|\}|\(|\)/g,'')}function y3EzuX9(){console['log'](2)}var yzLesc=m9pBnlk(n1mfO$O(y3EzuX9),957);if(yzLesc==0x7a77799eaf937){return y3EzuX9.apply(this,arguments)}}())
5952
```
6053
61-
The program no longer outputs anything. Integrity detected the change and stopped execution.
54+
The program no longer outputs anything. Integrity has detected the change and stopped execution.
55+
56+
### How is this possible?
57+
58+
JavaScript has a sneaky method to view the source code any function. Calling `Function.toString()` on any function reveals the raw source code.
59+
60+
Integrity uses a hashing algorithm on the obfuscated code during the obfuscation-phase. The obfuscator then places checksum functions throughout the output code to verify it's unchanged at runtime.
61+
62+
An additional RegEx is utilized to remove spaces, newlines, braces, and commas. This ensures the hash isn't too sensitive.
6263
63-
## How is this possible?
64+
### Tamper Detection
6465
65-
JavaScript has a sneaky method to view the source code any function. Calling `.toString()` on any function reveals the raw source code.
66-
Integrity hashes the code during obfuscation phase and embeds an IF-statement within the code. We used an additional regex to remove spaces, newlines, braces,
67-
and commas to ensure the hash isn't too sensitive.
66+
If tampering is detected, the `lock.countermeasures` function will be invoked. If you don't provide a `lock.countermeasures` function, the default behavior is to crash the program.
6867
69-
## Potential Issues
68+
[Learn more about the countermeasures function](Countermeasures.md).
69+
70+
### Potential Issues
7071
7172
If you decide to use Integrity, consider the following:
7273
73-
1. Any build-tools must not modify the locked code. The code can't be changed after JsConfuser runs.
74-
2. `.toString()` functionality may not be enabled in your environment (bytenode)
74+
1. Any build-tools must not modify the locked code. The code can't be changed after JS-Confuser is applied.
75+
2. `Function.toString()` functionality may not be enabled in your environment (bytenode)
76+
77+
### See also
78+
79+
- [Countermeasures](Countermeasures.md)
80+
- [Tamper Protection](TamperProtection.md)
81+
7582

docs/RGF.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,4 +416,9 @@ RGF only applies to:
416416
- Function Declarations or Expressions
417417
- Cannot be async / generator function
418418
- Cannot rely on outside-scoped variables
419-
- Cannot use `this`, `arguments`, or `eval`
419+
- Cannot use `this`, `arguments`, or `eval`
420+
421+
### See also
422+
423+
- [Control Flow Flattening](./ControlFlowFlattening.md)
424+
- [Tamper Protection](./TamperProtection.md)

docs/RenameVariables.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
## `Rename Variables`
2+
3+
Determines if variables should be renamed. (`true/false`)
4+
5+
Option name: `controlFlowFlattening`
6+
7+
Option values: `true/false`
8+
9+
```js
10+
// Input
11+
var twoSum = function (nums, target) {
12+
var hash = {};
13+
var len = nums.length;
14+
for (var i = 0; i < len; i++) {
15+
if (nums[i] in hash) return [hash[nums[i]], i];
16+
hash[target - nums[i]] = i;
17+
}
18+
return [-1, -1];
19+
};
20+
21+
var test = function () {
22+
var inputNums = [2, 7, 11, 15];
23+
var inputTarget = 9;
24+
var expectedResult = [0, 1];
25+
26+
var actualResult = twoSum(inputNums, inputTarget);
27+
ok(actualResult[0] === expectedResult[0]);
28+
ok(actualResult[1] === expectedResult[1]);
29+
};
30+
31+
test();
32+
33+
// Output
34+
var _O2mOcF = function (kB4uXM, w_07HXS) {
35+
var ZLTJcx = {};
36+
var sXQOaUx = kB4uXM["length"];
37+
for (var JYYxEk = 0; JYYxEk < sXQOaUx; JYYxEk++) {
38+
if (kB4uXM[JYYxEk] in ZLTJcx) {
39+
return [ZLTJcx[kB4uXM[JYYxEk]], JYYxEk];
40+
}
41+
ZLTJcx[w_07HXS - kB4uXM[JYYxEk]] = JYYxEk;
42+
}
43+
return [-1, -1];
44+
};
45+
var qFaI6S = function () {
46+
var fZpeOw = [2, 7, 11, 15];
47+
var UJ62R2c = 9;
48+
var dG6R0cV = [0, 1];
49+
var WgYXwn = _O2mOcF(fZpeOw, UJ62R2c);
50+
void (ok(WgYXwn[0] === dG6R0cV[0]), ok(WgYXwn[1] === dG6R0cV[1]));
51+
};
52+
qFaI6S();
53+
```
54+
55+
### Custom Implementation
56+
57+
A custom function can provided as the `renameVariables` option, determining if a variable should be renamed.
58+
59+
| Parameter | Type | Description |
60+
| --- | --- | --- |
61+
| `name` | `string` | The variable proposed to be renamed |
62+
| `isGlobal` | `boolean` | Is the variable defined at the global level? |
63+
64+
```js
65+
{
66+
target: "node",
67+
68+
// Avoid renaming a certain variable
69+
renameVariables: name=>name != "jQuery",
70+
}
71+
```
72+
73+
### Access the renamed variable
74+
75+
The `__JS_CONFUSER_VAR__` function provides a method to access variable mappings. This is especially useful for `eval()` scenarios where you want preserve the mapping.
76+
77+
78+
```js
79+
// Input
80+
var message = "Hello world!";
81+
eval(`console.log(${ __JS_CONFUSER_VAR__(message) })`);
82+
83+
console.log("message was renamed to", __JS_CONFUSER_VAR__(message));
84+
85+
// Output
86+
var nSgZyJf = "Hello world!";
87+
eval(`console.log(${"nSgZyJf"})`) // "Hello world!"
88+
console["log"]("message was renamed to", "nSgZyJf") // message was renamed to nSgZyJf
89+
```
90+
91+
Even if `Rename Variables` is disabled, the `__JS_CONFUSER_VAR__` will still be removed. (The original name will be returned as a string)
92+
93+
### Never rename a variable
94+
95+
The `__NO_JS_CONFUSER_RENAME__` prefix disables renaming a certain variable. This can be useful for debugging the obfuscator.
96+
97+
```js
98+
// Input
99+
var __NO_JS_CONFUSER_RENAME__message1 = "My first message"
100+
var message2 = "My other message"
101+
102+
console.log(__NO_JS_CONFUSER_RENAME__message1)
103+
console.log(message2)
104+
105+
// Output
106+
var __NO_JS_CONFUSER_RENAME__message1 = "My first message";
107+
var jRLf713 = "My other message";
108+
109+
console.log(__NO_JS_CONFUSER_RENAME__message1),
110+
console.log(jRLf713)
111+
```
112+
113+
114+
115+
116+

0 commit comments

Comments
 (0)