obfuscation of eval call expressions WIP

This commit is contained in:
sanex3339
2018-01-08 18:22:50 +03:00
parent 12a03d52e9
commit 07c7414420
12 changed files with 9462 additions and 34 deletions
+9316 -1
View File
File diff suppressed because one or more lines are too long
+8 -2
View File
@@ -49,6 +49,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
* @type {NodeTransformer[]}
*/
private static readonly convertingTransformersList: NodeTransformer[] = [
NodeTransformer.CallExpressionTransformer,
NodeTransformer.MemberExpressionTransformer,
NodeTransformer.MethodDefinitionTransformer,
NodeTransformer.TemplateLiteralTransformer
@@ -176,7 +177,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
const obfuscationTime: number = (Date.now() - timeStart) / 1000;
this.logger.success(LoggingMessage.ObfuscationCompleted, obfuscationTime);
return this.getObfuscationResult(generatorOutput);
return this.getObfuscationResult(obfuscatedAstTree, generatorOutput);
}
/**
@@ -290,11 +291,16 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
}
/**
* @param {Program} obfuscatedAstTree
* @param {IGeneratorOutput} generatorOutput
* @returns {IObfuscationResult}
*/
private getObfuscationResult (generatorOutput: IGeneratorOutput): IObfuscationResult {
private getObfuscationResult (
obfuscatedAstTree: ESTree.Program,
generatorOutput: IGeneratorOutput
): IObfuscationResult {
return this.sourceMapCorrector.correct(
obfuscatedAstTree,
generatorOutput.code,
generatorOutput.map
);
+18 -1
View File
@@ -1,11 +1,19 @@
import { injectable } from 'inversify';
import { Program } from 'estree';
import { IObfuscationResult } from './interfaces/IObfuscationResult';
import { initializable } from './decorators/Initializable';
@injectable()
export class ObfuscationResult implements IObfuscationResult {
/**
* @type {Program}
*/
@initializable()
private obfuscatedAst: Program;
/**
* @type {string}
*/
@@ -19,14 +27,23 @@ export class ObfuscationResult implements IObfuscationResult {
private sourceMap: string;
/**
* @param {Program} obfuscatedAst
* @param {string} obfuscatedCode
* @param {string} sourceMap
*/
public initialize (obfuscatedCode: string, sourceMap: string): void {
public initialize (obfuscatedAst: Program, obfuscatedCode: string, sourceMap: string): void {
this.obfuscatedAst = obfuscatedAst;
this.obfuscatedCode = obfuscatedCode;
this.sourceMap = sourceMap;
}
/**
* @returns {Program}
*/
public getObfuscatedAst (): Program {
return this.obfuscatedAst;
}
/**
* @returns {string}
*/
+4 -2
View File
@@ -1,6 +1,8 @@
import { Container, interfaces } from 'inversify';
import { ServiceIdentifiers } from './ServiceIdentifiers';
import * as ESTree from 'estree';
import { analyzersModule } from './modules/analyzers/AnalyzersModule';
import { controlFlowTransformersModule } from './modules/node-transformers/ControlFlowTransformersModule';
import { convertingTransformersModule } from './modules/node-transformers/ConvertingTransformersModule';
@@ -173,11 +175,11 @@ export class InversifyContainerFacade implements IInversifyContainerFacade {
this.container
.bind<IObfuscationResult>(ServiceIdentifiers.Factory__IObfuscationResult)
.toFactory<IObfuscationResult>((context: interfaces.Context) => {
return (obfuscatedCode: string, sourceMap: string) => {
return (obfuscatedAst: ESTree.Program, obfuscatedCode: string, sourceMap: string) => {
const obfuscationResult: IObfuscationResult = context.container
.get<IObfuscationResult>(ServiceIdentifiers.IObfuscationResult);
obfuscationResult.initialize(obfuscatedCode, sourceMap);
obfuscationResult.initialize(obfuscatedAst, obfuscatedCode, sourceMap);
return obfuscationResult;
};
@@ -5,12 +5,17 @@ import { INodeTransformer } from '../../../interfaces/node-transformers/INodeTra
import { NodeTransformer } from '../../../enums/node-transformers/NodeTransformer';
import { CallExpressionTransformer } from '../../../node-transformers/converting-transformers/CallExpressionTransformer';
import { MemberExpressionTransformer } from '../../../node-transformers/converting-transformers/MemberExpressionTransformer';
import { MethodDefinitionTransformer } from '../../../node-transformers/converting-transformers/MethodDefinitionTransformer';
import { TemplateLiteralTransformer } from '../../../node-transformers/converting-transformers/TemplateLiteralTransformer';
export const convertingTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
// converting transformers
bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
.to(CallExpressionTransformer)
.whenTargetNamed(NodeTransformer.CallExpressionTransformer);
bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
.to(MemberExpressionTransformer)
.whenTargetNamed(NodeTransformer.MemberExpressionTransformer);
@@ -1,5 +1,6 @@
export enum NodeTransformer {
BlockStatementControlFlowTransformer,
CallExpressionTransformer,
ClassDeclarationTransformer,
CommentsTransformer,
DeadCodeInjectionTransformer,
+7
View File
@@ -1,6 +1,13 @@
import * as ESTree from 'estree';
import { IInitializable } from './IInitializable';
export interface IObfuscationResult extends IInitializable {
/**
* @return {string}
*/
getObfuscatedAst (): ESTree.Program;
/**
* @return {string}
*/
+7 -4
View File
@@ -1,10 +1,13 @@
import * as ESTree from 'estree';
import { IObfuscationResult } from '../IObfuscationResult';
export interface ISourceMapCorrector {
/**
* @param obfuscatedCode
* @param sourceMap
* @returns IObfuscationResult
* @param {Program} obfuscatedAst
* @param {string} obfuscatedCode
* @param {string} sourceMap
* @returns {IObfuscationResult}
*/
correct (obfuscatedCode: string, sourceMap: string): IObfuscationResult;
correct (obfuscatedAst: ESTree.Program, obfuscatedCode: string, sourceMap: string): IObfuscationResult;
}
@@ -0,0 +1,84 @@
import { inject, injectable, } from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { IOptions } from '../../interfaces/options/IOptions';
import { IJavaScriptObfuscator } from '../../interfaces/IJavaScriptObfsucator';
import { IObfuscationResult } from '../../interfaces/IObfuscationResult';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeGuards } from '../../node/NodeGuards';
@injectable()
export class CallExpressionTransformer extends AbstractNodeTransformer {
/**
* @type {IJavaScriptObfuscator}
*/
private readonly javaScriptObfuscator: IJavaScriptObfuscator;
/**
* @param {IJavaScriptObfuscator} javaScriptObfuscator
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
*/
constructor (
@inject(ServiceIdentifiers.IJavaScriptObfuscator) javaScriptObfuscator: IJavaScriptObfuscator,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(randomGenerator, options);
this.javaScriptObfuscator = javaScriptObfuscator;
}
/**
* @return {IVisitor}
*/
public getVisitor (): IVisitor {
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
if (parentNode && NodeGuards.isCallExpressionNode(node)) {
return this.transformNode(node, parentNode);
}
}
};
}
/**
* @param {CallExpression} callExpressionNode
* @param {Node} parentNode
* @returns {Node}
*/
public transformNode (callExpressionNode: ESTree.CallExpression, parentNode: ESTree.Node): ESTree.Node {
const callExpressionFirstArgument: ESTree.Expression | ESTree.SpreadElement = callExpressionNode.arguments[0];
if (
NodeGuards.isIdentifierNode(callExpressionNode.callee)
&& callExpressionNode.callee.name === 'eval'
&& callExpressionFirstArgument
&& NodeGuards.isLiteralNode(callExpressionFirstArgument)
) {
return this.transformEvalCallExpressionLiteralToAst(callExpressionFirstArgument);
}
return callExpressionNode;
}
/**
* @param {Literal} literalNode
* @returns {Node}
*/
private transformEvalCallExpressionLiteralToAst (literalNode: ESTree.Literal): ESTree.Node {
if (typeof literalNode.value !== 'string') {
return literalNode;
}
const code: string = literalNode.value;
const obfuscationResult: IObfuscationResult = this.javaScriptObfuscator.obfuscate(code);
return obfuscationResult.getObfuscatedAst();
}
}
+5 -1
View File
@@ -1,6 +1,8 @@
import { inject, injectable } from 'inversify';
import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { TObfuscationResultFactory } from '../types/container/TObfuscationResultFactory';
import { ICryptUtils } from '../interfaces/utils/ICryptUtils';
@@ -43,12 +45,14 @@ export class SourceMapCorrector implements ISourceMapCorrector {
}
/**
* @param {Program} obfuscatedAst
* @param {string} obfuscatedCode
* @param {string} sourceMap
* @returns {IObfuscationResult}
*/
public correct (obfuscatedCode: string, sourceMap: string): IObfuscationResult {
public correct (obfuscatedAst: ESTree.Program, obfuscatedCode: string, sourceMap: string): IObfuscationResult {
return this.obfuscationResultFactory(
obfuscatedAst,
this.correctObfuscatedCode(obfuscatedCode, sourceMap),
sourceMap
);
+3 -1
View File
@@ -1,3 +1,5 @@
import * as ESTree from 'estree';
import { IObfuscationResult } from '../../interfaces/IObfuscationResult';
export type TObfuscationResultFactory = (obfuscatedCode: string, sourceMap: string) => IObfuscationResult;
export type TObfuscationResultFactory = (obfuscatedAst: ESTree.Program, obfuscatedCode: string, sourceMap: string) => IObfuscationResult;
+4 -22
View File
@@ -7,29 +7,11 @@ import { NO_CUSTOM_NODES_PRESET } from '../../src/options/presets/NoCustomNodes'
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
(function(){
if (true) {
var foo = function () {
console.log('abc');
};
var bar = function () {
console.log('def');
};
var baz = function () {
console.log('ghi');
};
var bark = function () {
console.log('jkl');
};
var hawk = function () {
console.log('mno');
};
foo();
bar();
baz();
bark();
hawk();
function foo (bar) {
eval('console.log(bar);');
}
foo(1);
})();
`,
{