added BlockStatementControlFlowReplacer

This commit is contained in:
sanex3339
2017-01-05 12:58:47 +03:00
parent 412b42403e
commit cd02a0bf82
6 changed files with 1175 additions and 1094 deletions
+1016 -966
View File
File diff suppressed because it is too large Load Diff
@@ -6,6 +6,7 @@ import { IControlFlowReplacer } from '../../../interfaces/node-transformers/ICon
import { NodeControlFlowReplacers } from '../../../enums/container/NodeControlFlowReplacers';
import { BinaryExpressionControlFlowReplacer } from '../../../node-transformers/node-control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer';
import { BlockStatementControlFlowReplacer } from '../../../node-transformers/node-control-flow-transformers/control-flow-replacers/BlockStatementControlFlowReplacer';
import { CallExpressionControlFlowReplacer } from '../../../node-transformers/node-control-flow-transformers/control-flow-replacers/CallExpressionControlFlowReplacer';
import { LogicalExpressionControlFlowReplacer } from '../../../node-transformers/node-control-flow-transformers/control-flow-replacers/LogicalExpressionControlFlowReplacer';
@@ -14,6 +15,10 @@ export const nodeControlFlowTransformersModule: interfaces.ContainerModule = new
.to(BinaryExpressionControlFlowReplacer)
.whenTargetNamed(NodeControlFlowReplacers.BinaryExpressionControlFlowReplacer);
bind<IControlFlowReplacer>(ServiceIdentifiers.IControlFlowReplacer)
.to(BlockStatementControlFlowReplacer)
.whenTargetNamed(NodeControlFlowReplacers.BlockStatementControlFlowReplacer);
bind<IControlFlowReplacer>(ServiceIdentifiers.IControlFlowReplacer)
.to(CallExpressionControlFlowReplacer)
.whenTargetNamed(NodeControlFlowReplacers.CallExpressionControlFlowReplacer);
@@ -1,5 +1,6 @@
export enum NodeControlFlowReplacers {
BinaryExpressionControlFlowReplacer,
BlockStatementControlFlowReplacer,
CallExpressionControlFlowReplacer,
LogicalExpressionControlFlowReplacer
}
@@ -20,10 +20,8 @@ import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { Node } from '../../node/Node';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeControlFlowReplacers } from '../../enums/container/NodeControlFlowReplacers';
import { Nodes } from '../../node/Nodes';
import { NodeUtils } from '../../node/NodeUtils';
import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
import { Utils } from '../../utils/Utils';
@injectable()
export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
@@ -32,6 +30,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
*/
private static readonly controlFlowReplacersMap: Map <string, NodeControlFlowReplacers> = new Map([
[NodeType.BinaryExpression, NodeControlFlowReplacers.BinaryExpressionControlFlowReplacer],
[NodeType.BlockStatement, NodeControlFlowReplacers.BlockStatementControlFlowReplacer],
[NodeType.CallExpression, NodeControlFlowReplacers.CallExpressionControlFlowReplacer],
[NodeType.LogicalExpression, NodeControlFlowReplacers.LogicalExpressionControlFlowReplacer]
]);
@@ -90,18 +89,6 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
this.customNodeFactory = customNodeFactory;
}
/**
* @param node
* @return {boolean}
*/
private static functionHasProhibitedStatements (node: ESTree.Node): boolean {
const isBreakOrContinueStatement: boolean = Node.isBreakStatementNode(node) || Node.isContinueStatementNode(node);
const isVariableDeclarationWithLetOrConstKind: boolean = Node.isVariableDeclarationNode(node) &&
(node.kind === 'const' || node.kind === 'let');
return Node.isFunctionDeclarationNode(node) || isBreakOrContinueStatement || isVariableDeclarationWithLetOrConstKind;
}
/**
* @param functionNode
* @returns {TNodeWithBlockStatement}
@@ -138,23 +125,8 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
const hostNode: TNodeWithBlockStatement = FunctionControlFlowTransformer.getHostNode(functionNode);
const controlFlowStorage: IStorage<ICustomNode> = this.getControlFlowStorage(hostNode);
let functionHasProhibitedStatements: boolean = false;
this.controlFlowData.set(hostNode, controlFlowStorage);
estraverse.replace(functionNode.body, {
enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
if (!functionHasProhibitedStatements) {
functionHasProhibitedStatements = FunctionControlFlowTransformer.functionHasProhibitedStatements(node);
}
return this.transformFunctionNodes(node, parentNode, controlFlowStorage);
}
});
if (!functionHasProhibitedStatements) {
this.transformFunctionStatements(functionNode);
}
this.transformFunctionBody(functionNode.body, controlFlowStorage);
if (!controlFlowStorage.getLength()) {
return functionNode;
@@ -190,108 +162,29 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
}
/**
* @param node
* @param parentNode
* @param functionNodeBody
* @param controlFlowStorage
* @return {ESTree.Node}
*/
private transformFunctionNodes (
node: ESTree.Node,
parentNode: ESTree.Node,
controlFlowStorage: IStorage<ICustomNode>
): ESTree.Node {
if (!FunctionControlFlowTransformer.controlFlowReplacersMap.has(node.type)) {
return node;
}
private transformFunctionBody (functionNodeBody: ESTree.BlockStatement, controlFlowStorage: IStorage<ICustomNode>): void {
estraverse.replace(functionNodeBody, {
enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
if (!FunctionControlFlowTransformer.controlFlowReplacersMap.has(node.type)) {
return node;
}
if (RandomGeneratorUtils.getRandomFloat(0, 1) > this.options.controlFlowFlatteningThreshold) {
return node;
}
if (RandomGeneratorUtils.getRandomFloat(0, 1) > this.options.controlFlowFlatteningThreshold) {
return node;
}
const controlFlowReplacerName: NodeControlFlowReplacers = <NodeControlFlowReplacers>FunctionControlFlowTransformer
.controlFlowReplacersMap.get(node.type);
const controlFlowReplacerName: NodeControlFlowReplacers = <NodeControlFlowReplacers>FunctionControlFlowTransformer
.controlFlowReplacersMap.get(node.type);
return {
...this.controlFlowReplacerFactory(controlFlowReplacerName).replace(node, parentNode, controlFlowStorage),
parentNode
};
}
/**
* @param functionNode
*/
private transformFunctionStatements (functionNode: ESTree.FunctionExpression | ESTree.FunctionDeclaration): void {
if (RandomGeneratorUtils.getRandomFloat(0, 1) > this.options.controlFlowFlatteningThreshold) {
return;
}
const functionStatements: ESTree.Statement[] = functionNode.body.body;
const functionStatementsObject: any = Object.assign({}, functionStatements);
const originalKeys: number[] = Object.keys(functionStatementsObject).map((key: string) => parseInt(key, 10));
const shuffledKeys: number[] = Utils.arrayShuffle(originalKeys);
const originalKeysIndexesInShuffledArray: number[] = originalKeys.map((key: number) => shuffledKeys.indexOf(key));
if (functionStatements.length <= 4) {
return;
} else if (!functionStatements.length) {
functionStatements.push(
Nodes.getReturnStatementNode(
Nodes.getLiteralNode(true)
)
);
}
const controllerIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
const indexIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
functionNode.body.body = [
Nodes.getVariableDeclarationNode([
Nodes.getVariableDeclaratorNode(
Nodes.getIdentifierNode(controllerIdentifierName),
Nodes.getCallExpressionNode(
Nodes.getMemberExpressionNode(
Nodes.getLiteralNode(
originalKeysIndexesInShuffledArray.join('|')
),
Nodes.getIdentifierNode('split')
),
[
Nodes.getLiteralNode('|')
]
)
),
Nodes.getVariableDeclaratorNode(
Nodes.getIdentifierNode(indexIdentifierName),
Nodes.getLiteralNode(0)
)
]),
Nodes.getWhileStatementNode(
Nodes.getLiteralNode(true),
Nodes.getBlockStatementNode([
Nodes.getSwitchStatementNode(
Nodes.getMemberExpressionNode(
Nodes.getIdentifierNode(controllerIdentifierName),
Nodes.getUpdateExpressionNode(
'++',
Nodes.getIdentifierNode(indexIdentifierName)
),
true
),
shuffledKeys.map((key: number, index: number) => {
return Nodes.getSwitchCaseNode(
Nodes.getLiteralNode(String(index)),
[
functionStatementsObject[key],
Nodes.getContinueStatement()
]
);
})
),
Nodes.getBreakStatement()
])
)
];
NodeUtils.parentize(functionNode.body);
return {
...this.controlFlowReplacerFactory(controlFlowReplacerName).replace(node, parentNode, controlFlowStorage),
parentNode
};
}
});
}
}
@@ -0,0 +1,132 @@
import { injectable, inject } from 'inversify';
import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { TCustomNodeFactory } from '../../../types/container/TCustomNodeFactory';
import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../../interfaces/options/IOptions';
import { IStorage } from '../../../interfaces/storages/IStorage';
import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
import { Node } from '../../../node/Node';
import { Nodes } from '../../../node/Nodes';
import { NodeUtils } from '../../../node/NodeUtils';
import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';
import { Utils } from '../../../utils/Utils';
@injectable()
export class BlockStatementControlFlowReplacer extends AbstractControlFlowReplacer {
/**
* @param customNodeFactory
* @param options
*/
constructor (
@inject(ServiceIdentifiers.Factory__ICustomNode) customNodeFactory: TCustomNodeFactory,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(customNodeFactory, options);
}
/**
* @param blockStatementNode
* @return {boolean}
*/
private static blockStatementHasProhibitedStatements (blockStatementNode: ESTree.BlockStatement): boolean {
return blockStatementNode.body.some((statement: ESTree.Statement) => {
const isBreakOrContinueStatement: boolean = Node.isBreakStatementNode(statement) || Node.isContinueStatementNode(statement);
const isVariableDeclarationWithLetOrConstKind: boolean = Node.isVariableDeclarationNode(statement) &&
(statement.kind === 'const' || statement.kind === 'let');
return Node.isFunctionDeclarationNode(statement) || isBreakOrContinueStatement || isVariableDeclarationWithLetOrConstKind;
});
}
/**
* @param blockStatementNode
* @param parentNode
* @param controlFlowStorage
* @returns {ESTree.Node}
*/
public replace (
blockStatementNode: ESTree.BlockStatement,
parentNode: ESTree.Node,
controlFlowStorage: IStorage <ICustomNode>
): ESTree.BlockStatement {
if (BlockStatementControlFlowReplacer.blockStatementHasProhibitedStatements(blockStatementNode)) {
return blockStatementNode;
}
const blockStatementStatements: ESTree.Statement[] = blockStatementNode.body;
const blockStatementStatementsAsObject: any = Object.assign({}, blockStatementStatements);
const originalKeys: number[] = Object.keys(blockStatementStatementsAsObject).map((key: string) => parseInt(key, 10));
const shuffledKeys: number[] = Utils.arrayShuffle(originalKeys);
const originalKeysIndexesInShuffledArray: number[] = originalKeys.map((key: number) => shuffledKeys.indexOf(key));
if (blockStatementStatements.length <= 4) {
return blockStatementNode;
} else if (!blockStatementStatements.length) {
blockStatementStatements.push(
Nodes.getReturnStatementNode(
Nodes.getLiteralNode(true)
)
);
}
const controllerIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
const indexIdentifierName: string = RandomGeneratorUtils.getRandomString(3);
blockStatementNode.body = [
Nodes.getVariableDeclarationNode([
Nodes.getVariableDeclaratorNode(
Nodes.getIdentifierNode(controllerIdentifierName),
Nodes.getCallExpressionNode(
Nodes.getMemberExpressionNode(
Nodes.getLiteralNode(
originalKeysIndexesInShuffledArray.join('|')
),
Nodes.getIdentifierNode('split')
),
[
Nodes.getLiteralNode('|')
]
)
),
Nodes.getVariableDeclaratorNode(
Nodes.getIdentifierNode(indexIdentifierName),
Nodes.getLiteralNode(0)
)
]),
Nodes.getWhileStatementNode(
Nodes.getLiteralNode(true),
Nodes.getBlockStatementNode([
Nodes.getSwitchStatementNode(
Nodes.getMemberExpressionNode(
Nodes.getIdentifierNode(controllerIdentifierName),
Nodes.getUpdateExpressionNode(
'++',
Nodes.getIdentifierNode(indexIdentifierName)
),
true
),
shuffledKeys.map((key: number, index: number) => {
return Nodes.getSwitchCaseNode(
Nodes.getLiteralNode(String(index)),
[
blockStatementStatementsAsObject[key],
Nodes.getContinueStatement()
]
);
})
),
Nodes.getBreakStatement()
])
)
];
NodeUtils.parentize(blockStatementNode);
return blockStatementNode;
}
}
+1 -1
View File
@@ -99,7 +99,7 @@ if (!(<any>global)._babelPolyfill) {
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
disableConsoleOutput: false,
stringArray: false,
stringArray: true,
unicodeEscapeSequence: false
}
).getObfuscatedCode();