Browse Source

obfuscation of eval call expressions WIP

sanex3339 7 years ago
parent
commit
07c7414420

File diff suppressed because it is too large
+ 0 - 0
dist/index.js


+ 8 - 2
src/JavaScriptObfuscator.ts

@@ -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
src/ObfuscationResult.ts

@@ -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
src/container/InversifyContainerFacade.ts

@@ -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 - 0
src/container/modules/node-transformers/ConvertingTransformersModule.ts

@@ -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 - 0
src/enums/node-transformers/NodeTransformer.ts

@@ -1,5 +1,6 @@
 export enum NodeTransformer {
     BlockStatementControlFlowTransformer,
+    CallExpressionTransformer,
     ClassDeclarationTransformer,
     CommentsTransformer,
     DeadCodeInjectionTransformer,

+ 7 - 0
src/interfaces/IObfuscationResult.d.ts

@@ -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
src/interfaces/source-map/ISourceMapCorrector.d.ts

@@ -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;
 }

+ 84 - 0
src/node-transformers/converting-transformers/CallExpressionTransformer.ts

@@ -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
src/source-map/SourceMapCorrector.ts

@@ -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
src/types/container/TObfuscationResultFactory.d.ts

@@ -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
test/dev/dev.ts

@@ -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);
         })();
         `,
         {

Some files were not shown because too many files changed in this diff