mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
More complex object keys transformation + some string literal transformations refactoring
This commit is contained in:
+5
-3
@@ -7,12 +7,14 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
|
||||
|
||||
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
|
||||
`
|
||||
var foo = {foo: 1};
|
||||
var foo = {['foo']: 1};
|
||||
`,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
transformObjectKeys: true,
|
||||
compact: false
|
||||
compact: false,
|
||||
unicodeEscapeSequence: true,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
|
||||
|
||||
+22
-14
@@ -152,11 +152,14 @@ describe('ObjectExpressionKeysTransformer', () => {
|
||||
|
||||
describe('Variant #6: nested objects #1', () => {
|
||||
const match: string = `` +
|
||||
`var *${variableMatch} *= *{};` +
|
||||
`${variableMatch}\\['baz'] *= *'bark';` +
|
||||
`var *${variableMatch} *= *{};` +
|
||||
`${variableMatch}\\['inner1'] *= *${variableMatch};` +
|
||||
`var *${variableMatch} *= *{};` +
|
||||
`${variableMatch}\\['foo'] *= *'bar';` +
|
||||
`${variableMatch}\\['inner'] *= *{};` +
|
||||
`${variableMatch}\\['inner']\\['inner1'] *= *{};` +
|
||||
`${variableMatch}\\['inner']\\['inner1']\\['baz'] *= *'bark';` +
|
||||
`${variableMatch}\\['inner'] *= *${variableMatch};` +
|
||||
`var object *= *${variableMatch};` +
|
||||
``;
|
||||
const regExp: RegExp = new RegExp(match);
|
||||
|
||||
@@ -181,14 +184,17 @@ describe('ObjectExpressionKeysTransformer', () => {
|
||||
|
||||
describe('Variant #7: nested objects #2', () => {
|
||||
const match: string = `` +
|
||||
`var *${variableMatch} *= *{};` +
|
||||
`${variableMatch}\\['hawk'] *= *'geek';` +
|
||||
`var *${variableMatch} *= *{};` +
|
||||
`${variableMatch}\\['baz'] *= *'bark';` +
|
||||
`${variableMatch}\\['inner1'] *= *${variableMatch};` +
|
||||
`${variableMatch}\\['cow'] *= *'bear';` +
|
||||
`var *${variableMatch} *= *{};` +
|
||||
`${variableMatch}\\['foo'] *= *'bar';` +
|
||||
`${variableMatch}\\['inner'] *= *{};` +
|
||||
`${variableMatch}\\['inner'] *= *${variableMatch};` +
|
||||
`${variableMatch}\\['ball'] *= *'door';` +
|
||||
`${variableMatch}\\['inner']\\['baz'] *= *'bark';` +
|
||||
`${variableMatch}\\['inner']\\['inner1'] *= *{};` +
|
||||
`${variableMatch}\\['inner']\\['cow'] *= *'bear';` +
|
||||
`${variableMatch}\\['inner']\\['inner1']\\['hawk'] *= *'geek';` +
|
||||
`var *object *= *${variableMatch};` +
|
||||
``;
|
||||
const regExp: RegExp = new RegExp(match);
|
||||
|
||||
@@ -213,14 +219,16 @@ describe('ObjectExpressionKeysTransformer', () => {
|
||||
|
||||
describe('Variant #8: nested objects #3', () => {
|
||||
const match: string = `` +
|
||||
`var *${variableMatch} *= *{};` +
|
||||
`${variableMatch}\\['hawk'] *= *'geek';` +
|
||||
`var *${variableMatch} *= *{};` +
|
||||
`${variableMatch}\\['baz'] *= *'bark';` +
|
||||
`${variableMatch}\\['inner1'] *= *${variableMatch};` +
|
||||
`${variableMatch}\\['cow'] *= *'bear';` +
|
||||
`var *${variableMatch} *= *{};` +
|
||||
`${variableMatch}\\['foo'] *= *'bar';` +
|
||||
`${variableMatch}\\['inner'] *= *{};` +
|
||||
`${variableMatch}\\['inner'] *= *${variableMatch};` +
|
||||
`${variableMatch}\\['ball'] *= *'door';` +
|
||||
`${variableMatch}\\['inner']\\['baz'] *= *'bark';` +
|
||||
`${variableMatch}\\['inner']\\['inner1'] *= *{};` +
|
||||
`${variableMatch}\\['inner']\\['cow'] *= *'bear';` +
|
||||
`${variableMatch}\\['inner']\\['inner1']\\['hawk'] *= *'geek';` +
|
||||
`return ${variableMatch};` +
|
||||
``;
|
||||
const regExp: RegExp = new RegExp(match);
|
||||
@@ -1394,7 +1402,7 @@ describe('ObjectExpressionKeysTransformer', () => {
|
||||
`var ${variableMatch} *= *{};` +
|
||||
`${variableMatch}\\['foo'] *= *'test';` +
|
||||
`var foo *= *${variableMatch};` +
|
||||
`var ${variableMatch} *= *{\\[foo.foo] *: *'1'};` +
|
||||
`var ${variableMatch} *= *{\\[foo\\['foo']] *: *'1'};` +
|
||||
`${variableMatch}\\['bar'] *= *'2';` +
|
||||
`var bar *= *${variableMatch};` +
|
||||
``;
|
||||
|
||||
+7
-9
@@ -1,10 +1,8 @@
|
||||
(function(){
|
||||
var object = {
|
||||
foo: 'bar',
|
||||
inner: {
|
||||
inner1: {
|
||||
baz: 'bark'
|
||||
}
|
||||
var object = {
|
||||
foo: 'bar',
|
||||
inner: {
|
||||
inner1: {
|
||||
baz: 'bark'
|
||||
}
|
||||
};
|
||||
})();
|
||||
}
|
||||
};
|
||||
+11
-13
@@ -1,14 +1,12 @@
|
||||
(function(){
|
||||
var object = {
|
||||
foo: 'bar',
|
||||
inner: {
|
||||
baz: 'bark',
|
||||
inner1: {
|
||||
hawk: 'geek'
|
||||
},
|
||||
cow: 'bear',
|
||||
|
||||
var object = {
|
||||
foo: 'bar',
|
||||
inner: {
|
||||
baz: 'bark',
|
||||
inner1: {
|
||||
hawk: 'geek'
|
||||
},
|
||||
ball: 'door',
|
||||
};
|
||||
})();
|
||||
cow: 'bear',
|
||||
|
||||
},
|
||||
ball: 'door',
|
||||
};
|
||||
+60
-2
@@ -135,7 +135,7 @@ describe('LiteralTransformer', () => {
|
||||
|
||||
describe('Variant #6: `unicodeEscapeSequence` and `stringArray` options are enabled', () => {
|
||||
const stringArrayRegExp: RegExp = /^var *_0x([a-f0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/;
|
||||
const stringArrayCallRegExp: RegExp = /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/;
|
||||
const stringArrayCallRegExp: RegExp = /var *test *= *_0x([a-f0-9]){4}\('\\x30\\x78\\x30'\);/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
@@ -157,7 +157,7 @@ describe('LiteralTransformer', () => {
|
||||
assert.match(obfuscatedCode, stringArrayRegExp);
|
||||
});
|
||||
|
||||
it('match #1: should replace literal node value with unicode escape sequence from string array', () => {
|
||||
it('match #2: should replace literal node value with unicode escape sequence from string array', () => {
|
||||
assert.match(obfuscatedCode, stringArrayCallRegExp);
|
||||
});
|
||||
});
|
||||
@@ -518,6 +518,64 @@ describe('LiteralTransformer', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #13: object expression key literal', () => {
|
||||
describe('Variant #1: base key literal', () => {
|
||||
const stringArrayRegExp: RegExp = /^var _0x([a-f0-9]){4} *= *\['bar'];/;
|
||||
const objectExpressionRegExp: RegExp = /var test *= *{'foo' *: *_0x([a-f0-9]){4}\('0x0'\)};/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/object-expression-key-literal.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: should not add object expression key literal to the string array', () => {
|
||||
assert.match(obfuscatedCode, stringArrayRegExp);
|
||||
});
|
||||
|
||||
it('match #2: should keep object expression key literal', () => {
|
||||
assert.match(obfuscatedCode, objectExpressionRegExp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: computed key literal', () => {
|
||||
const stringArrayRegExp: RegExp = /^var _0x([a-f0-9]){4} *= *\['foo', *'bar'];/;
|
||||
const objectExpressionRegExp: RegExp = /var test *= *{\[_0x([a-f0-9]){4}\('0x0'\)] *: *_0x([a-f0-9]){4}\('0x1'\)};/;
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/object-expression-computed-key-literal.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
stringArray: true,
|
||||
stringArrayThreshold: 1
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('match #1: should add object expression computed key literal to the string array', () => {
|
||||
assert.match(obfuscatedCode, stringArrayRegExp);
|
||||
});
|
||||
|
||||
it('match #2: should replace object expression computed key literal on call to the string array', () => {
|
||||
assert.match(obfuscatedCode, objectExpressionRegExp);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('transformation of literal node with boolean value', () => {
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
var test = {['foo']: 'bar'};
|
||||
+1
@@ -0,0 +1 @@
|
||||
var test = {'foo': 'bar'};
|
||||
+49
@@ -157,6 +157,55 @@ describe('StringArrayStorageAnalyzer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Analyzes of the AST tree with prohibited string literal nodes', () => {
|
||||
const literalNode1: ESTree.Literal = NodeFactory.literalNode('foo');
|
||||
const literalNode2: ESTree.Literal = NodeFactory.literalNode('bar');
|
||||
|
||||
const expectedStringArrayStorageItemData1: IStringArrayStorageItemData = {
|
||||
encodedValue: 'foo',
|
||||
decodeKey: null,
|
||||
index: 0,
|
||||
value: 'foo'
|
||||
};
|
||||
const expectedStringArrayStorageItemData2: undefined = undefined;
|
||||
|
||||
let stringArrayStorageItemData1: IStringArrayStorageItemData | undefined;
|
||||
let stringArrayStorageItemData2: IStringArrayStorageItemData | undefined;
|
||||
|
||||
before(() => {
|
||||
stringArrayStorageAnalyzer = getStringArrayStorageAnalyzer({
|
||||
stringArrayThreshold: 1
|
||||
});
|
||||
|
||||
const astTree: ESTree.Program = NodeFactory.programNode([
|
||||
NodeFactory.expressionStatementNode(literalNode1),
|
||||
NodeFactory.variableDeclarationNode([
|
||||
NodeFactory.variableDeclaratorNode(
|
||||
NodeFactory.identifierNode('bar'),
|
||||
NodeFactory.objectExpressionNode([
|
||||
NodeFactory.propertyNode(
|
||||
literalNode2,
|
||||
NodeFactory.literalNode(1)
|
||||
)
|
||||
])
|
||||
)
|
||||
])
|
||||
]);
|
||||
|
||||
stringArrayStorageAnalyzer.analyze(astTree);
|
||||
stringArrayStorageItemData1 = stringArrayStorageAnalyzer.getItemDataForLiteralNode(literalNode1);
|
||||
stringArrayStorageItemData2 = stringArrayStorageAnalyzer.getItemDataForLiteralNode(literalNode2);
|
||||
});
|
||||
|
||||
it('Variant #1: should return correct string array storage item data for literal node #1', () => {
|
||||
assert.deepEqual(stringArrayStorageItemData1, expectedStringArrayStorageItemData1);
|
||||
});
|
||||
|
||||
it('Variant #2: should return correct string array storage item data for literal node #1', () => {
|
||||
assert.deepEqual(stringArrayStorageItemData2, expectedStringArrayStorageItemData2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Analyzes of the AST tree with ignored nodes', () => {
|
||||
const literalNode1: ESTree.Literal = NodeFactory.literalNode('foo');
|
||||
const literalNode2: ESTree.Literal = NodeFactory.literalNode('bar');
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { assert } from 'chai';
|
||||
|
||||
import { NodeFactory } from '../../../../src/node/NodeFactory';
|
||||
import { NodeLiteralUtils } from '../../../../src/node/NodeLiteralUtils';
|
||||
|
||||
describe('NodeLiteralUtils', () => {
|
||||
describe('isProhibitedLiteralNode', () => {
|
||||
describe('String literal node', () => {
|
||||
describe('Variant #1: base string literal node', () => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
|
||||
|
||||
let statementNode: ESTree.Statement;
|
||||
|
||||
before(() => {
|
||||
statementNode = NodeFactory.expressionStatementNode(
|
||||
literalNode
|
||||
);
|
||||
|
||||
literalNode.parentNode = statementNode;
|
||||
});
|
||||
|
||||
it('should return false for base string literal node', () => {
|
||||
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, statementNode), false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: property literal node', () => {
|
||||
describe('Variant #1: property key literal node', () => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
|
||||
|
||||
let propertyNode: ESTree.Property;
|
||||
|
||||
before(() => {
|
||||
propertyNode = NodeFactory.propertyNode(
|
||||
literalNode,
|
||||
NodeFactory.literalNode(1)
|
||||
);
|
||||
|
||||
literalNode.parentNode = propertyNode;
|
||||
});
|
||||
|
||||
it('should return false for property key literal node', () => {
|
||||
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, propertyNode), true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: computed property key literal node', () => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
|
||||
|
||||
let propertyNode: ESTree.Property;
|
||||
|
||||
before(() => {
|
||||
propertyNode = NodeFactory.propertyNode(
|
||||
literalNode,
|
||||
NodeFactory.literalNode(1),
|
||||
true
|
||||
);
|
||||
|
||||
literalNode.parentNode = propertyNode;
|
||||
});
|
||||
|
||||
it('should return false for computed property key literal node', () => {
|
||||
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, propertyNode), false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: property value literal node', () => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
|
||||
|
||||
let propertyNode: ESTree.Property;
|
||||
|
||||
before(() => {
|
||||
propertyNode = NodeFactory.propertyNode(
|
||||
NodeFactory.literalNode(1),
|
||||
literalNode
|
||||
);
|
||||
|
||||
literalNode.parentNode = propertyNode;
|
||||
});
|
||||
|
||||
it('should return false for property value literal node', () => {
|
||||
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, propertyNode), false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: import declaration node', () => {
|
||||
describe('Variant #1: base import declaration literal node', () => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
|
||||
|
||||
let importDeclarationNode: ESTree.ImportDeclaration;
|
||||
|
||||
before(() => {
|
||||
importDeclarationNode = NodeFactory.importDeclarationNode(
|
||||
[],
|
||||
literalNode
|
||||
);
|
||||
|
||||
literalNode.parentNode = importDeclarationNode;
|
||||
});
|
||||
|
||||
it('should return false for import declaration literal node', () => {
|
||||
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, importDeclarationNode), true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Number literal node', () => {
|
||||
describe('Variant #1: base number literal node', () => {
|
||||
const literalNode: ESTree.Literal = NodeFactory.literalNode(1);
|
||||
|
||||
let statementNode: ESTree.Statement;
|
||||
|
||||
before(() => {
|
||||
statementNode = NodeFactory.expressionStatementNode(
|
||||
literalNode
|
||||
);
|
||||
|
||||
const blockStatementNode: ESTree.BlockStatement = NodeFactory.blockStatementNode([
|
||||
statementNode
|
||||
]);
|
||||
|
||||
statementNode.parentNode = blockStatementNode;
|
||||
literalNode.parentNode = statementNode;
|
||||
});
|
||||
|
||||
it('should return false for base number literal node', () => {
|
||||
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, statementNode), false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user