refactoring + control flow storage test

This commit is contained in:
sanex3339
2016-12-09 18:44:25 +03:00
parent 4b3bc9b81b
commit 1e7628b983
15 changed files with 688 additions and 587 deletions
+554 -525
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -20,7 +20,7 @@
"javascript-obfuscator": "./bin/javascript-obfuscator.js"
},
"dependencies": {
"babel-polyfill": "6.16.0",
"babel-polyfill": "6.20.0",
"chance": "1.0.4",
"class-validator": "0.6.6",
"commander": "2.9.0",
+2 -8
View File
@@ -6,6 +6,7 @@ import { nodeControlFlowTransformersModule } from './modules/node-transformers/N
import { nodeObfuscatorsModule } from './modules/node-transformers/NodeObfuscatorsModule';
import { nodeTransformersModule } from './modules/node-transformers/NodeTransformersModule';
import { stackTraceAnalyzerModule } from './modules/stack-trace-analyzer/StackTraceAnalyzerModule';
import { storagesModule } from './modules/storages/StoragesModule';
import { TInputOptions } from '../types/options/TInputOptions';
@@ -23,9 +24,6 @@ import { ObfuscationResult } from '../ObfuscationResult';
import { Obfuscator } from '../Obfuscator';
import { Options } from "../options/Options";
import { SourceMapCorrector } from '../SourceMapCorrector';
import { IStorage } from '../interfaces/storages/IStorage';
import { ICustomNodeGroup } from '../interfaces/custom-nodes/ICustomNodeGroup';
import { CustomNodeGroupStorage } from '../storages/custom-node-group/CustomNodeGroupStorage';
export class InversifyContainerFacade implements IInversifyContainerFacade {
/**
@@ -79,17 +77,13 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
.to(SourceMapCorrector)
.inSingletonScope();
this.container
.bind<IStorage<ICustomNodeGroup>>(ServiceIdentifiers['IStorage<ICustomNodeGroup>'])
.to(CustomNodeGroupStorage)
.inSingletonScope();
this.container
.bind<IObfuscationEventEmitter>(ServiceIdentifiers.IObfuscationEventEmitter)
.to(ObfuscationEventEmitter)
.inSingletonScope();
// modules
this.container.load(storagesModule);
this.container.load(stackTraceAnalyzerModule);
this.container.load(customNodesModule);
this.container.load(nodeTransformersModule);
+2
View File
@@ -6,6 +6,7 @@ export const ServiceIdentifiers: any = {
'Factory<INodeTransformer[]>': Symbol('Factory<INodeTransformer[]>'),
'Factory<IObfuscationResult>': Symbol('Factory<IObfuscationResult>'),
'Factory<IReplacer>': Symbol('Factory<IReplacer>'),
'Factory<IStorage<ICustomNode>>': Symbol('Factory<IStorage<ICustomNode>>'),
ICalleeDataExtractor: Symbol('ICalleeDataExtractor'),
ICustomNode: Symbol('ICustomNode'),
ICustomNodeGroup: Symbol('ICustomNodeGroup'),
@@ -19,5 +20,6 @@ export const ServiceIdentifiers: any = {
IReplacer: Symbol('IReplacer'),
ISourceMapCorrector: Symbol('ISourceMapCorrector'),
IStackTraceAnalyzer: Symbol('IStackTraceAnalyzer'),
'IStorage<ICustomNode>': Symbol('IStorage<ICustomNode>'),
'IStorage<ICustomNodeGroup>': Symbol('IStorage<ICustomNodeGroup>')
};
@@ -3,30 +3,30 @@ import { ServiceIdentifiers } from '../../ServiceIdentifiers';
import { IControlFlowReplacer } from '../../../interfaces/node-transformers/IControlFlowReplacer';
import { NodeControlFlowTransformersReplacers } from '../../../enums/container/NodeControlFlowTransformersReplacers';
import { NodeControlFlowReplacers } from '../../../enums/container/NodeControlFlowReplacers';
import { BinaryExpressionControlFlowReplacer } from '../../../node-transformers/node-control-flow-transformers/control-flow-replacers/BinaryExpressionControlFlowReplacer';
export const nodeControlFlowTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
bind<IControlFlowReplacer>(ServiceIdentifiers.IControlFlowReplacer)
.to(BinaryExpressionControlFlowReplacer)
.whenTargetNamed(NodeControlFlowTransformersReplacers.BinaryExpressionControlFlowReplacer);
.whenTargetNamed(NodeControlFlowReplacers.BinaryExpressionControlFlowReplacer);
bind<IControlFlowReplacer>(ServiceIdentifiers['Factory<IControlFlowReplacer>'])
.toFactory<IControlFlowReplacer>((context: interfaces.Context) => {
const cache: Map <NodeControlFlowTransformersReplacers, IControlFlowReplacer> = new Map <NodeControlFlowTransformersReplacers, IControlFlowReplacer> ();
const cache: Map <NodeControlFlowReplacers, IControlFlowReplacer> = new Map <NodeControlFlowReplacers, IControlFlowReplacer> ();
return (replacer: NodeControlFlowTransformersReplacers) => {
if (cache.has(replacer)) {
return <IControlFlowReplacer>cache.get(replacer);
return (replacerName: NodeControlFlowReplacers) => {
if (cache.has(replacerName)) {
return <IControlFlowReplacer>cache.get(replacerName);
}
const controlFlowReplacer: IControlFlowReplacer = context.container.getNamed<IControlFlowReplacer>(
ServiceIdentifiers.IControlFlowReplacer,
replacer
replacerName
);
cache.set(replacer, controlFlowReplacer);
cache.set(replacerName, controlFlowReplacer);
return controlFlowReplacer;
};
@@ -31,17 +31,17 @@ export const nodeObfuscatorsModule: interfaces.ContainerModule = new ContainerMo
.toFactory<IReplacer>((context: interfaces.Context) => {
const cache: Map <NodeObfuscatorsReplacers, IReplacer> = new Map <NodeObfuscatorsReplacers, IReplacer> ();
return (replacer: NodeObfuscatorsReplacers) => {
if (cache.has(replacer)) {
return <IReplacer>cache.get(replacer);
return (replacerName: NodeObfuscatorsReplacers) => {
if (cache.has(replacerName)) {
return <IReplacer>cache.get(replacerName);
}
const obfuscationReplacer: IReplacer = context.container.getNamed<IReplacer>(
ServiceIdentifiers.IReplacer,
replacer
replacerName
);
cache.set(replacer, obfuscationReplacer);
cache.set(replacerName, obfuscationReplacer);
return obfuscationReplacer;
};
@@ -0,0 +1,27 @@
import { ContainerModule, interfaces } from 'inversify';
import { ServiceIdentifiers } from '../../ServiceIdentifiers';
import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
import { ICustomNodeGroup } from '../../../interfaces/custom-nodes/ICustomNodeGroup';
import { IStorage } from '../../../interfaces/storages/IStorage';
import { ControlFlowStorage } from '../../../storages/control-flow/ControlFlowStorage';
import { CustomNodeGroupStorage } from '../../../storages/custom-node-group/CustomNodeGroupStorage';
export const storagesModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
// storages
bind<IStorage<ICustomNodeGroup>>(ServiceIdentifiers['IStorage<ICustomNodeGroup>'])
.to(CustomNodeGroupStorage)
.inSingletonScope();
bind<IStorage<ICustomNode>>(ServiceIdentifiers['IStorage<ICustomNode>'])
.to(ControlFlowStorage);
// controlFlowStorage factory
bind<IStorage<ICustomNode>>(ServiceIdentifiers['Factory<IStorage<ICustomNode>>'])
.toFactory<IStorage<ICustomNode>>((context: interfaces.Context) => {
return () => {
return context.container.get<IStorage<ICustomNode>>(ServiceIdentifiers['IStorage<ICustomNode>']);
};
});
});
@@ -0,0 +1,3 @@
export enum NodeControlFlowReplacers {
BinaryExpressionControlFlowReplacer
}
@@ -1,3 +0,0 @@
export enum NodeControlFlowTransformersReplacers {
BinaryExpressionControlFlowReplacer
}
@@ -4,39 +4,65 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';
import { TControlFlowReplacer } from '../../types/node-transformers/TControlFlowReplacer';
import { TControlFlowReplacerFactory } from '../../types/container/TControlFlowReplacerFactory';
import { TControlFlowStorageFactory } from '../../types/container/TControlFlowStorageFactory';
import { TCustomNodeFactory } from '../../types/container/TCustomNodeFactory';
import { TStatement } from '../../types/node/TStatement';
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { IOptions } from '../../interfaces/options/IOptions';
import { IStorage } from '../../interfaces/storages/IStorage';
import { CustomNodes } from '../../enums/container/CustomNodes';
import { NodeType } from '../../enums/NodeType';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { BinaryExpressionControlFlowReplacer } from './control-flow-replacers/BinaryExpressionControlFlowReplacer';
import { ControlFlowStorage } from '../../storages/control-flow/ControlFlowStorage';
import { ControlFlowStorageNode } from '../../custom-nodes/control-flow-storage-nodes/ControlFlowStorageNode';
import { Node } from '../../node/Node';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeControlFlowReplacers } from '../../enums/container/NodeControlFlowReplacers';
import { RandomGeneratorUtils } from '../../utils/RandomGeneratorUtils';
@injectable()
export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
/**
* @type {Map <string, IReplacer>}
* @type {Map <string, NodeControlFlowReplacers>}
*/
private static readonly controlFlowReplacers: Map <string, TControlFlowReplacer> = new Map <string, TControlFlowReplacer> ([
[NodeType.BinaryExpression, BinaryExpressionControlFlowReplacer]
private static readonly controlFlowReplacersMap: Map <string, NodeControlFlowReplacers> = new Map <string, NodeControlFlowReplacers> ([
[NodeType.BinaryExpression, NodeControlFlowReplacers.BinaryExpressionControlFlowReplacer]
]);
/**
* @type {TControlFlowReplacerFactory}
*/
private readonly controlFlowReplacerFactory: TControlFlowReplacerFactory;
/**
* @type {TControlFlowStorageFactory}
*/
private readonly controlFlowStorageFactory: TControlFlowStorageFactory;
/**
* @type {TCustomNodeFactory}
*/
private readonly customNodeFactory: TCustomNodeFactory;
/**
* @param controlFlowStorageFactory
* @param controlFlowReplacerFactory
* @param customNodeFactory
* @param options
*/
constructor (
@inject(ServiceIdentifiers['Factory<IStorage<ICustomNode>>']) controlFlowStorageFactory: TControlFlowStorageFactory,
@inject(ServiceIdentifiers['Factory<IControlFlowReplacer>']) controlFlowReplacerFactory: TControlFlowReplacerFactory,
@inject(ServiceIdentifiers['Factory<ICustomNode>']) customNodeFactory: TCustomNodeFactory,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(options);
this.controlFlowStorageFactory = controlFlowStorageFactory;
this.controlFlowReplacerFactory = controlFlowReplacerFactory;
this.customNodeFactory = customNodeFactory;
}
/**
@@ -54,21 +80,20 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
return;
}
const controlFlowStorage: IStorage <ICustomNode> = new ControlFlowStorage();
const controlFlowStorage: IStorage <ICustomNode> = this.controlFlowStorageFactory();
const controlFlowStorageCustomNodeName: string = RandomGeneratorUtils.getRandomVariableName(6);
estraverse.replace(functionNode.body, {
enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
const controlFlowReplacer: TControlFlowReplacer | undefined = FunctionControlFlowTransformer
.controlFlowReplacers.get(node.type);
const controlFlowReplacerName: NodeControlFlowReplacers | undefined = FunctionControlFlowTransformer
.controlFlowReplacersMap.get(node.type);
if (!controlFlowReplacer) {
if (controlFlowReplacerName === undefined) {
return;
}
const controlFlowStorageCallCustomNode: ICustomNode | undefined = new controlFlowReplacer(
this.options
).replace(node, parentNode, controlFlowStorage, controlFlowStorageCustomNodeName);
const controlFlowStorageCallCustomNode: ICustomNode | undefined = this.controlFlowReplacerFactory(controlFlowReplacerName)
.replace(node, parentNode, controlFlowStorage, controlFlowStorageCustomNodeName);
if (!controlFlowStorageCallCustomNode) {
return;
@@ -78,7 +103,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
// so we can get it by index `0`
// also we need to return `expression` property of `ExpressionStatement` node because bug:
// https://github.com/estools/escodegen/issues/289
const statementNode: TStatement | undefined = controlFlowStorageCallCustomNode.getNode()[0];
const statementNode: TStatement = controlFlowStorageCallCustomNode.getNode()[0];
if (!statementNode || !Node.isExpressionStatementNode(statementNode)) {
throw new Error(`\`controlFlowStorageCallCustomNode.getNode()\` should returns array with \`ExpressionStatement\` node`);
@@ -92,7 +117,7 @@ export class FunctionControlFlowTransformer extends AbstractNodeTransformer {
return;
}
const controlFlowStorageCustomNode: ICustomNode = new ControlFlowStorageNode(this.options);
const controlFlowStorageCustomNode: ICustomNode = this.customNodeFactory(CustomNodes.ControlFlowStorageNode);
controlFlowStorageCustomNode.initialize(controlFlowStorage, controlFlowStorageCustomNodeName);
@@ -4,23 +4,34 @@ import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
import * as escodegen from 'escodegen';
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 { CustomNodes } from '../../../enums/container/CustomNodes';
import { AbstractControlFlowReplacer } from './AbstractControlFlowReplacer';
import { BinaryExpressionFunctionNode } from '../../../custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/BinaryExpressionFunctionNode';
import { ControlFlowStorageCallNode } from '../../../custom-nodes/control-flow-replacers-nodes/binary-expression-control-flow-replacer-nodes/ControlFlowStorageCallNode';
@injectable()
export class BinaryExpressionControlFlowReplacer extends AbstractControlFlowReplacer {
/**
* @type {TCustomNodeFactory}
*/
private readonly customNodeFactory: TCustomNodeFactory;
/**
* @param customNodeFactory
* @param options
*/
constructor (
@inject(ServiceIdentifiers['Factory<ICustomNode>']) customNodeFactory: TCustomNodeFactory,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(options);
this.customNodeFactory = customNodeFactory;
}
/**
@@ -47,15 +58,10 @@ export class BinaryExpressionControlFlowReplacer extends AbstractControlFlowRepl
controlFlowStorageCustomNodeName: string
): ICustomNode {
const key: string = AbstractControlFlowReplacer.getStorageKey();
const binaryExpressionFunctionNode = new BinaryExpressionFunctionNode(this.options);
const binaryExpressionFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.BinaryExpressionFunctionNode);
const controlFlowStorageCallNode: ICustomNode = this.customNodeFactory(CustomNodes.ControlFlowStorageCallNode);
// TODO: pass through real stackTraceData
binaryExpressionFunctionNode.initialize(binaryExpressionNode.operator);
controlFlowStorage.set(key, binaryExpressionFunctionNode);
const controlFlowStorageCallNode: ICustomNode = new ControlFlowStorageCallNode(this.options);
controlFlowStorageCallNode.initialize(
controlFlowStorageCustomNodeName,
key,
@@ -63,6 +69,8 @@ export class BinaryExpressionControlFlowReplacer extends AbstractControlFlowRepl
BinaryExpressionControlFlowReplacer.getExpressionValue(binaryExpressionNode.right)
);
controlFlowStorage.set(key, binaryExpressionFunctionNode);
return controlFlowStorageCallNode;
}
}
+5
View File
@@ -0,0 +1,5 @@
import { IControlFlowReplacer } from '../../interfaces/node-transformers/IControlFlowReplacer';
import { NodeControlFlowReplacers } from '../../enums/container/NodeControlFlowReplacers';
export type TControlFlowReplacerFactory = (replacer: NodeControlFlowReplacers) => IControlFlowReplacer;
+4
View File
@@ -0,0 +1,4 @@
import { ICustomNode } from '../../interfaces/custom-nodes/ICustomNode';
import { IStorage } from '../../interfaces/storages/IStorage';
export type TControlFlowStorageFactory = () => IStorage<ICustomNode>;
-4
View File
@@ -1,4 +0,0 @@
import { IControlFlowReplacer } from '../../interfaces/node-transformers/IControlFlowReplacer';
import { IOptions } from '../../interfaces/options/IOptions';
export type TControlFlowReplacer = (new (options: IOptions) => IControlFlowReplacer);
@@ -1,7 +1,8 @@
/*
import { ServiceIdentifiers } from '../../../src/container/ServiceIdentifiers';
import { assert } from 'chai';
import { assert } from 'chai';
import { TCustomNodeFactory } from '../../../src/types/container/TCustomNodeFactory';
import { ICustomNode } from '../../../src/interfaces/custom-nodes/ICustomNode';
import { IInversifyContainerFacade } from '../../../src/interfaces/container/IInversifyContainerFacade';
@@ -13,19 +14,29 @@ import { InversifyContainerFacade } from '../../../src/container/InversifyContai
describe('ControlFlowStorage', () => {
describe('toString (): string', () => {
it('should returns obfuscated code if `.toString()` was called on `ObfuscationResult` object', () => {
it('should return correct ControlFlowStorage data after `.toString()` call', () => {
const key1: string = 'key1';
const key2: string = 'key2';
const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade({
controlFlowFlattening: true
});
const customNodeFactory: TCustomNodeFactory = inversifyContainerFacade
.get<TCustomNodeFactory>(ServiceIdentifiers['Factory<ICustomNode>']);
const controlFlowStorage: IStorage <ICustomNode> = inversifyContainerFacade
.get<IStorage<ICustomNode>>(ServiceIdentifiers['IStorage<ICustomNode>']);
const controlFlowStorageCallNode: ICustomNode = inversifyContainerFacade
.getNamed<ICustomNode>(ServiceIdentifiers.ICustomNode, CustomNodes.ControlFlowStorageCallNode);
const controlFlowStorageCallNode1: ICustomNode = customNodeFactory(CustomNodes.ControlFlowStorageCallNode);
const controlFlowStorageCallNode2: ICustomNode = customNodeFactory(CustomNodes.ControlFlowStorageCallNode);
controlFlowStorage.set('key1', controlFlowStorageCallNode);
controlFlowStorageCallNode1.initialize('controlFlowStorageName', key1, 1, 2);
controlFlowStorageCallNode2.initialize('controlFlowStorageName', key2, 3, 4);
assert.equal(controlFlowStorage.toString(), [`key1: ${controlFlowStorageCallNode.getCode()}`]);
controlFlowStorage.set(key1, controlFlowStorageCallNode1);
controlFlowStorage.set(key2, controlFlowStorageCallNode2);
assert.equal(
controlFlowStorage.toString(),
`${key1}: ${controlFlowStorageCallNode1.getCode()},${key2}: ${controlFlowStorageCallNode2.getCode()}`
);
});
});
});
*/