Socket
Socket
Sign inDemoInstall

js-confuser

Package Overview
Dependencies
6
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.5.6 to 1.5.7

14

CHANGELOG.md

@@ -0,1 +1,15 @@

# `1.5.7`
Countermeasures function fixes
This update focuses on fixing Countermeasures bugs
The `countermeasures` is custom callback function to invoke when a lock is triggered.
- Fixed [#66](https://github.com/MichaelXF/js-confuser/issues/66)
- - RGF to properly handle the countermeasures function
- Added additional code to prevent an infinite loop from occurring
- Slight improvements to RGF
# `1.5.6`

@@ -2,0 +16,0 @@ Website changed and RGF fixes

8

dist/transforms/lock/integrity.js

@@ -151,3 +151,3 @@ "use strict";

return () => {
object.__hiddenCountermeasures = this.lock.getCounterMeasuresCode();
object.__hiddenCountermeasures = this.lock.getCounterMeasuresCode(object, parents);

@@ -182,4 +182,8 @@ object.$eval = () => {

object.body = (0, _gen.BlockStatement)([functionDeclaration, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(hashName, (0, _gen.CallExpression)((0, _insert.clone)(this.hashFn), [(0, _gen.CallExpression)((0, _insert.clone)(this.stringFn), [(0, _gen.Identifier)(functionName)]), (0, _gen.Literal)(this.seed)]))), ifStatement]);
object.body = (0, _gen.BlockStatement)([functionDeclaration, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(hashName, (0, _gen.CallExpression)((0, _insert.clone)(this.hashFn), [(0, _gen.CallExpression)((0, _insert.clone)(this.stringFn), [(0, _gen.Identifier)(functionName)]), (0, _gen.Literal)(this.seed)]))), ifStatement]); // Make sure the countermeasures activation variable is present
if (this.lock.counterMeasuresActivated) {
object.body.body.unshift((0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.lock.counterMeasuresActivated)));
}
if (object.type == "ArrowFunctionExpression") {

@@ -186,0 +190,0 @@ object.type = "FunctionExpression";

@@ -46,2 +46,6 @@ "use strict";

class Lock extends _transform.default {
/**
* This is a boolean variable injected into the source code determining wether the countermeasures function has been called.
* This is used to prevent infinite loops from happening
*/
constructor(o) {

@@ -59,2 +63,4 @@ super(o, _order.ObfuscateOrder.Lock); // Removed feature

_defineProperty(this, "counterMeasuresActivated", void 0);
_defineProperty(this, "made", void 0);

@@ -75,30 +81,25 @@

if (typeof this.options.lock.countermeasures === "string" && (0, _compare.isValidIdentifier)(this.options.lock.countermeasures)) {
var defined = new Set();
(0, _traverse.default)(tree, (object, parents) => {
if (object.type == "Identifier") {
if (object.type == "Identifier" && object.name === this.options.lock.countermeasures) {
var info = (0, _identifiers.getIdentifierInfo)(object, parents);
if (info.spec.isDefined) {
defined.add(object.name);
if (this.counterMeasuresNode) {
throw new Error("Countermeasures function was already defined, it must have a unique name from the rest of your code");
} else {
var definingContext = (0, _insert.getVarContext)(parents[0], parents.slice(1));
if (object.name === this.options.lock.countermeasures) {
if (this.counterMeasuresNode) {
throw new Error("Countermeasures function was already defined, it must have a unique name from the rest of your code");
} else {
var definingContext = (0, _insert.getVarContext)(parents[0], parents.slice(1));
if (definingContext != tree) {
throw new Error("Countermeasures function must be defined at the global level");
}
if (definingContext != tree) {
throw new Error("Countermeasures function must be defined at the global level");
}
var chain = [object, parents];
var chain = [object, parents];
if (info.isFunctionDeclaration) {
chain = [parents[0], parents.slice(1)];
} else if (info.isVariableDeclaration) {
chain = [parents[1], parents.slice(2)];
}
if (info.isFunctionDeclaration) {
chain = [parents[0], parents.slice(1)];
} else if (info.isVariableDeclaration) {
chain = [parents[1], parents.slice(2)];
}
this.counterMeasuresNode = chain;
}
this.counterMeasuresNode = chain;
}

@@ -117,3 +118,3 @@ }

getCounterMeasuresCode() {
getCounterMeasuresCode(object, parents) {
var opt = this.options.lock.countermeasures;

@@ -127,4 +128,9 @@

if (typeof opt === "string") {
// Since Lock occurs before variable renaming, we are using the pre-obfuscated function name
return [(0, _gen.ExpressionStatement)((0, _gen.CallExpression)((0, _template.default)(opt).single().expression, []))];
if (!this.counterMeasuresActivated) {
this.counterMeasuresActivated = this.getPlaceholder();
(0, _insert.prepend)(parents[parents.length - 1] || object, (0, _gen.VariableDeclaration)((0, _gen.VariableDeclarator)(this.counterMeasuresActivated)));
} // Since Lock occurs before variable renaming, we are using the pre-obfuscated function name
return [(0, _gen.ExpressionStatement)((0, _gen.LogicalExpression)("||", (0, _gen.Identifier)(this.counterMeasuresActivated), (0, _gen.SequenceExpression)([(0, _gen.AssignmentExpression)("=", (0, _gen.Identifier)(this.counterMeasuresActivated), (0, _gen.Literal)(true)), (0, _gen.CallExpression)((0, _template.default)(opt).single().expression, [])])))];
}

@@ -247,3 +253,3 @@

var callExpression = (0, _template.default)("\n (\n function(){\n // Breaks JSNice.org, beautifier.io\n var namedFunction = function(){\n const test = function(){\n const regExp=new RegExp('\\n');\n return regExp['test'](namedFunction)\n };\n return test()\n }\n\n return namedFunction();\n }\n )()\n ").single().expression;
nodes.push((0, _gen.IfStatement)(callExpression, this.getCounterMeasuresCode() || [], null));
nodes.push((0, _gen.IfStatement)(callExpression, this.getCounterMeasuresCode(object, parents) || [], null));
break;

@@ -279,3 +285,3 @@

nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
}

@@ -287,3 +293,3 @@

test = (0, _gen.BinaryExpression)("<", dateNow, (0, _gen.Literal)(this.getTime(this.options.lock.startDate)));
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
break;

@@ -293,7 +299,8 @@

test = (0, _gen.BinaryExpression)(">", dateNow, (0, _gen.Literal)(this.getTime(this.options.lock.endDate)));
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
break;
case "context":
var prop = (0, _random.choice)(this.options.lock.context); // Todo: Alternative to `this`
var prop = (0, _random.choice)(this.options.lock.context);
var code = this.getCounterMeasuresCode(object, parents) || []; // Todo: Alternative to `this`

@@ -307,3 +314,3 @@ if (!this.globalVar) {

test = (0, _gen.UnaryExpression)("!", (0, _gen.MemberExpression)((0, _gen.Identifier)(this.globalVar), (0, _gen.Literal)(prop), true));
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
nodes.push((0, _gen.IfStatement)(test, code, null));
break;

@@ -314,2 +321,3 @@

(0, _assert.ok)(this.options.lock.osLock);
var code = this.getCounterMeasuresCode(object, parents) || [];
this.options.lock.osLock.forEach(osName => {

@@ -352,3 +360,3 @@ var agentMatcher = {

});
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
nodes.push((0, _gen.IfStatement)(test, code, null));
break;

@@ -375,3 +383,3 @@

});
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
break;

@@ -408,3 +416,3 @@

nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode() || [], null));
nodes.push((0, _gen.IfStatement)(test, this.getCounterMeasuresCode(object, parents) || [], null));
}

@@ -411,0 +419,0 @@

@@ -20,4 +20,2 @@ "use strict";

var _antiDestructuring = _interopRequireDefault(require("../es5/antiDestructuring"));
var _compare = require("../../util/compare");

@@ -183,7 +181,2 @@

this.before.push(new ExplicitDeclarations(o));
if (this.options.es5) {
this.before.push(new _antiDestructuring.default(o));
} // this.before.push(new NameConflicts(o));
}

@@ -190,0 +183,0 @@

@@ -78,2 +78,4 @@ "use strict";

if (object !== contextObject && (0, _insert.isFunction)(object) && !object.$requiresEval && !object.async && !object.generator && (0, _insert.getVarContext)(parents[0], parents.slice(1)) === contextObject) {
var _this$options$lock;
// Discard getter/setter methods

@@ -89,2 +91,15 @@ if (parents[0].type === "Property" && parents[0].value === object) {

return;
} // Avoid applying to the countermeasures function
if (typeof ((_this$options$lock = this.options.lock) === null || _this$options$lock === void 0 ? void 0 : _this$options$lock.countermeasures) === "string") {
// function countermeasures(){...}
if (object.type === "FunctionDeclaration" && object.id.type === "Identifier" && object.id.name === this.options.lock.countermeasures) {
return;
} // var countermeasures = function(){...}
if (parents[0].type === "VariableDeclarator" && parents[0].init === object && parents[0].id.type === "Identifier" && parents[0].id.name === this.options.lock.countermeasures) {
return;
}
}

@@ -95,3 +110,14 @@

var isBound = false;
(0, _traverse.walk)(object.body, [object, ...parents], (o, p) => {
/**
* The fnTraverses serves two important purposes
*
* - Identify all the variables referenced and defined here
* - Identify is the 'this' keyword is used anywhere
*
* @param o
* @param p
* @returns
*/
const fnTraverser = (o, p) => {
if (o.type == "Identifier" && !_constants.reservedIdentifiers.has(o.name) && !this.options.globalVariables.has(o.name)) {

@@ -104,3 +130,3 @@ var info = (0, _identifiers.getIdentifierInfo)(o, p);

if (info.spec.isDefined) {
if (info.spec.isDefined && (0, _insert.getDefiningContext)(o, p) === object) {
defined.add(o.name);

@@ -115,4 +141,7 @@ } else {

}
});
};
(0, _traverse.walk)(object.params, [object, ...parents], fnTraverser);
(0, _traverse.walk)(object.body, [object, ...parents], fnTraverser);
if (!isBound) {

@@ -119,0 +148,0 @@ var _object$id;

{
"name": "js-confuser",
"version": "1.5.6",
"version": "1.5.7",
"description": "JavaScript Obfuscation Tool.",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -198,3 +198,6 @@ import Transform from "../transform";

return () => {
object.__hiddenCountermeasures = this.lock.getCounterMeasuresCode();
object.__hiddenCountermeasures = this.lock.getCounterMeasuresCode(
object,
parents
);

@@ -262,2 +265,11 @@ object.$eval = () => {

// Make sure the countermeasures activation variable is present
if (this.lock.counterMeasuresActivated) {
object.body.body.unshift(
VariableDeclaration(
VariableDeclarator(this.lock.counterMeasuresActivated)
)
);
}
if (object.type == "ArrowFunctionExpression") {

@@ -264,0 +276,0 @@ object.type = "FunctionExpression";

@@ -14,9 +14,3 @@ import Transform from "../transform";

NewExpression,
FunctionDeclaration,
ReturnStatement,
VariableDeclaration,
ObjectExpression,
Property,
ArrayExpression,
FunctionExpression,
ThisExpression,

@@ -26,2 +20,3 @@ VariableDeclarator,

LogicalExpression,
SequenceExpression,
} from "../../util/gen";

@@ -52,2 +47,8 @@ import traverse, { getBlock, isBlock } from "../../traverse";

/**
* This is a boolean variable injected into the source code determining wether the countermeasures function has been called.
* This is used to prevent infinite loops from happening
*/
counterMeasuresActivated: string;
made: number;

@@ -79,32 +80,28 @@

) {
var defined = new Set<string>();
traverse(tree, (object, parents) => {
if (object.type == "Identifier") {
if (
object.type == "Identifier" &&
object.name === this.options.lock.countermeasures
) {
var info = getIdentifierInfo(object, parents);
if (info.spec.isDefined) {
defined.add(object.name);
if (object.name === this.options.lock.countermeasures) {
if (this.counterMeasuresNode) {
if (this.counterMeasuresNode) {
throw new Error(
"Countermeasures function was already defined, it must have a unique name from the rest of your code"
);
} else {
var definingContext = getVarContext(parents[0], parents.slice(1));
if (definingContext != tree) {
throw new Error(
"Countermeasures function was already defined, it must have a unique name from the rest of your code"
"Countermeasures function must be defined at the global level"
);
} else {
var definingContext = getVarContext(
parents[0],
parents.slice(1)
);
if (definingContext != tree) {
throw new Error(
"Countermeasures function must be defined at the global level"
);
}
var chain: Location = [object, parents];
if (info.isFunctionDeclaration) {
chain = [parents[0], parents.slice(1)];
} else if (info.isVariableDeclaration) {
chain = [parents[1], parents.slice(2)];
}
}
var chain: Location = [object, parents];
if (info.isFunctionDeclaration) {
chain = [parents[0], parents.slice(1)];
} else if (info.isVariableDeclaration) {
chain = [parents[1], parents.slice(2)];
}
this.counterMeasuresNode = chain;
}
this.counterMeasuresNode = chain;
}

@@ -127,3 +124,3 @@ }

getCounterMeasuresCode(): Node[] {
getCounterMeasuresCode(object: Node, parents: Node[]): Node[] {
var opt = this.options.lock.countermeasures;

@@ -137,6 +134,26 @@

if (typeof opt === "string") {
if (!this.counterMeasuresActivated) {
this.counterMeasuresActivated = this.getPlaceholder();
prepend(
parents[parents.length - 1] || object,
VariableDeclaration(VariableDeclarator(this.counterMeasuresActivated))
);
}
// Since Lock occurs before variable renaming, we are using the pre-obfuscated function name
return [
ExpressionStatement(
CallExpression(Template(opt).single().expression, [])
LogicalExpression(
"||",
Identifier(this.counterMeasuresActivated),
SequenceExpression([
AssignmentExpression(
"=",
Identifier(this.counterMeasuresActivated),
Literal(true)
),
CallExpression(Template(opt).single().expression, []),
])
)
),

@@ -297,3 +314,3 @@ ];

callExpression,
this.getCounterMeasuresCode() || [],
this.getCounterMeasuresCode(object, parents) || [],
null

@@ -334,3 +351,7 @@ )

nodes.push(
IfStatement(test, this.getCounterMeasuresCode() || [], null)
IfStatement(
test,
this.getCounterMeasuresCode(object, parents) || [],
null
)
);

@@ -349,3 +370,7 @@ }

nodes.push(
IfStatement(test, this.getCounterMeasuresCode() || [], null)
IfStatement(
test,
this.getCounterMeasuresCode(object, parents) || [],
null
)
);

@@ -363,3 +388,7 @@

nodes.push(
IfStatement(test, this.getCounterMeasuresCode() || [], null)
IfStatement(
test,
this.getCounterMeasuresCode(object, parents) || [],
null
)
);

@@ -372,2 +401,4 @@

var code = this.getCounterMeasuresCode(object, parents) || [];
// Todo: Alternative to `this`

@@ -398,5 +429,3 @@ if (!this.globalVar) {

);
nodes.push(
IfStatement(test, this.getCounterMeasuresCode() || [], null)
);
nodes.push(IfStatement(test, code, null));

@@ -412,2 +441,4 @@ break;

var code = this.getCounterMeasuresCode(object, parents) || [];
this.options.lock.osLock.forEach((osName) => {

@@ -465,5 +496,3 @@ var agentMatcher = {

test = UnaryExpression("!", { ...test });
nodes.push(
IfStatement(test, this.getCounterMeasuresCode() || [], null)
);
nodes.push(IfStatement(test, code, null));
break;

@@ -505,3 +534,7 @@

nodes.push(
IfStatement(test, this.getCounterMeasuresCode() || [], null)
IfStatement(
test,
this.getCounterMeasuresCode(object, parents) || [],
null
)
);

@@ -558,3 +591,7 @@ break;

nodes.push(
IfStatement(test, this.getCounterMeasuresCode() || [], null)
IfStatement(
test,
this.getCounterMeasuresCode(object, parents) || [],
null
)
);

@@ -561,0 +598,0 @@ }

@@ -6,20 +6,7 @@ /**

import {
BlockStatement,
Identifier,
LabeledStatement,
Literal,
Location,
Node,
ReturnStatement,
} from "../../util/gen";
import { BlockStatement, Literal, ReturnStatement } from "../../util/gen";
import { ObfuscateOrder } from "../../order";
import { getIndexDirect, clone, getFunction } from "../../util/insert";
import { ok } from "assert";
import { clone, getFunction } from "../../util/insert";
import { getIdentifierInfo } from "../../util/identifiers";
import { walk } from "../../traverse";
import Label from "../label";
import NameConflicts from "./nameConflicts";
import AntiDestructuring from "../es5/antiDestructuring";
import { OPERATOR_PRECEDENCE } from "../../precedence";
import { isLoop } from "../../util/compare";

@@ -185,8 +172,2 @@

this.before.push(new ExplicitDeclarations(o));
if (this.options.es5) {
this.before.push(new AntiDestructuring(o));
}
// this.before.push(new NameConflicts(o));
}

@@ -193,0 +174,0 @@

@@ -33,2 +33,3 @@ import { compileJsSync } from "../compiler";

prepend,
getDefiningContext,
} from "../util/insert";

@@ -110,2 +111,24 @@ import { getRandomString } from "../util/random";

// Avoid applying to the countermeasures function
if (typeof this.options.lock?.countermeasures === "string") {
// function countermeasures(){...}
if (
object.type === "FunctionDeclaration" &&
object.id.type === "Identifier" &&
object.id.name === this.options.lock.countermeasures
) {
return;
}
// var countermeasures = function(){...}
if (
parents[0].type === "VariableDeclarator" &&
parents[0].init === object &&
parents[0].id.type === "Identifier" &&
parents[0].id.name === this.options.lock.countermeasures
) {
return;
}
}
var defined = new Set<string>(),

@@ -116,3 +139,13 @@ referenced = new Set<string>();

walk(object.body, [object, ...parents], (o, p) => {
/**
* The fnTraverses serves two important purposes
*
* - Identify all the variables referenced and defined here
* - Identify is the 'this' keyword is used anywhere
*
* @param o
* @param p
* @returns
*/
const fnTraverser = (o, p) => {
if (

@@ -127,3 +160,3 @@ o.type == "Identifier" &&

}
if (info.spec.isDefined) {
if (info.spec.isDefined && getDefiningContext(o, p) === object) {
defined.add(o.name);

@@ -138,4 +171,7 @@ } else {

}
});
};
walk(object.params, [object, ...parents], fnTraverser);
walk(object.body, [object, ...parents], fnTraverser);
if (!isBound) {

@@ -142,0 +178,0 @@ defined.forEach((identifier) => {

@@ -83,1 +83,19 @@ import JsConfuser from "../../../src/index";

});
// https://github.com/MichaelXF/js-confuser/issues/66
test("Variant #5: Should work with RGF enabled", async () => {
await JsConfuser.obfuscate(
`
function myCountermeasuresFunction(){
}
`,
{
target: "node",
lock: {
countermeasures: "myCountermeasuresFunction",
},
rgf: true,
}
);
});

@@ -254,2 +254,39 @@ import { writeFileSync } from "fs";

});
it("should not apply to functions that reference their parent scope in the parameters", async () => {
var output = await JsConfuser.obfuscate(
`
var outsideVar = 0;
function myFunction(insideVar = outsideVar){
}
`,
{
target: "node",
rgf: true,
}
);
expect(output).not.toContain("new Function");
});
it("should not apply to functions that reference their parent scope in previously defined names", async () => {
var output = await JsConfuser.obfuscate(
`
var outsideVar = 0;
function myFunction(){
(function (){
var outsideVar;
})();
console.log(outsideVar);
}
`,
{
target: "node",
rgf: true,
}
);
expect(output).not.toContain("new Function");
});
});

@@ -256,0 +293,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc