sanex3339
2017-11-16 01:21:36 +03:00
parent e1964b2ee2
commit 224483d837
4 changed files with 69 additions and 21 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
@@ -8,8 +8,10 @@ import { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatemen
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { ITransformersRunner } from '../../interfaces/node-transformers/ITransformersRunner';
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
import { NodeTransformer } from '../../enums/node-transformers/NodeTransformer';
import { NodeType } from '../../enums/node/NodeType';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
@@ -29,6 +31,18 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
*/
private static readonly minCollectedBlockStatementsCount: number = 5;
/**
* @type {NodeTransformer[]}
*/
private static readonly transformersToRenameBlockScopeIdentifiers: NodeTransformer[] = [
NodeTransformer.CatchClauseTransformer,
NodeTransformer.ClassDeclarationTransformer,
NodeTransformer.FunctionDeclarationTransformer,
NodeTransformer.FunctionTransformer,
NodeTransformer.LabeledStatementTransformer,
NodeTransformer.VariableDeclarationTransformer
];
/**
* @type {ESTree.BlockStatement[]}
*/
@@ -40,14 +54,23 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
private collectedBlockStatementsLength: number;
/**
* @type {ITransformersRunner}
*/
private readonly transformersRunner: ITransformersRunner;
/**
* @param {ITransformersRunner} transformersRunner
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
*/
constructor (
@inject(ServiceIdentifiers.ITransformersRunner) transformersRunner: ITransformersRunner,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(randomGenerator, options);
this.transformersRunner = transformersRunner;
}
/**
@@ -131,15 +154,14 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
blockStatementNode: ESTree.BlockStatement,
collectedBlockStatements: ESTree.BlockStatement[]
): void {
const clonedBlockStatementNode: ESTree.BlockStatement = NodeUtils.clone(blockStatementNode);
let nestedBlockStatementsCount: number = 0,
let clonedBlockStatementNode: ESTree.BlockStatement = NodeUtils.clone(blockStatementNode),
nestedBlockStatementsCount: number = 0,
isValidBlockStatementNode: boolean = true;
estraverse.replace(clonedBlockStatementNode, {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): any => {
/**
* First step: count nested block statements in current block statement
* Count nested block statements in current block statement
*/
if (NodeGuards.isBlockStatementNode(node)) {
nestedBlockStatementsCount++;
@@ -159,18 +181,6 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
return estraverse.VisitorOption.Break;
}
/**
* Second step: rename all identifiers (except identifiers in member expressions)
* in current block statement
*/
if (
NodeGuards.isIdentifierNode(node) &&
parentNode &&
!NodeGuards.isMemberExpressionNode(parentNode)
) {
node.name = this.randomGenerator.getRandomVariableName(6);
}
return node;
}
});
@@ -179,6 +189,14 @@ export class DeadCodeInjectionTransformer extends AbstractNodeTransformer {
return;
}
/**
* We should transform identifiers in the dead code block statement to avoid conflicts with original code
*/
clonedBlockStatementNode = this.transformersRunner.transform(
clonedBlockStatementNode,
DeadCodeInjectionTransformer.transformersToRenameBlockScopeIdentifiers
);
collectedBlockStatements.push(clonedBlockStatementNode);
}
@@ -190,26 +190,26 @@ describe('DeadCodeInjectionTransformer', () => {
`if *\\(${variableMatch}\\('${hexMatch}'\\) *=== *${variableMatch}\\('${hexMatch}'\\)\\) *\\{` +
`console.*` +
`\\} *else *\\{` +
`${variableMatch}.*` +
`alert.*` +
`\\}` +
``;
const match2: string = `` +
`if *\\(${variableMatch}\\('${hexMatch}'\\) *!== *${variableMatch}\\('${hexMatch}'\\)\\) *\\{` +
`console.*` +
`\\} *else *\\{` +
`${variableMatch}.*` +
`alert.*` +
`\\}` +
``;
const match3: string = `` +
`if *\\(${variableMatch}\\('${hexMatch}'\\) *=== *${variableMatch}\\('${hexMatch}'\\)\\) *\\{` +
`${variableMatch}.*` +
`alert.*` +
`\\} *else *\\{` +
`console.*` +
`\\}` +
``;
const match4: string = `` +
`if *\\(${variableMatch}\\('${hexMatch}'\\) *!== *${variableMatch}\\('${hexMatch}'\\)\\) *\\{` +
`${variableMatch}.*` +
`alert.*` +
`\\} *else *\\{` +
`console.*` +
`\\}` +
@@ -309,5 +309,30 @@ describe('DeadCodeInjectionTransformer', () => {
assert.match(obfuscatedCode, regExp);
});
});
describe('variant #7 - correct obfuscation of dead-code block statements', () => {
const variableName: string = 'importantVariableName';
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/obfuscation-of-dead-code-block-statements.js');
const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
code,
{
...NO_CUSTOM_NODES_PRESET,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1,
debugProtection: true
}
);
obfuscatedCode = obfuscationResult.getObfuscatedCode();
});
it('should correctly obfuscate dead-code block statements and prevent any exposing of internal variable names', () => {
assert.notInclude(obfuscatedCode, variableName);
});
});
});
});
@@ -0,0 +1,5 @@
function test() {
var importantVariableName = 'test';
return importantVariableName.indexOf('test');
}