Merge pull request #522 from javascript-obfuscator/transform-object-keys-return-fix

Fixed wrong object keys transformation of objects inside sequence expressions
This commit is contained in:
Timofey Kachalov
2020-01-26 14:50:03 +03:00
committed by GitHub
13 changed files with 234 additions and 11 deletions
+3 -3
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "0.24.0-rc.1",
"version": "0.24.0-rc.2",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
+1
View File
@@ -36,6 +36,7 @@ export enum NodeType {
Property = 'Property',
RestElement = 'RestElement',
ReturnStatement = 'ReturnStatement',
SequenceExpression = 'SequenceExpression',
Super = 'Super',
SwitchCase = 'SwitchCase',
SwitchStatement = 'SwitchStatement',
@@ -58,7 +58,9 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
hostStatement: ESTree.Statement
): boolean {
return ObjectExpressionKeysTransformer.isProhibitedVariableDeclarationHostStatement(objectExpressionNode, hostStatement)
|| ObjectExpressionKeysTransformer.isProhibitedFunctionHostStatement(objectExpressionNode, hostStatement);
|| ObjectExpressionKeysTransformer.isProhibitedFunctionHostStatement(objectExpressionNode, hostStatement)
|| ObjectExpressionKeysTransformer.isProhibitedExpressionHostStatement(objectExpressionNode, hostStatement)
|| ObjectExpressionKeysTransformer.isProhibitedReturnHostStatement(objectExpressionNode, hostStatement);
}
/**
@@ -109,6 +111,63 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
);
}
/**
* @param {ObjectExpression} objectExpressionNode
* @param {Statement} hostStatement
* @returns {boolean}
*/
private static isProhibitedReturnHostStatement (
objectExpressionNode: ESTree.ObjectExpression,
hostStatement: ESTree.Statement
): boolean {
if (!NodeGuards.isReturnStatementNode(hostStatement) || !hostStatement.argument) {
return false;
}
return ObjectExpressionKeysTransformer.isProhibitedSequenceExpressionNode(
objectExpressionNode,
hostStatement.argument
);
}
/**
* @param {ObjectExpression} objectExpressionNode
* @param {Statement} hostStatement
* @returns {boolean}
*/
private static isProhibitedExpressionHostStatement (
objectExpressionNode: ESTree.ObjectExpression,
hostStatement: ESTree.Statement
): boolean {
if (!NodeGuards.isExpressionStatementNode(hostStatement)) {
return false;
}
return ObjectExpressionKeysTransformer.isProhibitedSequenceExpressionNode(
objectExpressionNode,
hostStatement.expression
);
}
/**
* @param {ObjectExpression} objectExpressionNode
* @param {Statement} node
* @returns {boolean}
*/
private static isProhibitedSequenceExpressionNode (
objectExpressionNode: ESTree.ObjectExpression,
node: ESTree.Node
): boolean {
if (!NodeGuards.isSequenceExpressionNode(node) || !node.expressions.length) {
return false;
}
return ObjectExpressionKeysTransformer.isReferencedIdentifierName(
objectExpressionNode,
node.expressions
);
}
/**
* @param {ObjectExpression} objectExpressionNode
* @param {Node[]} nodesToSearch
+8
View File
@@ -358,6 +358,14 @@ export class NodeGuards {
return node.type === NodeType.ReturnStatement;
}
/**
* @param {Node} node
* @returns {boolean}
*/
public static isSequenceExpressionNode (node: ESTree.Node): node is ESTree.SequenceExpression {
return node.type === NodeType.SequenceExpression;
}
/**
* @param {Node} node
* @returns {boolean}
+9 -4
View File
@@ -7,14 +7,19 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
var foo = {['foo']: 1};
function foo () {
var foo;
var bar;
(foo = {foo: 1}), (bar = {bar: foo.foo});
return bar.bar;
}
console.log(foo());
`,
{
...NO_ADDITIONAL_NODES_PRESET,
compact: false,
unicodeEscapeSequence: true,
stringArray: true,
stringArrayThreshold: 1
transformObjectKeys: true
}
).getObfuscatedCode();
@@ -634,6 +634,71 @@ describe('ObjectExpressionKeysTransformer', () => {
});
});
});
describe('Variant #17: sequence expression object expressions', () => {
const match: string = `` +
`var ${variableMatch};` +
`var ${variableMatch};` +
`var ${variableMatch} *= *{};` +
`${variableMatch}\\['foo'] *= *0x1;` +
`var ${variableMatch} *= *{};` +
`${variableMatch}\\['bar'] *= *0x2;` +
`${variableMatch} *= *${variableMatch}, *` +
`${variableMatch} *= *${variableMatch};` +
``;
const regExp: RegExp = new RegExp(match);
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/sequence-expression-object-expressions.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
transformObjectKeys: true
}
).getObfuscatedCode();
});
it('shouldn transform sequence expression object expressions keys', () => {
assert.match(obfuscatedCode, regExp);
});
});
describe('Variant #18: return statement sequence expression object expressions', () => {
const match: string = `` +
`var ${variableMatch};` +
`var ${variableMatch};` +
`var ${variableMatch} *= *{};` +
`${variableMatch}\\['foo'] *= *0x1;` +
`var ${variableMatch} *= *{};` +
`${variableMatch}\\['bar'] *= *0x2;` +
`return ${variableMatch} *= *${variableMatch}, *` +
`${variableMatch} *= *${variableMatch}, *` +
`${variableMatch}\\['bar'];` +
``;
const regExp: RegExp = new RegExp(match);
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/return-statement-sequence-expression-object-expressions.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
transformObjectKeys: true
}
).getObfuscatedCode();
});
it('shouldn transform sequence expression object expressions keys', () => {
assert.match(obfuscatedCode, regExp);
});
});
});
describe('member expression as host of object expression', () => {
@@ -1426,5 +1491,66 @@ describe('ObjectExpressionKeysTransformer', () => {
assert.match(obfuscatedCode, regExp);
});
});
describe('Variant #5: sequence expression identifier reference', () => {
const match: string = `` +
`var ${variableMatch};` +
`var ${variableMatch};` +
`var ${variableMatch} *= *{};` +
`${variableMatch}\\['foo'] *= *0x1;` +
`${variableMatch} *= *${variableMatch}, *` +
`${variableMatch} *= *{'bar' *: *${variableMatch}\\['foo']};` +
``;
const regExp: RegExp = new RegExp(match);
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/sequence-expression-identifier-reference.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
transformObjectKeys: true
}
).getObfuscatedCode();
});
it('shouldn ignore sequence expression object expression if it references other sequence expression identifier', () => {
assert.match(obfuscatedCode, regExp);
});
});
describe('Variant #6: return statement sequence expression identifier reference', () => {
const match: string = `` +
`var ${variableMatch};` +
`var ${variableMatch};` +
`var ${variableMatch} *= *{};` +
`${variableMatch}\\['foo'] *= *0x1;` +
`return ${variableMatch} *= *${variableMatch}, *` +
`${variableMatch} *= *{'bar' *: *${variableMatch}\\['foo']}, *` +
`${variableMatch}\\['bar'];` +
``;
const regExp: RegExp = new RegExp(match);
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/return-statement-sequence-expression-identifier-reference.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
transformObjectKeys: true
}
).getObfuscatedCode();
});
it('shouldn ignore sequence expression object expression if it references other sequence expression identifier', () => {
assert.match(obfuscatedCode, regExp);
});
});
});
});
@@ -0,0 +1,7 @@
function foo () {
var foo;
var bar;
return (foo = {foo: 1}),
(bar = {bar: foo.foo}),
bar.bar;
}
@@ -0,0 +1,7 @@
function foo () {
var foo;
var bar;
return (foo = {foo: 1}),
(bar = {bar: 2}),
bar.bar;
}
@@ -0,0 +1,5 @@
function foo () {
var foo;
var bar;
(foo = {foo: 1}), (bar = {bar: foo.foo});
}
@@ -0,0 +1,5 @@
function foo () {
var foo;
var bar;
(foo = {foo: 1}), (bar = {bar: 2});
}