Base mangle properties realisation

This commit is contained in:
sanex3339
2020-06-05 23:44:05 +03:00
parent 4e9a9b90d7
commit f0465fc8f8
13 changed files with 41761 additions and 7 deletions
+2
View File
@@ -70,6 +70,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
NodeTransformer.FunctionControlFlowTransformer,
NodeTransformer.LabeledStatementTransformer,
NodeTransformer.LiteralTransformer,
NodeTransformer.ManglePropertiesTransformer,
NodeTransformer.MemberExpressionTransformer,
NodeTransformer.MetadataTransformer,
NodeTransformer.MethodDefinitionTransformer,
@@ -208,6 +209,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.ControlFlowFlattening);
}
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.MangleProperties);
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Converting);
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Obfuscating);
astTree = this.runNodeTransformationStage(astTree, NodeTransformationStage.Finalizing);
@@ -10,6 +10,7 @@ import { customNodesModule } from './modules/custom-nodes/CustomNodesModule';
import { finalizingTransformersModule } from './modules/node-transformers/FinalizingTransformersModule';
import { generatorsModule } from './modules/generators/GeneratorsModule';
import { initializingTransformersModule } from './modules/node-transformers/InitializingTransformersModule';
import { manglePropertiesTransformersModule } from './modules/node-transformers/ManglePropertiesTransformersModule';
import { nodeModule } from './modules/node/NodeModule';
import { nodeTransformersModule } from './modules/node-transformers/NodeTransformersModule';
import { obfuscatingTransformersModule } from './modules/node-transformers/ObfuscatingTransformersModule';
@@ -210,6 +211,7 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
this.container.load(finalizingTransformersModule);
this.container.load(generatorsModule);
this.container.load(initializingTransformersModule);
this.container.load(manglePropertiesTransformersModule);
this.container.load(nodeModule);
this.container.load(nodeTransformersModule);
this.container.load(obfuscatingTransformersModule);
+1
View File
@@ -33,6 +33,7 @@ export enum ServiceIdentifiers {
IJavaScriptObfuscator = 'IJavaScriptObfuscator',
ILevelledTopologicalSorter = 'ILevelledTopologicalSorter',
ILogger = 'ILogger',
IManglePropertiesObfuscatingReplacer = 'IManglePropertiesObfuscatingReplacer',
INodeGuard = 'INodeGuard',
INodeTransformer = 'INodeTransformer',
INodeTransformerNamesGroupsBuilder = 'INodeTransformerNamesGroupsBuilder',
@@ -0,0 +1,21 @@
import { ContainerModule, interfaces } from 'inversify';
import { ServiceIdentifiers } from '../../ServiceIdentifiers';
import { IManglePropertiesReplacer } from '../../../interfaces/node-transformers/mangle-properties-transformers/replacer/IManglePropertiesReplacer';
import { INodeTransformer } from '../../../interfaces/node-transformers/INodeTransformer';
import { NodeTransformer } from '../../../enums/node-transformers/NodeTransformer';
import { ManglePropertiesReplacer } from '../../../node-transformers/mangle-properties-transformers/replacer/ManglePropertiesReplacer';
import { ManglePropertiesTransformer } from '../../../node-transformers/mangle-properties-transformers/ManglePropertiesTransformer';
export const manglePropertiesTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
// mangle properties transformers
bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
.to(ManglePropertiesTransformer)
.whenTargetNamed(NodeTransformer.ManglePropertiesTransformer);
// mangle properties obfuscating replacer
bind<IManglePropertiesReplacer>(ServiceIdentifiers.IManglePropertiesObfuscatingReplacer)
.to(ManglePropertiesReplacer);
});
@@ -45,7 +45,7 @@ export const obfuscatingTransformersModule: interfaces.ContainerModule = new Con
.to(StringLiteralObfuscatingReplacer)
.whenTargetNamed(LiteralObfuscatingReplacer.StringLiteralObfuscatingReplacer);
// identifier obfuscating replacers
// identifier obfuscating replacer
bind<IIdentifierObfuscatingReplacer>(ServiceIdentifiers.IIdentifierObfuscatingReplacer)
.to(BaseIdentifierObfuscatingReplacer)
.whenTargetNamed(IdentifierObfuscatingReplacer.BaseIdentifierObfuscatingReplacer);
@@ -1,6 +1,7 @@
export enum NodeTransformationStage {
Initializing = 'Initializing',
Preparing = 'Preparing',
MangleProperties = 'MangleProperties',
DeadCodeInjection = 'DeadCodeInjection',
ControlFlowFlattening = 'ControlFlowFlattening',
Converting = 'Converting',
@@ -7,6 +7,7 @@ export enum NodeTransformer {
FunctionControlFlowTransformer = 'FunctionControlFlowTransformer',
LabeledStatementTransformer = 'LabeledStatementTransformer',
LiteralTransformer = 'LiteralTransformer',
ManglePropertiesTransformer = 'ManglePropertiesTransformer',
MemberExpressionTransformer = 'MemberExpressionTransformer',
MetadataTransformer = 'MetadataTransformer',
MethodDefinitionTransformer = 'MethodDefinitionTransformer',
@@ -0,0 +1,9 @@
import * as ESTree from 'estree';
export interface IManglePropertiesReplacer {
/**
* @param {TNode} node
* @returns {TNode}
*/
replace <TNode extends ESTree.Identifier | ESTree.Literal> (node: TNode): TNode;
}
@@ -0,0 +1,136 @@
import { inject, injectable, } from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { IManglePropertiesReplacer } from '../../interfaces/node-transformers/mangle-properties-transformers/replacer/IManglePropertiesReplacer';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
import { NodeTransformationStage } from '../../enums/node-transformers/NodeTransformationStage';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeGuards } from '../../node/NodeGuards';
@injectable()
export class ManglePropertiesTransformer extends AbstractNodeTransformer {
/**
* @type {IManglePropertiesReplacer}
*/
private readonly manglePropertiesObfuscatingReplacer: IManglePropertiesReplacer;
/**
* @param {IManglePropertiesReplacer} manglePropertiesObfuscatingReplacer
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
*/
public constructor (
@inject(ServiceIdentifiers.IManglePropertiesObfuscatingReplacer)
manglePropertiesObfuscatingReplacer: IManglePropertiesReplacer,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(randomGenerator, options);
this.manglePropertiesObfuscatingReplacer = manglePropertiesObfuscatingReplacer;
}
/**
* @param {NodeTransformationStage} nodeTransformationStage
* @returns {IVisitor | null}
*/
public getVisitor (nodeTransformationStage: NodeTransformationStage): IVisitor | null {
switch (nodeTransformationStage) {
case NodeTransformationStage.MangleProperties:
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node | undefined => {
if (parentNode) {
return this.transformNode(node, parentNode);
}
return node;
}
};
default:
return null;
}
}
/**
* @param {Node} node
* @param {NodeGuards} parentNode
* @returns {Node}
*/
public transformNode (node: ESTree.Node, parentNode: ESTree.Node): ESTree.Node {
if (NodeGuards.isPropertyNode(node)) {
return this.transformPropertyNode(node);
}
if (NodeGuards.isMemberExpressionNode(node)) {
return this.transformMemberExpressionNode(node);
}
if (NodeGuards.isMethodDefinitionNode(node)) {
return this.transformMethodDefinitionNode(node);
}
return node;
}
/**
* @param {Property} propertyNode
* @returns {Property}
*/
private transformPropertyNode (propertyNode: ESTree.Property): ESTree.Property {
const propertyKeyNode: ESTree.Expression = propertyNode.key;
if (NodeGuards.isIdentifierNode(propertyKeyNode) && propertyNode.computed) {
return propertyNode;
}
if (NodeGuards.isIdentifierNode(propertyKeyNode) || NodeGuards.isLiteralNode(propertyKeyNode)) {
propertyNode.key = this.manglePropertiesObfuscatingReplacer.replace(propertyKeyNode);
propertyNode.shorthand = false;
}
return propertyNode;
}
/**
* @param {Property} memberExpressionNode
* @returns {Property}
*/
private transformMemberExpressionNode (memberExpressionNode: ESTree.MemberExpression): ESTree.MemberExpression {
const propertyKeyNode: ESTree.Expression = memberExpressionNode.property;
if (NodeGuards.isIdentifierNode(propertyKeyNode) && memberExpressionNode.computed) {
return memberExpressionNode;
}
if (NodeGuards.isIdentifierNode(propertyKeyNode) || NodeGuards.isLiteralNode(propertyKeyNode)) {
memberExpressionNode.property = this.manglePropertiesObfuscatingReplacer.replace(propertyKeyNode);
}
return memberExpressionNode;
}
/**
* @param {MethodDefinition} methodDefinitionNode
* @returns {MethodDefinition}
*/
private transformMethodDefinitionNode (methodDefinitionNode: ESTree.MethodDefinition): ESTree.MethodDefinition {
const propertyKeyNode: ESTree.Expression = methodDefinitionNode.key;
if (NodeGuards.isIdentifierNode(propertyKeyNode) && methodDefinitionNode.computed) {
return methodDefinitionNode;
}
if (NodeGuards.isIdentifierNode(propertyKeyNode) || NodeGuards.isLiteralNode(propertyKeyNode)) {
methodDefinitionNode.key = this.manglePropertiesObfuscatingReplacer.replace(propertyKeyNode);
}
return methodDefinitionNode;
}
}
@@ -0,0 +1,127 @@
import { inject, injectable, } from 'inversify';
import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { TIdentifierNamesGeneratorFactory } from '../../../types/container/generators/TIdentifierNamesGeneratorFactory';
import { IIdentifierNamesGenerator } from '../../../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
import { IManglePropertiesReplacer } from '../../../interfaces/node-transformers/mangle-properties-transformers/replacer/IManglePropertiesReplacer';
import { IOptions } from '../../../interfaces/options/IOptions';
import { ReservedDomProperties } from '../../../constants/ReservedDomProperties';
import { NodeGuards } from '../../../node/NodeGuards';
import { NodeFactory } from '../../../node/NodeFactory';
@injectable()
export class ManglePropertiesReplacer implements IManglePropertiesReplacer {
/**
* @type {IIdentifierNamesGenerator}
*/
private readonly identifierNamesGenerator: IIdentifierNamesGenerator;
/**
* @type {Map<string, string>}
* @private
*/
private readonly mangledPropertyNamesMap: Map<string, string> = new Map();
/**
* @type {IOptions}
*/
private readonly options: IOptions;
/**
* @type {Set<string>}
*/
private readonly reservedDomPropertiesList: Set<string> = new Set(ReservedDomProperties);
/**
* @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
* @param {IOptions} options
*/
public constructor (
@inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
this.identifierNamesGenerator = identifierNamesGeneratorFactory(options);
this.options = options;
}
/**
* @param {string} node
* @returns {string}
*/
public replace <TNode extends ESTree.Identifier | ESTree.Literal> (node: TNode): TNode {
if (NodeGuards.isIdentifierNode(node)) {
return <TNode>NodeFactory.identifierNode(
this.replacePropertyName(node.name)
);
}
if (NodeGuards.isLiteralNode(node) && typeof node.value === 'string') {
return <TNode>NodeFactory.literalNode(
this.replacePropertyName(node.value)
);
}
return node;
}
/**
* @param {string} propertyName
* @returns {string}
* @private
*/
private replacePropertyName (propertyName: string): string {
if (this.isReservedName(propertyName)) {
return propertyName;
}
let mangledPropertyName: string;
if (this.mangledPropertyNamesMap.has(propertyName)) {
mangledPropertyName = <string>this.mangledPropertyNamesMap.get(propertyName);
} else {
mangledPropertyName = this.identifierNamesGenerator.generateNext();
this.mangledPropertyNamesMap.set(propertyName, mangledPropertyName);
}
return mangledPropertyName;
}
/**
* @param {string} name
* @returns {boolean}
*/
private isReservedName (name: string): boolean {
return this.isReservedOptionName(name)
|| this.isReservedDomPropertyName(name);
}
/**
* @param {string} name
* @returns {boolean}
*/
private isReservedOptionName (name: string): boolean {
if (!this.options.reservedNames.length) {
return false;
}
return this.options.reservedNames
.some((reservedName: string) => {
return new RegExp(reservedName, 'g').exec(name) !== null;
});
}
/**
* @param {string} name
* @returns {boolean}
*/
private isReservedDomPropertyName (name: string): boolean {
return this.reservedDomPropertiesList.has(name);
}
}