Exemplo n.º 1
0
        public CfgManipulator(IModule module, PeReader.DefaultHost host, Log.Log logger, MethodCfg methodCfg) {
            this.host = host;
            this.logger = logger;
            this.module = module;

            this.methodCfg = methodCfg;
        }
Exemplo n.º 2
0
        // adds a nop instruction after every instruction in the given method cfg
        public void addNopsToCfg(MethodCfg methodCfg) {

            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                List<IOperation> newOperations = new List<IOperation>();
                for (int idx = 0; idx < tempBB.operations.Count(); idx++) {

                    IOperation currentOperation = tempBB.operations.ElementAt(idx);

                    // copy current operation to new operations list
                    newOperations.Add(currentOperation);

                    if (idx == tempBB.operations.Count() - 1) {
                        break;
                    }

                    // ignore all prefixes (because nop after prefix will crash the program)
                    if (currentOperation.OperationCode == OperationCode.No_
                        || currentOperation.OperationCode == OperationCode.Constrained_
                        || currentOperation.OperationCode == OperationCode.Readonly_
                        || currentOperation.OperationCode == OperationCode.Tail_
                        || currentOperation.OperationCode == OperationCode.Unaligned_
                        || currentOperation.OperationCode == OperationCode.Volatile_) {
                        continue;
                    }

                    InternalOperation newNopOperation = new InternalOperation();
                    newNopOperation.OperationCode = OperationCode.Nop;

                    // add nop operation after current one
                    newOperations.Add(newNopOperation);

                }

                // replace old operations with new ones
                tempBB.operations = newOperations;

            }

        }
Exemplo n.º 3
0
        public GraphRandomStateGenerator(IModule module, PeReader.DefaultHost host, Log.Log logger, CfgManipulator cfgManipulator, Helper helperClass, Graph.Graph graph, MethodCfg methodCfg, bool debugging) {

            this.module = module;
            this.host = host;
            this.logger = logger;
            this.cfgManipulator = cfgManipulator;            
            this.helperClass = helperClass;
            this.graph = graph;
            this.methodCfg = methodCfg;
            this.debugging = debugging;

            // add local random generator variable
            this.tempRandomLocal = new LocalDefinition();
            this.tempRandomLocal.IsReference = false;
            this.tempRandomLocal.IsPinned = false;
            this.tempRandomLocal.IsModified = false;
            this.tempRandomLocal.Type = this.helperClass.systemRandom;
            this.tempRandomLocal.MethodDefinition = methodCfg.method;
            cfgManipulator.addLocalVariable(this.tempRandomLocal);


        }
Exemplo n.º 4
0
        // build recursively the cfg of the given operations
        private void buildRecursivelyCfg(MethodCfg methodCfg, IEnumerable<IOperation> operations, int currentIdx, IBranchTarget entryBranch, ref BasicBlock currentBasicBlock) {

            // check if a new basic block has to be created
            for (int bbIdx = 0; bbIdx < methodCfg.basicBlocks.Count(); bbIdx++) {

                // check if the current index points into an existing basic block
                // => split basic block
                BasicBlock tempBB = methodCfg.basicBlocks.ElementAt(bbIdx);
                if (tempBB.startIdx < currentIdx && tempBB.endIdx >= currentIdx) {

                    // create new basic block which will be the second half of the found one
                    BasicBlock newBasicBlock = new BasicBlock(this.semanticId);
                    this.semanticId++;
                    newBasicBlock.startIdx = currentIdx;
                    newBasicBlock.endIdx = tempBB.endIdx;
                    tempBB.endIdx = currentIdx - 1;

                    // move the exit basic blocks to the new created basic block
                    // and make the new created basic block the exit of the splitted one                    
                    newBasicBlock.exitBranch = tempBB.exitBranch;
                    newBasicBlock.exitBranch.sourceBasicBlock = newBasicBlock;
                    NoBranchTarget tempExitBranch = new NoBranchTarget();
                    tempExitBranch.takenTarget = newBasicBlock;
                    tempExitBranch.sourceBasicBlock = tempBB;
                    tempBB.exitBranch = tempExitBranch;

                    // set the current basic block to the new created basic block
                    currentBasicBlock = newBasicBlock;

                    // add splitted basic block branch and basic block branch that leads to this split
                    // to the entries of the new one
                    newBasicBlock.entryBranches.Add(entryBranch);
                    newBasicBlock.entryBranches.Add(tempExitBranch);

                    // distribute the instructions to the basic blocks 
                    List<IOperation> previousOperations = new List<IOperation>();
                    List<IOperation> nextOperations = new List<IOperation>();
                    for (int operationIdx = 0; (operationIdx + tempBB.startIdx) <= newBasicBlock.endIdx; operationIdx++) {

                        if ((operationIdx + tempBB.startIdx) < currentIdx) {
                            previousOperations.Add(tempBB.operations.ElementAt(operationIdx));
                        }
                        else {
                            nextOperations.Add(tempBB.operations.ElementAt(operationIdx));
                        }
                    }
                    tempBB.operations = previousOperations;
                    newBasicBlock.operations = nextOperations;

                    // add new basic block to the cfg
                    methodCfg.basicBlocks.Add(newBasicBlock);

                    return;
                }

                // if the current index of the operation points to the start index of an existing basic block
                // => update entry branches
                else if (tempBB.startIdx == currentIdx && entryBranch != null && currentBasicBlock != null) {
                    tempBB.entryBranches.Add(entryBranch);

                    // set the found basic block as the current basic block
                    currentBasicBlock = tempBB;
                    return;
                }

                // if the current index of the operation points to the start index of an existing basic block, has no entry branch
                // and is not the first instruction
                // set the current basic block to the found one
                else if (currentIdx != 0 && tempBB.startIdx == currentIdx && currentBasicBlock != null) {

                    // set the found basic block as the current basic block
                    currentBasicBlock = tempBB;
                    return;

                }

            }

            // set index of current basic block and add it to the cfg
            currentBasicBlock.startIdx = currentIdx;
            methodCfg.basicBlocks.Add(currentBasicBlock);

            // check if the basic block was jumped to from another basic block
            // => update entry branches
            if (entryBranch != null) {
                currentBasicBlock.entryBranches.Add(entryBranch);
            }

            // parse every instruction to find branches etc
            for (int idx = currentIdx; idx < operations.Count(); idx++) {

                // check if the current instruction is the start instruction of an already existing basic block (except the current basic block)
                // => add the current basic block to the list of entry basic blocks, the found basic block to the list of exit basic blocks and set the index
                for (int bbIdx = 0; bbIdx < methodCfg.basicBlocks.Count(); bbIdx++) {
                    BasicBlock tempBB = methodCfg.basicBlocks.ElementAt(bbIdx);
                    if (tempBB.startIdx == idx && tempBB != currentBasicBlock) {
                        currentBasicBlock.endIdx = idx - 1;

                        // create new exit branch and add it
                        NoBranchTarget currentExitBranch = new NoBranchTarget();
                        currentExitBranch.sourceBasicBlock = currentBasicBlock;
                        currentExitBranch.takenTarget = tempBB;
                        currentBasicBlock.exitBranch = currentExitBranch;

                        // add current exit branch as entry for the found one
                        tempBB.entryBranches.Add(currentExitBranch);
                        return;
                    }
                }

                // add current instruction to the basic block
                var operation = operations.ElementAt(idx);
                currentBasicBlock.operations.Add(operation);

                // check for special instructions like branches
                switch (operation.OperationCode) {

                    // conditional branch instructions
                    case OperationCode.Beq:
                    case OperationCode.Bge:
                    case OperationCode.Bge_Un:
                    case OperationCode.Bgt:
                    case OperationCode.Bgt_Un:
                    case OperationCode.Ble:
                    case OperationCode.Ble_Un:
                    case OperationCode.Blt:
                    case OperationCode.Blt_Un:
                    case OperationCode.Bne_Un:
                    case OperationCode.Brfalse:
                    case OperationCode.Brtrue:
                    case OperationCode.Beq_S:
                    case OperationCode.Bge_S:
                    case OperationCode.Bge_Un_S:
                    case OperationCode.Bgt_S:
                    case OperationCode.Bgt_Un_S:
                    case OperationCode.Ble_S:
                    case OperationCode.Ble_Un_S:
                    case OperationCode.Blt_S:
                    case OperationCode.Blt_Un_S:
                    case OperationCode.Bne_Un_S:
                    case OperationCode.Brfalse_S:
                    case OperationCode.Brtrue_S: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // calculate the target index of the branch
                            int branchTargetIdx = 0;
                            uint branchTargetOffset;

                            // do operation value can be of type long which can not be casted in this way
                            if (operation.Value is long) {
                                branchTargetOffset = Convert.ToUInt32(operation.Value);
                            }
                            else {
                                branchTargetOffset = (uint)operation.Value;
                            }

                            while (true) {
                                if (operations.ElementAt(branchTargetIdx).Offset == branchTargetOffset) {
                                    break;
                                }
                                else if (operations.ElementAt(branchTargetIdx).Offset > branchTargetOffset) {
                                    throw new ArgumentException("Could not find target off branch.");
                                }
                                branchTargetIdx++;
                            }

                            // create new exit branch object
                            ConditionalBranchTarget currentExitBranch = new ConditionalBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentExitBranch.notTakenTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentExitBranch.takenTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // start two new basic blocks from this branch on and end current execution
                            this.buildRecursivelyCfg(methodCfg, operations, idx + 1, currentExitBranch, ref currentExitBranch.notTakenTarget);
                            this.buildRecursivelyCfg(methodCfg, operations, branchTargetIdx, currentExitBranch, ref currentExitBranch.takenTarget);
                            return;
                        }

                    // unconditional branch instructions
                    case OperationCode.Br:
                    case OperationCode.Br_S: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // calculate the target index of the branch
                            int branchTargetIdx = 0;
                            uint branchTargetOffset = (uint)operation.Value;
                            while (true) {
                                if (operations.ElementAt(branchTargetIdx).Offset == branchTargetOffset) {
                                    break;
                                }
                                else if (operations.ElementAt(branchTargetIdx).Offset > branchTargetOffset) {
                                    throw new ArgumentException("Could not find target off branch.");
                                }
                                branchTargetIdx++;
                            }

                            // create new exit branch object
                            UnconditionalBranchTarget currentExitBranch = new UnconditionalBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentExitBranch.takenTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // start one new basic block from this branch on and end current execution
                            this.buildRecursivelyCfg(methodCfg, operations, branchTargetIdx, currentExitBranch, ref currentExitBranch.takenTarget);
                            return;
                        }

                    // exit operation
                    case OperationCode.Ret: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // create new exit branch object
                            ExitBranchTarget currentExitBranch = new ExitBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // end current execution
                            return;
                        }

                    // operations that exit the current function/control flow
                    case OperationCode.Throw: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // create new exit branch object
                            ThrowBranchTarget currentExitBranch = new ThrowBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // start a new basic block if this was not the last instruction of the method
                            // (needed because some control flows that are reached via throw are not found without it) 
                            if ((idx + 1) < operations.Count()) {
                                BasicBlock newStartBasicBlock = new BasicBlock(this.semanticId);
                                this.semanticId++;
                                this.buildRecursivelyCfg(methodCfg, operations, idx + 1, null, ref newStartBasicBlock);
                            }

                            // end current execution
                            return;
                        }

                    // switch instruction (has a variable set of jump targets)
                    case OperationCode.Switch: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // create new exit branch object
                            SwitchBranchTarget currentExitBranch = new SwitchBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentExitBranch.notTakenTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // calculate the target index of all switch branches
                            int counter = 0;
                            foreach (uint branchTargetOffset in (uint[])operation.Value) {
                                int branchTargetIdx = 0;
                                while (true) {
                                    if (operations.ElementAt(branchTargetIdx).Offset == branchTargetOffset) {
                                        break;
                                    }
                                    else if (operations.ElementAt(branchTargetIdx).Offset > branchTargetOffset) {
                                        throw new ArgumentException("Could not find target off branch.");
                                    }
                                    branchTargetIdx++;
                                }

                                // start a new basic block from this branch on
                                BasicBlock tempNextBasicBlock = new BasicBlock(this.semanticId);
                                this.semanticId++;
                                this.buildRecursivelyCfg(methodCfg, operations, branchTargetIdx, currentExitBranch, ref tempNextBasicBlock);

                                // add new basic block to branch targets
                                currentExitBranch.takenTarget.Add(tempNextBasicBlock);

                                counter++;
                            }

                            // start a new basic block directly after the switch instruction and end current execution
                            this.buildRecursivelyCfg(methodCfg, operations, idx + 1, currentExitBranch, ref currentExitBranch.notTakenTarget);

                            return;
                        }

                    // exception handler beginning or end (end of try block or catch block)
                    case OperationCode.Leave:
                    case OperationCode.Leave_S: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // calculate the target index of the branch
                            int branchTargetIdx = 0;
                            uint branchTargetOffset = (uint)operation.Value;
                            while (true) {
                                if (operations.ElementAt(branchTargetIdx).Offset == branchTargetOffset) {
                                    break;
                                }
                                else if (operations.ElementAt(branchTargetIdx).Offset > branchTargetOffset) {
                                    throw new ArgumentException("Could not find target off branch.");
                                }
                                branchTargetIdx++;
                            }

                            // create new exit branch object
                            ExceptionBranchTarget currentExitBranch = new ExceptionBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentExitBranch.exceptionTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentExitBranch.exitTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // start two new basic blocks from this branch on and end current execution
                            this.buildRecursivelyCfg(methodCfg, operations, idx + 1, currentExitBranch, ref currentExitBranch.exceptionTarget);
                            this.buildRecursivelyCfg(methodCfg, operations, branchTargetIdx, currentExitBranch, ref currentExitBranch.exitTarget);
                            return;
                        }

                    // create a virtual basic block at the end of a catch/finally handler
                    case OperationCode.Rethrow:
                    case OperationCode.Endfinally: {

                            // the current basic block ends here
                            currentBasicBlock.endIdx = idx;

                            // create new exit branch object
                            NoBranchTarget currentExitBranch = new NoBranchTarget();
                            currentExitBranch.sourceBasicBlock = currentBasicBlock;
                            currentExitBranch.takenTarget = new BasicBlock(this.semanticId);
                            this.semanticId++;
                            currentBasicBlock.exitBranch = currentExitBranch;

                            // start a new basic block from this branch on and end current execution
                            this.buildRecursivelyCfg(methodCfg, operations, idx + 1, currentExitBranch, ref currentExitBranch.takenTarget);

                            return;
                        }


                    default:
                        break;
                }
            }
        }
Exemplo n.º 5
0
        // creates a method for a given method CFG (IMPORTANT: it updates the operations
        // and exception handlers of the existing method, does not create a new method)
        public void createMethodFromCfg(MethodCfg methodCfg) {

            // list of basic blocks that belong together logically (i.e. BB2 lies directly behind BB1 because it reaches it without a branch)
            IList<BasicBlockUnion> basicBlockUnions = new List<BasicBlockUnion>();

            // first step: create basic block unions
            // create first basic block union starting from the start basic block
            BasicBlockUnion firstBasicBlockUnion = new BasicBlockUnion();
            this.createRecursivelyBasicBlockUnion(basicBlockUnions, firstBasicBlockUnion, methodCfg.startBasicBlock);
            basicBlockUnions.Add(firstBasicBlockUnion);

            // create basic block unions for the rest of the basic blocks
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                // create a basic block union (if basic block is not contained by another existing basic block union)
                BasicBlockUnion basicBlockUnion = new BasicBlockUnion();
                this.createRecursivelyBasicBlockUnion(basicBlockUnions, basicBlockUnion, tempBB);

                // if the newly created basic block union contains basic blocks
                // => add to list of basic block unions
                if (basicBlockUnion.basicBlocks.Count() != 0) {
                    basicBlockUnions.Add(basicBlockUnion);
                }
            }


            // step two: merge basic block unions with respect to the exception handler
            foreach (OperationExceptionInformation exceptionHandler in methodCfg.method.Body.OperationExceptionInformation) {

                // create a temporary object to reorder the basic block unions with respect to the exception handler
                BasicBlockUnionExceptionHandlerOrder tempNewOrder = new BasicBlockUnionExceptionHandlerOrder();
                tempNewOrder.exceptionHandler = exceptionHandler;

                // find all basic blocks that are connected to the current exception handler
                foreach (BasicBlockUnion basicBlockUnion in basicBlockUnions) {
                    foreach (BasicBlock basicBlock in basicBlockUnion.basicBlocks) {

                        // ignore all basic blocks that do not have any try/catch/finally handler in it
                        if (basicBlock.tryBlocks.Count() == 0 && basicBlock.handlerBlocks.Count() == 0) {
                            continue;
                        }

                        // find the try block that is connected to the current exception handler
                        foreach (TryBlock tryBlock in basicBlock.tryBlocks) {

                            // ignore try blocks that do not belong to the current exception handler
                            if (tryBlock.exceptionHandler != exceptionHandler) {
                                continue;
                            }

                            // check if basic block union already resides in try body
                            // if not => add to try body
                            if (!tempNewOrder.tryBody.Contains(basicBlockUnion)) {
                                tempNewOrder.tryBody.Add(basicBlockUnion);
                            }

                            // check if the basic block starts the try block
                            if (tryBlock.firstBasicBlockOfTryBlock) {
                                tempNewOrder.tryStart = basicBlockUnion;
                            }

                            // check if the basic block ends the try block
                            if (tryBlock.lastBasicBlockOfTryBlock) {
                                tempNewOrder.tryEnd = basicBlockUnion;
                            }
                        }

                        // find the handler block that is connected to the current exception handler
                        foreach (HandlerBlock handlerBlock in basicBlock.handlerBlocks) {

                            // ignore handler blocks that do not belong to the current exception handler
                            if (handlerBlock.exceptionHandler != exceptionHandler) {
                                continue;
                            }

                            // check if basic block union already resides in handler body
                            // if not => add to handler body
                            if (!tempNewOrder.handlerBody.Contains(basicBlockUnion)) {
                                tempNewOrder.handlerBody.Add(basicBlockUnion);
                            }

                            // check if the basic block starts the handler block
                            if (handlerBlock.firstBasicBlockOfHandlerBlock) {
                                tempNewOrder.handlerStart = basicBlockUnion;
                            }

                            // check if the basic block ends the handler block
                            if (handlerBlock.lastBasicBlockOfHandlerBlock) {
                                tempNewOrder.handlerEnd = basicBlockUnion;
                            }
                        }
                    }
                }
                if (tempNewOrder.tryStart == null
                    || tempNewOrder.tryEnd == null
                    || tempNewOrder.handlerStart == null
                    || tempNewOrder.handlerEnd == null) {
                        throw new ArgumentException("Could not find all try/catch beginnings/ends.");
                }



                // merge basic block unions with respect to the current exception handler

                // check if the complete exception handling is done in only one basic block union
                // => ignore it
                if (tempNewOrder.tryStart == tempNewOrder.tryEnd
                    && tempNewOrder.handlerStart == tempNewOrder.handlerEnd
                    && tempNewOrder.tryStart == tempNewOrder.handlerStart) {
                    continue;
                }

                // if not everything lies in the same basic block union
                // extend the basic block union that starts the try block
                BasicBlockUnion extendedUnion = tempNewOrder.tryStart;

                // if try block start and end are the same => nothing to merge
                // else merge the basic block unions
                if (tempNewOrder.tryStart != tempNewOrder.tryEnd) {
                    foreach (BasicBlockUnion tryBodyBasicBlockUnion in tempNewOrder.tryBody) {

                        // ignore the basic block union that starts the try block (already in extended union)
                        // and ignore the basic block union that ends the try block (is added last)
                        if (tryBodyBasicBlockUnion == tempNewOrder.tryStart
                            || tryBodyBasicBlockUnion == tempNewOrder.tryEnd) {
                            continue;
                        }

                        // extend first basic block union with the basic block union of the
                        // try block body and remove the added one from the list of basic block unions
                        extendedUnion.basicBlocks.AddRange(tryBodyBasicBlockUnion.basicBlocks);
                        basicBlockUnions.Remove(tryBodyBasicBlockUnion);
                    }

                    // extend first basic block union with the basic block union of the
                    // try block end and remove the added one from the list of basic block unions
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.tryEnd.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.tryEnd);
                }

                // if the try block end and the handler block start are not the same basic block union
                // => merge the union of the handler block start to the current basic block union
                if (tempNewOrder.tryEnd != tempNewOrder.handlerStart) {
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.handlerStart.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.handlerStart);
                }

                // if handler block start and end are the same => nothing to merge
                // else merge the basic block unions
                if (tempNewOrder.handlerStart != tempNewOrder.handlerEnd) {
                    foreach (BasicBlockUnion handlerBodyBasicBlockUnion in tempNewOrder.handlerBody) {

                        // ignore the basic block union that starts the handler block (already in extended union)
                        // and ignore the basic block union that ends the handler block (is added last)
                        if (handlerBodyBasicBlockUnion == tempNewOrder.handlerStart
                            || handlerBodyBasicBlockUnion == tempNewOrder.handlerEnd) {
                            continue;
                        }

                        // add basic block union of the handler block body to the extended basic block union 
                        // and remove the added one from the list of basic block unions
                        extendedUnion.basicBlocks.AddRange(handlerBodyBasicBlockUnion.basicBlocks);
                        basicBlockUnions.Remove(handlerBodyBasicBlockUnion);
                    }

                    // extend the extended basic block union with the basic block union of the
                    // handler block end and remove the added one from the list of basic block unions
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.handlerEnd.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.handlerEnd);
                }
            }


            // step three: create one list of operations and modify jump offsets
            // create a list of operations from the basic blocks,
            // update basic block start/end indices accordingly
            // and update the offsets of the operations (needed to update branch operations)
            IList<IOperation> methodOperations = new List<IOperation>();
            int operationIdx = 0;
            uint currentOffset = 0;
            foreach (BasicBlockUnion basicBlockUnion in basicBlockUnions) {
                foreach (BasicBlock basicBlock in basicBlockUnion.basicBlocks) {
                    basicBlock.startIdx = operationIdx;
                    //foreach (IOperation operation in basicBlock.operations) {
                    for (int opIdx = 0; opIdx < basicBlock.operations.Count(); opIdx++) {
                        IOperation operation = basicBlock.operations.ElementAt(opIdx);

                        // a new operation object is needed because the old operations
                        // are read only due to cci
                        InternalOperation newOperation = new InternalOperation();

                        // exchange every short instruction with its larger one
                        switch (operation.OperationCode) {
                            case OperationCode.Beq_S:
                                newOperation.OperationCode = OperationCode.Beq;
                                break;
                            case OperationCode.Bge_S:
                                newOperation.OperationCode = OperationCode.Bge;
                                break;
                            case OperationCode.Bge_Un_S:
                                newOperation.OperationCode = OperationCode.Bge_Un;
                                break;
                            case OperationCode.Bgt_S:
                                newOperation.OperationCode = OperationCode.Bgt;
                                break;
                            case OperationCode.Bgt_Un_S:
                                newOperation.OperationCode = OperationCode.Bgt_Un;
                                break;
                            case OperationCode.Ble_S:
                                newOperation.OperationCode = OperationCode.Ble;
                                break;
                            case OperationCode.Ble_Un_S:
                                newOperation.OperationCode = OperationCode.Ble_Un;
                                break;
                            case OperationCode.Blt_S:
                                newOperation.OperationCode = OperationCode.Blt;
                                break;
                            case OperationCode.Blt_Un_S:
                                newOperation.OperationCode = OperationCode.Blt_Un;
                                break;
                            case OperationCode.Bne_Un_S:
                                newOperation.OperationCode = OperationCode.Bne_Un;
                                break;
                            case OperationCode.Br_S:
                                newOperation.OperationCode = OperationCode.Br;
                                break;
                            case OperationCode.Brfalse_S:
                                newOperation.OperationCode = OperationCode.Brfalse;
                                break;
                            case OperationCode.Brtrue_S:
                                newOperation.OperationCode = OperationCode.Brtrue;
                                break;
                            case OperationCode.Ldarg_S:
                                newOperation.OperationCode = OperationCode.Ldarg;
                                break;
                            case OperationCode.Ldarga_S:
                                newOperation.OperationCode = OperationCode.Ldarga;
                                break;
                            case OperationCode.Ldc_I4_S:
                                newOperation.OperationCode = OperationCode.Ldc_I4;
                                break;
                            case OperationCode.Ldloc_S:
                                newOperation.OperationCode = OperationCode.Ldloc;
                                break;
                            case OperationCode.Ldloca_S:
                                newOperation.OperationCode = OperationCode.Ldloca;
                                break;
                            case OperationCode.Leave_S:
                                newOperation.OperationCode = OperationCode.Leave;
                                break;
                            case OperationCode.Starg_S:
                                newOperation.OperationCode = OperationCode.Starg;
                                break;
                            case OperationCode.Stloc_S:
                                newOperation.OperationCode = OperationCode.Stloc;
                                break;
                            default:
                                newOperation.OperationCode = operation.OperationCode;
                                break;
                        }
                        newOperation.Value = operation.Value;
                        newOperation.Location = operation.Location;
                        newOperation.Offset = currentOffset;
                        methodOperations.Add(newOperation);

                        // replace old operation in basic block with newly created one
                        basicBlock.operations[opIdx] = newOperation;

                        operationIdx++;
                        currentOffset += CfgBuilder.getSizeOfOperation(newOperation);
                    }
                    basicBlock.endIdx = operationIdx - 1;
                }
            }


            // step four: update branches with new target offsets
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {
                InternalOperation branchOperation = (InternalOperation)methodOperations.ElementAt(tempBB.endIdx);

                // check which kind of exit branch is used by this basic block and update its operation accordingly
                if (tempBB.exitBranch as NoBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as TryBlockTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ConditionalBranchTarget != null) {
                    ConditionalBranchTarget tempExitBranch = (tempBB.exitBranch as ConditionalBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.takenTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else if (tempBB.exitBranch as SwitchBranchTarget != null) {
                    SwitchBranchTarget tempExitBranch = (tempBB.exitBranch as SwitchBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // update all switch branches
                    for (int switchIdx = 0; switchIdx < tempExitBranch.takenTarget.Count(); switchIdx++) {

                        // get index of the branch target
                        int targetBranchIdx = tempExitBranch.takenTarget.ElementAt(switchIdx).startIdx;

                        // update offset of the taken branch
                        ((uint[])branchOperation.Value)[switchIdx] = methodOperations.ElementAt(targetBranchIdx).Offset;
                    }
                }
                else if (tempBB.exitBranch as UnconditionalBranchTarget != null) {
                    UnconditionalBranchTarget tempExitBranch = (tempBB.exitBranch as UnconditionalBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.takenTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else if (tempBB.exitBranch as ExitBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ThrowBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ExceptionBranchTarget != null) {
                    ExceptionBranchTarget tempExitBranch = (tempBB.exitBranch as ExceptionBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.exitTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else {
                    throw new ArgumentException("Do not know how to handle exit branch.");
                }
            }


            // step five: create new exception handler with updated offsets and
            // create new method body of the cci method
            MethodDefinition method = methodCfg.method;
            var ilGenerator = new ILGenerator(this.host, method);
            // emit all operations to the new body
            foreach (IOperation operation in methodOperations) {
                ilGenerator.Emit(operation.OperationCode, operation.Value);
            }

            // list that is used to replace the pointer to the old exception handler in the basic blocks to the new exception handler
            List<OldExceptionHandlerMapping> oldExceptionHandlerMappings = new List<OldExceptionHandlerMapping>();
            
            // create for each old exception handler a new one with updated data
            foreach (IOperationExceptionInformation exceptionHandler in method.Body.OperationExceptionInformation) {

                // create mapping object for old exception handler
                OldExceptionHandlerMapping oldExceptionHandlerMapping = new OldExceptionHandlerMapping();
                oldExceptionHandlerMapping.oldExceptionHandler = exceptionHandler;
                oldExceptionHandlerMappings.Add(oldExceptionHandlerMapping);

                ILGeneratorLabel tryStart = new ILGeneratorLabel();
                ILGeneratorLabel tryEnd = new ILGeneratorLabel();
                ILGeneratorLabel handlerStart = new ILGeneratorLabel();
                ILGeneratorLabel handlerEnd = new ILGeneratorLabel();
                ILGeneratorLabel filterStart = new ILGeneratorLabel();

                // search for the basic blocks that start/end the try block and handler block
                foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                    foreach (TryBlock tempTryBlock in tempBB.tryBlocks) {

                        // ignore try blocks that do not belong to the current exception handler
                        if (tempTryBlock.exceptionHandler != exceptionHandler) {
                            continue;
                        }

                        // get offset of the instruction that starts the try block
                        if (tempTryBlock.firstBasicBlockOfTryBlock) {
                            tryStart.Offset = tempBB.operations.ElementAt(0).Offset;
                            oldExceptionHandlerMapping.tryStartOffset = tryStart.Offset;
                        }

                        // get offset of the instruction that ends the try block (always the last instruction of the basic block)
                        if (tempTryBlock.lastBasicBlockOfTryBlock) {
                            tryEnd.Offset = tempBB.operations.ElementAt(tempBB.operations.Count() - 1).Offset;
                            // exception handler object needs offset of the end of the instruction (not the beginning)
                            tryEnd.Offset += CfgBuilder.getSizeOfOperation(tempBB.operations.ElementAt(tempBB.operations.Count() - 1));
                            oldExceptionHandlerMapping.tryEndOffset = tryEnd.Offset;
                        }
                    }

                    foreach (HandlerBlock tempHandlerBlock in tempBB.handlerBlocks) {

                        // ignore handler blocks that do not belong to the current exception handler
                        if (tempHandlerBlock.exceptionHandler != exceptionHandler) {
                            continue;
                        }

                        // get offset ot the instruction that starts the handler block
                        if (tempHandlerBlock.firstBasicBlockOfHandlerBlock) {
                            handlerStart.Offset = tempBB.operations.ElementAt(0).Offset;
                            oldExceptionHandlerMapping.handlerStartOffset = handlerStart.Offset;
                        }

                        // get offset of the instruction that ends the handler block
                        if (tempHandlerBlock.lastBasicBlockOfHandlerBlock) {
                            handlerEnd.Offset = tempBB.operations.ElementAt(tempBB.operations.Count() - 1).Offset;
                            // exception handler object needs offset of the end of the instruction (not the beginning)
                            handlerEnd.Offset += CfgBuilder.getSizeOfOperation(tempBB.operations.ElementAt(tempBB.operations.Count() - 1));
                            oldExceptionHandlerMapping.handlerEndOffset = handlerEnd.Offset;
                        }
                    }
                }

                // copy the exception handler filter
                filterStart.Offset = exceptionHandler.FilterDecisionStartOffset;
                oldExceptionHandlerMapping.filterStartOffset = filterStart.Offset;

                // add new exception handler
                oldExceptionHandlerMapping.exceptionType = exceptionHandler.ExceptionType;
                oldExceptionHandlerMapping.handlerKind = exceptionHandler.HandlerKind;
                ilGenerator.AddExceptionHandlerInformation(exceptionHandler.HandlerKind, exceptionHandler.ExceptionType, tryStart, tryEnd, handlerStart, handlerEnd, filterStart);
            }

            // create the body
            List<ILocalDefinition> variableListCopy = new List<ILocalDefinition>(method.Body.LocalVariables);
            List<ITypeDefinition> privateHelperTypesListCopy = new List<ITypeDefinition>(method.Body.PrivateHelperTypes);
            var newBody = new ILGeneratorMethodBody(ilGenerator, method.Body.LocalsAreZeroed, 8, method, variableListCopy, privateHelperTypesListCopy); // TODO dynamic max stack size?
            method.Body = newBody;


            // step six: replace pointer to the old exception handler with the new exception handler

            // map all old exception handler to the new objects
            foreach (IOperationExceptionInformation exceptionHandler in method.Body.OperationExceptionInformation) {

                // search for the new exception handler object to get the mapping to the old one
                bool found = false;
                foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                    if (oldExceptionHandlerMapping.exceptionType == exceptionHandler.ExceptionType
                        && oldExceptionHandlerMapping.handlerKind == exceptionHandler.HandlerKind
                        && oldExceptionHandlerMapping.filterStartOffset == exceptionHandler.FilterDecisionStartOffset
                        && oldExceptionHandlerMapping.tryStartOffset == exceptionHandler.TryStartOffset
                        && oldExceptionHandlerMapping.tryEndOffset == exceptionHandler.TryEndOffset
                        && oldExceptionHandlerMapping.handlerStartOffset == exceptionHandler.HandlerStartOffset
                        && oldExceptionHandlerMapping.handlerEndOffset == exceptionHandler.HandlerEndOffset) {
                        oldExceptionHandlerMapping.newExceptionHandler = exceptionHandler;
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    throw new ArgumentException("Not able to map old exception handler to new one.");
                }
            }

            // replace all old exception handler in the basic blocks with the new exception handler
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                // replace all exception handler in the try blocks
                foreach (TryBlock tryBlock in tempBB.tryBlocks) {
                    foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                        if (tryBlock.exceptionHandler == oldExceptionHandlerMapping.oldExceptionHandler) {
                            tryBlock.exceptionHandler = oldExceptionHandlerMapping.newExceptionHandler;
                            break;
                        }
                    }
                }

                // replace all exception handler in the handler blocks
                foreach (HandlerBlock handlerBlock in tempBB.handlerBlocks) {
                    foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                        if (handlerBlock.exceptionHandler == oldExceptionHandlerMapping.oldExceptionHandler) {
                            handlerBlock.exceptionHandler = oldExceptionHandlerMapping.newExceptionHandler;
                            break;
                        }
                    }
                }
            }

            
            // TODO
            // DEBUG
            /*
            // sanitize method name to store it as a file
            String invalidChars = System.Text.RegularExpressions.Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars()));
            String invalidRegStr = string.Format(@"([{0}]*\.+$)|([{0}]+)", invalidChars);
            String fileName = System.Text.RegularExpressions.Regex.Replace(methodCfg.method.ToString(), invalidRegStr, "_");
            fileName = fileName.Length >= 230 ? fileName.Substring(0, 230) : fileName;

            // dump cfg created from the exit branches
            System.IO.StreamWriter dotFile = new System.IO.StreamWriter("e:\\" + "\\BBUnion_" + fileName + ".dot");

            // start .dot file graph
            dotFile.WriteLine("digraph G {");

            for (int bbuidx = 0; bbuidx < basicBlockUnions.Count(); bbuidx++) {
                BasicBlockUnion basicBlockUnion = basicBlockUnions.ElementAt(bbuidx);
                    // write all basic blocks to .dot file
                    for (int idx = 0; idx < basicBlockUnion.basicBlocks.Count(); idx++) {

                        BasicBlock currentBasicBlock = basicBlockUnion.basicBlocks.ElementAt(idx);

                        // write the current basic block to the file and all its instructions
                        dotFile.WriteLine("BB" + bbuidx.ToString() + "_" + idx.ToString() + " [shape=record]");
                        bool first = true;
                        for (int opIdx = 0; opIdx < currentBasicBlock.operations.Count(); opIdx++) {
                            var operation = currentBasicBlock.operations.ElementAt(opIdx);
                            if (first) {
                                dotFile.Write("BB" + bbuidx.ToString() + "_" + idx.ToString() + " [label=\"{");
                                first = false;
                            }
                            else {
                                dotFile.Write("|");
                            }

                            // insert try block beginnings
                            foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                                if (tryBlock.firstBasicBlockOfTryBlock && opIdx == 0) {
                                    dotFile.Write("TRY START (" + tryBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                }
                            }

                            // insert catch block beginnings
                            foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                                if (handlerBlock.firstBasicBlockOfHandlerBlock && opIdx == 0) {
                                    if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                        dotFile.Write("CATCH START (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                    }
                                    else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                        dotFile.Write("FINALLY START (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                    }
                                    else {
                                        throw new ArgumentException("Do not know how to handle handler.");
                                    }
                                }
                            }

                            // check if instruction has an argument
                            if (operation.Value != null) {
                                dotFile.Write(operation.OperationCode.ToString() + " " + operation.Value.ToString());
                            }
                            else {
                                dotFile.Write(operation.OperationCode.ToString());
                            }

                            // insert try block endings
                            foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                                if (tryBlock.lastBasicBlockOfTryBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                                    dotFile.Write("|TRY END (" + tryBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                }
                            }

                            // insert catch block endings
                            foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                                if (handlerBlock.lastBasicBlockOfHandlerBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                                    if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                        dotFile.Write("|CATCH END (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                    }
                                    else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                        dotFile.Write("|FINALLY END (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                    }
                                    else {
                                        throw new ArgumentException("Do not know how to handle handler.");
                                    }
                                }
                            }
                        }
                        dotFile.WriteLine("}\"]");


                        if ((idx + 1) < basicBlockUnion.basicBlocks.Count()) {
                            dotFile.WriteLine("BB" + bbuidx.ToString() + "_" + idx.ToString() + " -> BB" + bbuidx.ToString() + "_" + (idx + 1).ToString() + "[ color=\"blue\" ]");
                        }

                    }
                }


            // finish graph
            dotFile.WriteLine("}");

            dotFile.Close();
            */
        }
Exemplo n.º 6
0
        // this constructor copies the given source method cfg and all its elements
        // NOTE: it ignores the transformation metadata
        public MethodCfg(MethodCfg sourceMethodCfg) {

            // copy link to the method
            this.method = sourceMethodCfg.method;

            // generate a list of already processed basic blocks
            List<BasicBlock> processedBasicBlocks = new List<BasicBlock>();

            // set start basic block of the CFG as already processed
            processedBasicBlocks.Add(sourceMethodCfg.startBasicBlock);

            // create copy of start basic block
            BasicBlock copiedStartBasicBlock = new BasicBlock();
            this.startBasicBlock = copiedStartBasicBlock;
            this.basicBlocks.Add(copiedStartBasicBlock);

            // copy simple values
            copiedStartBasicBlock.id = sourceMethodCfg.startBasicBlock.id;
            copiedStartBasicBlock.semanticId = sourceMethodCfg.startBasicBlock.semanticId;
            copiedStartBasicBlock.startIdx = sourceMethodCfg.startBasicBlock.startIdx;
            copiedStartBasicBlock.endIdx = sourceMethodCfg.startBasicBlock.endIdx;

            // copy all operations of the basic block
            foreach (IOperation operation in sourceMethodCfg.startBasicBlock.operations) {
                InternalOperation copiedOperation = new InternalOperation();
                copiedOperation.OperationCode = operation.OperationCode;
                copiedOperation.Value = operation.Value;
                copiedOperation.Offset = operation.Offset;
                copiedOperation.Location = operation.Location;
                copiedStartBasicBlock.operations.Add(copiedOperation);
            }


            // process rest of the cfg and copy the exit branch
            if ((sourceMethodCfg.startBasicBlock.exitBranch as NoBranchTarget) != null) {
                NoBranchTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as NoBranchTarget);

                // create a copied exit branch
                NoBranchTarget copiedExitBranch = new NoBranchTarget();
                copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock;
                copiedStartBasicBlock.exitBranch = copiedExitBranch;

                // process branch and next basic block
                BasicBlock nextCopiedBasicBlock = null;
                this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch);

            }

            else if (sourceMethodCfg.startBasicBlock.exitBranch as UnconditionalBranchTarget != null) {
                UnconditionalBranchTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as UnconditionalBranchTarget);

                // create a copied exit branch
                UnconditionalBranchTarget copiedExitBranch = new UnconditionalBranchTarget();
                copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock;
                copiedStartBasicBlock.exitBranch = copiedExitBranch;

                // process branch and next basic block
                BasicBlock nextCopiedBasicBlock = null;
                this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch);

            }

            else if (sourceMethodCfg.startBasicBlock.exitBranch as ConditionalBranchTarget != null) {
                ConditionalBranchTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as ConditionalBranchTarget);

                // create a copied exit branch
                ConditionalBranchTarget copiedExitBranch = new ConditionalBranchTarget();
                copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock;
                copiedStartBasicBlock.exitBranch = copiedExitBranch;

                // process branch and next basic block
                BasicBlock nextCopiedBasicBlock = null;
                this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch, true);

                // process branch and next basic block
                nextCopiedBasicBlock = null;
                this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.notTakenTarget, ref nextCopiedBasicBlock, copiedExitBranch, false);

            }

            else if (sourceMethodCfg.startBasicBlock.exitBranch as SwitchBranchTarget != null) {
                SwitchBranchTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as SwitchBranchTarget);

                // create a copied exit branch
                SwitchBranchTarget copiedExitBranch = new SwitchBranchTarget();
                copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock;
                copiedStartBasicBlock.exitBranch = copiedExitBranch;

                // first process not taken branch and next basic block
                BasicBlock nextCopiedBasicBlock = null;
                this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.notTakenTarget, ref nextCopiedBasicBlock, copiedExitBranch, -1);

                // process all taken branches and next basic blocks
                for (int idx = 0; idx < exitBranch.takenTarget.Count(); idx++) {
                    nextCopiedBasicBlock = null;
                    this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget.ElementAt(idx), ref nextCopiedBasicBlock, copiedExitBranch, idx);
                }

            }

            else if (sourceMethodCfg.startBasicBlock.exitBranch as ExitBranchTarget != null) {

                // create a copied exit branch
                ExitBranchTarget copiedExitBranch = new ExitBranchTarget();
                copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock;
                copiedStartBasicBlock.exitBranch = copiedExitBranch;

            }

            else if (sourceMethodCfg.startBasicBlock.exitBranch as ThrowBranchTarget != null) {

                // create a copied exit branch
                ThrowBranchTarget copiedExitBranch = new ThrowBranchTarget();
                copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock;
                copiedStartBasicBlock.exitBranch = copiedExitBranch;

            }

            else if (sourceMethodCfg.startBasicBlock.exitBranch as TryBlockTarget != null) {
                TryBlockTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as TryBlockTarget);

                // create a copied exit branch
                TryBlockTarget copiedExitBranch = new TryBlockTarget();
                copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock;
                copiedStartBasicBlock.exitBranch = copiedExitBranch;

                // process branch and next basic block
                BasicBlock nextCopiedBasicBlock = null;
                this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.takenTarget, ref nextCopiedBasicBlock, copiedExitBranch);

            }

            else if (sourceMethodCfg.startBasicBlock.exitBranch as ExceptionBranchTarget != null) {
                ExceptionBranchTarget exitBranch = (sourceMethodCfg.startBasicBlock.exitBranch as ExceptionBranchTarget);

                // create a copied exit branch
                ExceptionBranchTarget copiedExitBranch = new ExceptionBranchTarget();
                copiedExitBranch.sourceBasicBlock = copiedStartBasicBlock;
                copiedStartBasicBlock.exitBranch = copiedExitBranch;

                // process branch and next basic block
                BasicBlock nextCopiedBasicBlock = null;
                this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.exceptionTarget, ref nextCopiedBasicBlock, copiedExitBranch, true);

                // process branch and next basic block
                nextCopiedBasicBlock = null;
                this.copyMethodCfgRecursively(processedBasicBlocks, exitBranch.exitTarget, ref nextCopiedBasicBlock, copiedExitBranch, false);

            }

            else {
                throw new ArgumentException("Do not know how to handle exit branch.");
            }


            // copy all try blocks
            foreach (TryBlock sourceTryBlock in sourceMethodCfg.startBasicBlock.tryBlocks) {

                TryBlock copiedTryBlock = new TryBlock();
                copiedTryBlock.exceptionHandler = sourceTryBlock.exceptionHandler;
                copiedTryBlock.firstBasicBlockOfTryBlock = sourceTryBlock.firstBasicBlockOfTryBlock;
                copiedTryBlock.lastBasicBlockOfTryBlock = sourceTryBlock.lastBasicBlockOfTryBlock;

                copiedStartBasicBlock.tryBlocks.Add(copiedTryBlock);
            }


            // copy all handler blocks
            foreach (HandlerBlock sourceHandlerBlock in sourceMethodCfg.startBasicBlock.handlerBlocks) {

                HandlerBlock copiedHandlerBlock = new HandlerBlock();
                copiedHandlerBlock.exceptionHandler = sourceHandlerBlock.exceptionHandler;
                copiedHandlerBlock.typeOfHandler = sourceHandlerBlock.typeOfHandler;
                copiedHandlerBlock.firstBasicBlockOfHandlerBlock = sourceHandlerBlock.firstBasicBlockOfHandlerBlock;
                copiedHandlerBlock.lastBasicBlockOfHandlerBlock = sourceHandlerBlock.lastBasicBlockOfHandlerBlock;

                copiedStartBasicBlock.handlerBlocks.Add(copiedHandlerBlock);
            }

        }
Exemplo n.º 7
0
        public CodeGenerator(IModule module, PeReader.DefaultHost host, Log.Log logger, Random prng, MethodCfg methodCfg,
            bool debugging=false, CfgManipulator manipulator=null)
        {
            this.host = host;
            this.logger = logger;
            this.module = module;
            this.prng = prng;
            this.methodCfg = methodCfg;
            this.debugging = debugging;
            this.manipulator = manipulator;

            callableMethods = retrieveCallableMethods();
        }
Exemplo n.º 8
0
        public CodeMutator(IModule module, PeReader.DefaultHost host, Log.Log logger, Random prng, MethodCfg methodCfg,
            CfgManipulator manipulator, bool debugging=false)
        {
            this.host = host;
            this.logger = logger;
            this.module = module;
            this.prng = prng;
            this.methodCfg = methodCfg;
            this.debugging = debugging;
            this.manipulator = manipulator;

            returnBlock = new BasicBlock();
            var exitBranch = new ExitBranchTarget();

            returnBlock.exitBranch = exitBranch;
            returnBlock.operations.Add(createNewOperation(OperationCode.Ret));

            methodCfg.basicBlocks.Add(returnBlock);
        }
Exemplo n.º 9
0
        // this function injects an opaque predicate to the target branch
        private void injectOpaquePredicateCode(CfgManipulator cfgManipulator, MethodCfg methodCfg, BasicBlock targetBasicBlock, IBranchTarget targetBranch, BasicBlockGraphNodeLink link, int opaquePredicate, LocalDefinition currentNodeLocal) {

            int currentValidPathId = link.validPathId;
            ConditionalBranchTarget opaqueExitBranch = null;

            // create "true" or "false" opaque predicate and add it to the code
            switch (opaquePredicate) {

                // "true" opaque predicate
                case 0: {
                        BasicBlock opaqueStartBasicBlock = null;

                        this.createCodeTruePredicate(ref opaqueStartBasicBlock, ref opaqueExitBranch, link, currentNodeLocal);

                        // inject target branch with opaque predicate
                        if ((targetBranch as SwitchBranchTarget) != null) {
                            SwitchBranchTarget tempTargetBranch = (targetBranch as SwitchBranchTarget);
                            cfgManipulator.insertBasicBlockBetweenBranch(tempTargetBranch, currentValidPathId, opaqueStartBasicBlock, opaqueExitBranch, true);
                        }
                        else if ((targetBranch as UnconditionalBranchTarget) != null) {
                            UnconditionalBranchTarget tempTargetBranch = (targetBranch as UnconditionalBranchTarget);
                            cfgManipulator.insertBasicBlockBetweenBranch(tempTargetBranch, opaqueStartBasicBlock, opaqueExitBranch, true);
                        }
                        else {
                            throw new ArgumentException("Not implemented yet.");
                        }

                        // set template semantic id of dead code basic block
                        BasicBlock deadCodeBasicBlock = opaqueExitBranch.notTakenTarget;
                        GraphTransformerDeadCodeBasicBlock deadCodeMetadata = (deadCodeBasicBlock.transformationMetadata.ElementAt(0) as GraphTransformerDeadCodeBasicBlock);
                        deadCodeMetadata.semanticId = targetBasicBlock.semanticId;

                        // create intermediate basic block and inject it between correct opaque predicate branch and target basic block
                        BasicBlock intermediateBasicBlock = new BasicBlock();
                        intermediateBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Br, 0));
                        methodCfg.basicBlocks.Add(intermediateBasicBlock);

                        // add metadata to intermediate basic block
                        GraphTransformerIntermediateBasicBlock metadataIntermediate = new GraphTransformerIntermediateBasicBlock();
                        metadataIntermediate.correspondingGraphNodes.Add(link);
                        intermediateBasicBlock.transformationMetadata.Add(metadataIntermediate);

                        // create intermediate exit branch
                        UnconditionalBranchTarget intermediateBasicBlockExitBranch = new UnconditionalBranchTarget();
                        intermediateBasicBlockExitBranch.sourceBasicBlock = intermediateBasicBlock;
                        intermediateBasicBlock.exitBranch = intermediateBasicBlockExitBranch;

                        cfgManipulator.insertBasicBlockBetweenBranch(opaqueExitBranch, true, intermediateBasicBlock, intermediateBasicBlockExitBranch);

                        break;
                    }

                // "false" opaque predicate
                case 1: {
                        BasicBlock opaqueStartBasicBlock = null;

                        this.createCodeFalsePredicate(ref opaqueStartBasicBlock, ref opaqueExitBranch, link, currentNodeLocal);

                        // inject target branch with opaque predicate
                        if ((targetBranch as SwitchBranchTarget) != null) {
                            SwitchBranchTarget tempTargetBranch = (targetBranch as SwitchBranchTarget);
                            cfgManipulator.insertBasicBlockBetweenBranch(tempTargetBranch, currentValidPathId, opaqueStartBasicBlock, opaqueExitBranch, false);
                        }
                        else if ((targetBranch as UnconditionalBranchTarget) != null) {
                            UnconditionalBranchTarget tempTargetBranch = (targetBranch as UnconditionalBranchTarget);
                            cfgManipulator.insertBasicBlockBetweenBranch(tempTargetBranch, opaqueStartBasicBlock, opaqueExitBranch, false);
                        }
                        else {
                            throw new ArgumentException("Not implemented yet.");
                        }

                        // set template semantic id of dead code basic block
                        BasicBlock deadCodeBasicBlock = opaqueExitBranch.takenTarget;
                        GraphTransformerDeadCodeBasicBlock deadCodeMetadata = (deadCodeBasicBlock.transformationMetadata.ElementAt(0) as GraphTransformerDeadCodeBasicBlock);
                        deadCodeMetadata.semanticId = targetBasicBlock.semanticId;

                        // create intermediate basic block and inject it between correct opaque predicate branch and target basic block
                        BasicBlock intermediateBasicBlock = new BasicBlock();
                        intermediateBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Br, 0));
                        methodCfg.basicBlocks.Add(intermediateBasicBlock);

                        // add metadata to intermediate basic block
                        GraphTransformerIntermediateBasicBlock metadataIntermediate = new GraphTransformerIntermediateBasicBlock();
                        metadataIntermediate.correspondingGraphNodes.Add(link);
                        intermediateBasicBlock.transformationMetadata.Add(metadataIntermediate);

                        // create intermediate exit branch
                        UnconditionalBranchTarget intermediateBasicBlockExitBranch = new UnconditionalBranchTarget();
                        intermediateBasicBlockExitBranch.sourceBasicBlock = intermediateBasicBlock;
                        intermediateBasicBlock.exitBranch = intermediateBasicBlockExitBranch;

                        cfgManipulator.insertBasicBlockBetweenBranch(opaqueExitBranch, false, intermediateBasicBlock, intermediateBasicBlockExitBranch);

                        break;
                    }

                // "Random" opaque predicate.
                case 2: {
                        BasicBlock opaqueStartBasicBlock = null;

                        if ((targetBranch as SwitchBranchTarget) != null) {
                            SwitchBranchTarget tempTargetBranch = (targetBranch as SwitchBranchTarget);
                            var destinationBlock = tempTargetBranch.takenTarget[currentValidPathId];

                            this.createCodeRandomPredicate(ref opaqueStartBasicBlock, ref opaqueExitBranch, link, currentNodeLocal);

                            bool chooseBranch = prng.Next(1) == 0;
                            cfgManipulator.insertBasicBlockBetweenBranch(tempTargetBranch, currentValidPathId, opaqueStartBasicBlock, opaqueExitBranch, chooseBranch);
                        }
                        else {
                            throw new ArgumentException("Not implemented yet.");
                        }
                        break;
                    }

                default:
                    throw new ArgumentException("This case should never be reached.");
            }

        }
Exemplo n.º 10
0
        private void processExitBranchesIter(CfgManipulator cfgManipulator, GraphRandomStateGenerator randomStateGenerator, MethodCfg originalMethodCfg, MethodCfg methodCfg, BasicBlock startBasicBlock, LocalDefinition intStateLocal, LocalDefinition currentNodeLocal) {

            int currentValidPathId;

            // create a list of basic blocks that still have to be processed by the algorithm
            List<BasicBlock> basicBlocksToProcess = new List<BasicBlock>(methodCfg.basicBlocks);

            System.Console.WriteLine("Basic Blocks to process (Control Flow): " + basicBlocksToProcess.Count());

            while (true) {

                List<BasicBlock> copiedList = new List<BasicBlock>(basicBlocksToProcess);
                foreach (BasicBlock currentBasicBlock in copiedList) {

                    // get the metadata for the current basic block
                    GraphTransformerMetadataBasicBlock metadata = null;
                    for (int i = 0; i < currentBasicBlock.transformationMetadata.Count(); i++) {
                        // get graph transformer metadata for basic blocks
                        if ((currentBasicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock) == null) {
                            continue;
                        }
                        metadata = (currentBasicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock);
                        break;
                    }
                    if (metadata == null) {
                        throw new ArgumentException("Not able to find metadata for current basic block.");
                    }

                    // remove currently processed basic block from the list of basic blocks to process
                    basicBlocksToProcess.Remove(currentBasicBlock);

                    // check if the current exit branch is of type "no branch target"
                    if (currentBasicBlock.exitBranch as NoBranchTarget != null) {

                        NoBranchTarget introBranch = (NoBranchTarget)currentBasicBlock.exitBranch;

                        // search for all semantically equal basic blocks in the modified method CFG (as possible targets)
                        int searchSementicId = introBranch.takenTarget.semanticId;
                        List<BasicBlock> possibleTargetBasicBlocks = new List<BasicBlock>();
                        if (searchSementicId != -1) {
                            foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                                if (searchBasicBlock.semanticId == searchSementicId) {
                                    possibleTargetBasicBlocks.Add(searchBasicBlock);
                                }
                            }
                            if (possibleTargetBasicBlocks.Count() == 0) {
                                throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                            }
                        }
                        else {
                            possibleTargetBasicBlocks.Add(introBranch.takenTarget);
                        }

                        // create a list of target basic blocks of this branch
                        List<Target> listOfTargets = new List<Target>();
                        Target target = new Target();
                        target.basicBlock = introBranch.takenTarget;
                        listOfTargets.Add(target);

                        // generate code for the "state switch"
                        BasicBlock stateBasicBlock = null;
                        SwitchBranchTarget stateExitBranch = null;
                        this.createCodeStateSwitch(ref stateBasicBlock, ref stateExitBranch, intStateLocal, metadata.correspondingGraphNodes);
                        cfgManipulator.insertBasicBlockBetweenBranch(introBranch, stateBasicBlock, stateExitBranch, 0);

                        // create for each valid path a branch in the switch statement of the "state switch"
                        for (currentValidPathId = 0; currentValidPathId < this.graph.graphValidPathCount; currentValidPathId++) {

                            // ignore first valid path (with id 0)
                            // => add artificial branch to original branch target (for the current valid path id)
                            if (currentValidPathId != 0) {

                                // fill switch taken branch list with null when index is out of range
                                while (stateExitBranch.takenTarget.Count() <= currentValidPathId) {
                                    stateExitBranch.takenTarget.Add(null);
                                }

                                // randomly chose what the target of the current branch should be (weight to use an existing basic block to have less memory consumption)
                                switch (this.prng.Next(this.duplicateBasicBlockWeight)) {
                                    case 0:
                                    case 1:
                                    case 2:
                                    case 3:
                                    case 4:
                                    case 5: {

                                            // duplicate the target basic block
                                            BasicBlock duplicatedBasicBlock = this.duplicateBasicBlock(originalMethodCfg, methodCfg, listOfTargets.ElementAt(0).basicBlock);
                                            methodCfg.basicBlocks.Add(duplicatedBasicBlock);
                                            basicBlocksToProcess.Add(duplicatedBasicBlock);

                                            // add new basic block as target of the switch case
                                            stateExitBranch.takenTarget[currentValidPathId] = duplicatedBasicBlock;
                                            duplicatedBasicBlock.entryBranches.Add(stateExitBranch);

                                            // add new basic block to the list of target basic blocks
                                            target = new Target();
                                            target.basicBlock = duplicatedBasicBlock;
                                            listOfTargets.Add(target);

                                            // add duplicated basic block to the list of possible target basic blocks
                                            possibleTargetBasicBlocks.Add(duplicatedBasicBlock);

                                            // create metadata for the newly created basic block
                                            if (!createAndAddMetadata(duplicatedBasicBlock)) {
                                                throw new ArgumentException("Creating metadata for the duplicated basic block failed.");
                                            }

                                            break;

                                        }
                                    default: {

                                            // use a random possible basic block as target
                                            int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                                            BasicBlock newTarget = possibleTargetBasicBlocks.ElementAt(randPosition);

                                            target = new Target();
                                            target.basicBlock = newTarget;
                                            listOfTargets.Add(target);

                                            // set switch taken branch for current valid path id to the chosen branch target
                                            stateExitBranch.takenTarget[currentValidPathId] = target.basicBlock;
                                            target.basicBlock.entryBranches.Add(stateExitBranch);

                                            break;

                                        }

                                }

                            }

                            // set current valid path id of the target
                            target.currentValidPathId = currentValidPathId;

                            // get the link from the current basic block to the obfuscation graph
                            BasicBlockGraphNodeLink currentGraphLink = null;
                            foreach (BasicBlockGraphNodeLink tempLink in metadata.correspondingGraphNodes) {
                                if (tempLink.validPathId == currentValidPathId) {
                                    currentGraphLink = tempLink;
                                    break;
                                }
                            }
                            if (currentGraphLink == null) {
                                throw new ArgumentNullException("Could not find link from current basic block to the graph for the given path id.");
                            }

                            // get the metadata for the target basic block
                            GraphTransformerMetadataBasicBlock targetMetadata = null;
                            for (int i = 0; i < target.basicBlock.transformationMetadata.Count(); i++) {
                                // get graph transformer metadata for basic blocks
                                if ((target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock) == null) {
                                    continue;
                                }
                                targetMetadata = (target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock);
                                break;
                            }
                            if (targetMetadata == null) {
                                throw new ArgumentException("Not able to find metadata for target basic block.");
                            }

                            // get the link from the target basic block to the obfuscation graph
                            BasicBlockGraphNodeLink targetGraphLink = null;
                            foreach (BasicBlockGraphNodeLink tempLink in targetMetadata.correspondingGraphNodes) {
                                if (tempLink.validPathId == currentValidPathId) {
                                    targetGraphLink = tempLink;
                                    break;
                                }
                            }
                            if (targetGraphLink == null) {
                                throw new ArgumentNullException("Could not find link from target basic block to the graph for the given path id.");
                            }

                            // choose randomly to either just correct the pointer position or to inject a "state change"
                            switch (this.prng.Next(this.stateChangeWeight)) {

                                // case: "state change"
                                case 0:
                                case 1:
                                case 2:
                                case 3:
                                case 4:
                                case 5: {

                                        // generate code for the "state change"
                                        BasicBlock stateChangeBasicBlock = null;
                                        SwitchBranchTarget stateChangeExitBranch = null;
                                        this.createCodeStateChange(ref stateChangeBasicBlock, ref stateChangeExitBranch, randomStateGenerator, currentGraphLink, intStateLocal); 
                                        cfgManipulator.insertBasicBlockBetweenBranch(stateExitBranch, currentValidPathId, stateChangeBasicBlock, stateChangeExitBranch, 0);

                                        // create for each valid path a branch in the switch statement of the "state change"
                                        for (int changedCurrentValidPathId = 0; changedCurrentValidPathId < this.graph.graphValidPathCount; changedCurrentValidPathId++) {

                                            // ignore first valid path (with id 0)
                                            // => add artificial branch to original branch target (for the changed current valid path id)
                                            if (changedCurrentValidPathId != 0) {

                                                // fill switch taken branch list with null when index is out of range
                                                while (stateChangeExitBranch.takenTarget.Count() <= changedCurrentValidPathId) {
                                                    stateChangeExitBranch.takenTarget.Add(null);
                                                }

                                                // randomly chose what the target of the current branch should be (weight to use an existing basic block to have less memory consumption)
                                                switch (this.prng.Next(this.duplicateBasicBlockWeight)) {
                                                    case 0:
                                                    case 1:
                                                    case 2:
                                                    case 3:
                                                    case 4:
                                                    case 5: {

                                                            // duplicate the target basic block
                                                            BasicBlock duplicatedBasicBlock = this.duplicateBasicBlock(originalMethodCfg, methodCfg, listOfTargets.ElementAt(0).basicBlock);
                                                            methodCfg.basicBlocks.Add(duplicatedBasicBlock);
                                                            basicBlocksToProcess.Add(duplicatedBasicBlock);

                                                            // add new basic block as target of the switch case
                                                            stateChangeExitBranch.takenTarget[changedCurrentValidPathId] = duplicatedBasicBlock;
                                                            duplicatedBasicBlock.entryBranches.Add(stateChangeExitBranch);

                                                            // add new basic block to the list of target basic blocks
                                                            target = new Target();
                                                            target.basicBlock = duplicatedBasicBlock;
                                                            listOfTargets.Add(target);

                                                            // add duplicated basic block to the list of possible target basic blocks
                                                            possibleTargetBasicBlocks.Add(duplicatedBasicBlock);

                                                            // create metadata for the newly created basic block
                                                            if (!createAndAddMetadata(duplicatedBasicBlock)) {
                                                                throw new ArgumentException("Creating metadata for the duplicated basic block failed.");
                                                            }

                                                            break;

                                                        }
                                                    default: {

                                                            // use a random possible basic block as target
                                                            int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                                                            BasicBlock newTarget = possibleTargetBasicBlocks.ElementAt(randPosition);

                                                            target = new Target();
                                                            target.basicBlock = newTarget;
                                                            listOfTargets.Add(target);

                                                            // set switch taken branch for current valid path id to the chosen branch target
                                                            stateChangeExitBranch.takenTarget[changedCurrentValidPathId] = target.basicBlock;
                                                            target.basicBlock.entryBranches.Add(stateChangeExitBranch);

                                                            break;

                                                        }
                                                }

                                            }

                                            // set current valid path id of the target
                                            target.currentValidPathId = changedCurrentValidPathId;

                                            // get the metadata for the change target basic block
                                            GraphTransformerMetadataBasicBlock changeTargetMetadata = null;
                                            for (int i = 0; i < target.basicBlock.transformationMetadata.Count(); i++) {
                                                // get graph transformer metadata for basic blocks
                                                if ((target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock) == null) {
                                                    continue;
                                                }
                                                changeTargetMetadata = (target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock);
                                                break;
                                            }
                                            if (changeTargetMetadata == null) {
                                                throw new ArgumentException("Not able to find metadata for target basic block.");
                                            }

                                            // get the link from the change target basic block to the obfuscation graph
                                            BasicBlockGraphNodeLink changeTargetGraphLink = null;
                                            foreach (BasicBlockGraphNodeLink tempLink in changeTargetMetadata.correspondingGraphNodes) {
                                                if (tempLink.validPathId == changedCurrentValidPathId) {
                                                    changeTargetGraphLink = tempLink;
                                                    break;
                                                }
                                            }
                                            if (changeTargetGraphLink == null) {
                                                throw new ArgumentNullException("Could not find link from target basic block to the graph for the given path id.");
                                            }

                                            // correct the pointer position to the obfuscation graph
                                            this.injectLinkMoveCode(cfgManipulator, currentGraphLink, changeTargetGraphLink, stateChangeExitBranch, changedCurrentValidPathId, currentNodeLocal);

                                            // if debugging is activated => dump method cfg and add code to dump current graph
                                            if (this.debugging) {
                                                List<IOperation> debugOperations = new List<IOperation>();
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingNumber.ToString().PadLeft(3, '0') + "_" + target.basicBlock.id.ToString() + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method)));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.debuggingDumpGraphMethod));
                                                target.basicBlock.operations.InsertRange(0, debugOperations);

                                                //this.logger.dumpMethodCfg(methodCfg, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method));
                                                this.debuggingNumber++;
                                            }

                                        }

                                        break;
                                    }

                                // case: correct pointer position
                                default: {

                                        this.injectLinkMoveCode(cfgManipulator, currentGraphLink, targetGraphLink, stateExitBranch, currentGraphLink.validPathId, currentNodeLocal);

                                        // if debugging is activated => dump method cfg and add code to dump current graph
                                        if (this.debugging) {
                                            List<IOperation> debugOperations = new List<IOperation>();
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingNumber.ToString().PadLeft(3, '0') + "_" + target.basicBlock.id.ToString() + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method)));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.debuggingDumpGraphMethod));
                                            target.basicBlock.operations.InsertRange(0, debugOperations);

                                            //this.logger.dumpMethodCfg(methodCfg, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method));
                                            this.debuggingNumber++;
                                        }

                                        break;
                                    }
                            }
                        }

                    }

                    // check if the current exit branch is of type "unconditional branch target"
                    else if (currentBasicBlock.exitBranch as UnconditionalBranchTarget != null) {

                        UnconditionalBranchTarget introBranch = (UnconditionalBranchTarget)currentBasicBlock.exitBranch;

                        // search for all semantically equal basic blocks in the modified method CFG (as possible targets)
                        int searchSementicId = introBranch.takenTarget.semanticId;
                        List<BasicBlock> possibleTargetBasicBlocks = new List<BasicBlock>();
                        if (searchSementicId != -1) {
                            foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                                if (searchBasicBlock.semanticId == searchSementicId) {
                                    possibleTargetBasicBlocks.Add(searchBasicBlock);
                                }
                            }
                            if (possibleTargetBasicBlocks.Count() == 0) {
                                throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                            }
                        }
                        else {
                            possibleTargetBasicBlocks.Add(introBranch.takenTarget);
                        }

                        // create a list of target basic blocks of this branch
                        List<Target> listOfTargets = new List<Target>();
                        Target target = new Target();
                        target.basicBlock = introBranch.takenTarget;
                        listOfTargets.Add(target);

                        // generate code for the "state switch"
                        BasicBlock stateBasicBlock = null;
                        SwitchBranchTarget stateExitBranch = null;
                        this.createCodeStateSwitch(ref stateBasicBlock, ref stateExitBranch, intStateLocal, metadata.correspondingGraphNodes);
                        cfgManipulator.insertBasicBlockBetweenBranch(introBranch, stateBasicBlock, stateExitBranch, 0);

                        // create for each valid path a branch in the switch statement of the "state switch"
                        for (currentValidPathId = 0; currentValidPathId < this.graph.graphValidPathCount; currentValidPathId++) {

                            // ignore first valid path (with id 0)
                            // => add artificial branch to original branch target (for the current valid path id)
                            if (currentValidPathId != 0) {

                                // fill switch taken branch list with null when index is out of range
                                while (stateExitBranch.takenTarget.Count() <= currentValidPathId) {
                                    stateExitBranch.takenTarget.Add(null);
                                }

                                // randomly chose what the target of the current branch should be (weight to use an existing basic block to have less memory consumption)
                                switch (this.prng.Next(this.duplicateBasicBlockWeight)) {
                                    case 0:
                                    case 1:
                                    case 2:
                                    case 3:
                                    case 4:
                                    case 5: {

                                            // duplicate the target basic block
                                            BasicBlock duplicatedBasicBlock = this.duplicateBasicBlock(originalMethodCfg, methodCfg, listOfTargets.ElementAt(0).basicBlock);
                                            methodCfg.basicBlocks.Add(duplicatedBasicBlock);
                                            basicBlocksToProcess.Add(duplicatedBasicBlock);

                                            // add new basic block as target of the switch case
                                            stateExitBranch.takenTarget[currentValidPathId] = duplicatedBasicBlock;
                                            duplicatedBasicBlock.entryBranches.Add(stateExitBranch);

                                            // add new basic block to the list of target basic blocks
                                            target = new Target();
                                            target.basicBlock = duplicatedBasicBlock;
                                            listOfTargets.Add(target);

                                            // add duplicated basic block to the list of possible target basic blocks
                                            possibleTargetBasicBlocks.Add(duplicatedBasicBlock);

                                            // create metadata for the newly created basic block
                                            if (!createAndAddMetadata(duplicatedBasicBlock)) {
                                                throw new ArgumentException("Creating metadata for the duplicated basic block failed.");
                                            }

                                            break;

                                        }
                                    default: {

                                            // use a random possible basic block as target
                                            int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                                            BasicBlock newTarget = possibleTargetBasicBlocks.ElementAt(randPosition);

                                            target = new Target();
                                            target.basicBlock = newTarget;
                                            listOfTargets.Add(target);

                                            //set switch taken branch for current valid path id to the chosen branch target
                                            stateExitBranch.takenTarget[currentValidPathId] = target.basicBlock;
                                            target.basicBlock.entryBranches.Add(stateExitBranch);

                                            break;

                                        }

                                }

                            }

                            // set current valid path id of the target
                            target.currentValidPathId = currentValidPathId;

                            // get the link from the current basic block to the obfuscation graph
                            BasicBlockGraphNodeLink currentGraphLink = null;
                            foreach (BasicBlockGraphNodeLink tempLink in metadata.correspondingGraphNodes) {
                                if (tempLink.validPathId == currentValidPathId) {
                                    currentGraphLink = tempLink;
                                    break;
                                }
                            }
                            if (currentGraphLink == null) {
                                throw new ArgumentNullException("Could not find link from current basic block to the graph for the given path id.");
                            }

                            // get the metadata for the target basic block
                            GraphTransformerMetadataBasicBlock targetMetadata = null;
                            for (int i = 0; i < target.basicBlock.transformationMetadata.Count(); i++) {
                                // get graph transformer metadata for basic blocks
                                if ((target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock) == null) {
                                    continue;
                                }
                                targetMetadata = (target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock);
                                break;
                            }
                            if (targetMetadata == null) {
                                throw new ArgumentException("Not able to find metadata for target basic block.");
                            }

                            // get the link from the target basic block to the obfuscation graph
                            BasicBlockGraphNodeLink targetGraphLink = null;
                            foreach (BasicBlockGraphNodeLink tempLink in targetMetadata.correspondingGraphNodes) {
                                if (tempLink.validPathId == currentValidPathId) {
                                    targetGraphLink = tempLink;
                                    break;
                                }
                            }
                            if (targetGraphLink == null) {
                                throw new ArgumentNullException("Could not find link from target basic block to the graph for the given path id.");
                            }

                            // choose randomly to either just correct the pointer position or to inject a "state change"
                            switch (this.prng.Next(this.stateChangeWeight)) {

                                // case: "state change"
                                case 0:
                                case 1:
                                case 2:
                                case 3:
                                case 4:
                                case 5: {

                                        // generate code for the "state change"
                                        BasicBlock stateChangeBasicBlock = null;
                                        SwitchBranchTarget stateChangeExitBranch = null;
                                        this.createCodeStateChange(ref stateChangeBasicBlock, ref stateChangeExitBranch, randomStateGenerator, currentGraphLink, intStateLocal);
                                        cfgManipulator.insertBasicBlockBetweenBranch(stateExitBranch, currentValidPathId, stateChangeBasicBlock, stateChangeExitBranch, 0);

                                        // create for each valid path a branch in the switch statement of the "state change"
                                        for (int changedCurrentValidPathId = 0; changedCurrentValidPathId < this.graph.graphValidPathCount; changedCurrentValidPathId++) {

                                            // ignore first valid path (with id 0)
                                            // => add artificial branch to original branch target (for the changed current valid path id)
                                            if (changedCurrentValidPathId != 0) {

                                                // fill switch taken branch list with null when index is out of range
                                                while (stateChangeExitBranch.takenTarget.Count() <= changedCurrentValidPathId) {
                                                    stateChangeExitBranch.takenTarget.Add(null);
                                                }

                                                // randomly chose what the target of the current branch should be (weight to use an existing basic block to have less memory consumption)
                                                switch (this.prng.Next(this.duplicateBasicBlockWeight)) {
                                                    case 0:
                                                    case 1:
                                                    case 2:
                                                    case 3:
                                                    case 4:
                                                    case 5: {

                                                            // duplicate the target basic block
                                                            BasicBlock duplicatedBasicBlock = this.duplicateBasicBlock(originalMethodCfg, methodCfg, listOfTargets.ElementAt(0).basicBlock);
                                                            methodCfg.basicBlocks.Add(duplicatedBasicBlock);
                                                            basicBlocksToProcess.Add(duplicatedBasicBlock);

                                                            // add new basic block as target of the switch case
                                                            stateChangeExitBranch.takenTarget[changedCurrentValidPathId] = duplicatedBasicBlock;
                                                            duplicatedBasicBlock.entryBranches.Add(stateChangeExitBranch);

                                                            // add new basic block to the list of target basic blocks
                                                            target = new Target();
                                                            target.basicBlock = duplicatedBasicBlock;
                                                            listOfTargets.Add(target);

                                                            // add duplicated basic block to the list of possible target basic blocks
                                                            possibleTargetBasicBlocks.Add(duplicatedBasicBlock);

                                                            // create metadata for the newly created basic block
                                                            if (!createAndAddMetadata(duplicatedBasicBlock)) {
                                                                throw new ArgumentException("Creating metadata for the duplicated basic block failed.");
                                                            }

                                                            break;

                                                        }
                                                    default: {

                                                            // use a random possible basic block as target
                                                            int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                                                            BasicBlock newTarget = possibleTargetBasicBlocks.ElementAt(randPosition);

                                                            target = new Target();
                                                            target.basicBlock = newTarget;
                                                            listOfTargets.Add(target);

                                                            // set switch taken branch for current valid path id to the chosen branch target
                                                            stateChangeExitBranch.takenTarget[changedCurrentValidPathId] = target.basicBlock;
                                                            target.basicBlock.entryBranches.Add(stateChangeExitBranch);

                                                            break;

                                                        }
                                                }

                                            }

                                            // set current valid path id of the target
                                            target.currentValidPathId = changedCurrentValidPathId;

                                            // get the metadata for the change target basic block
                                            GraphTransformerMetadataBasicBlock changeTargetMetadata = null;
                                            for (int i = 0; i < target.basicBlock.transformationMetadata.Count(); i++) {
                                                // get graph transformer metadata for basic blocks
                                                if ((target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock) == null) {
                                                    continue;
                                                }
                                                changeTargetMetadata = (target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock);
                                                break;
                                            }
                                            if (changeTargetMetadata == null) {
                                                throw new ArgumentException("Not able to find metadata for target basic block.");
                                            }

                                            // get the link from the change target basic block to the obfuscation graph
                                            BasicBlockGraphNodeLink changeTargetGraphLink = null;
                                            foreach (BasicBlockGraphNodeLink tempLink in changeTargetMetadata.correspondingGraphNodes) {
                                                if (tempLink.validPathId == changedCurrentValidPathId) {
                                                    changeTargetGraphLink = tempLink;
                                                    break;
                                                }
                                            }
                                            if (changeTargetGraphLink == null) {
                                                throw new ArgumentNullException("Could not find link from target basic block to the graph for the given path id.");
                                            }

                                            // correct the pointer position to the obfuscation graph
                                            this.injectLinkMoveCode(cfgManipulator, currentGraphLink, changeTargetGraphLink, stateChangeExitBranch, changedCurrentValidPathId, currentNodeLocal);

                                            // if debugging is activated => dump method cfg and add code to dump current graph
                                            if (this.debugging) {
                                                List<IOperation> debugOperations = new List<IOperation>();
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingNumber.ToString().PadLeft(3, '0') + "_" + target.basicBlock.id.ToString() + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method)));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.debuggingDumpGraphMethod));
                                                target.basicBlock.operations.InsertRange(0, debugOperations);

                                                //this.logger.dumpMethodCfg(methodCfg, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method));
                                                this.debuggingNumber++;
                                            }

                                        }

                                        break;
                                    }

                                // case: correct pointer position
                                default: {

                                        this.injectLinkMoveCode(cfgManipulator, currentGraphLink, targetGraphLink, stateExitBranch, currentGraphLink.validPathId, currentNodeLocal);

                                        // if debugging is activated => dump method cfg and add code to dump current graph
                                        if (this.debugging) {
                                            List<IOperation> debugOperations = new List<IOperation>();
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingNumber.ToString().PadLeft(3, '0') + "_" + target.basicBlock.id.ToString() + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method)));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.debuggingDumpGraphMethod));
                                            target.basicBlock.operations.InsertRange(0, debugOperations);

                                            //this.logger.dumpMethodCfg(methodCfg, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method));
                                            this.debuggingNumber++;
                                        }

                                        break;
                                    }
                            }
                        }

                    }

                    // check if the current exit branch is of type "conditional branch target"
                    else if (currentBasicBlock.exitBranch as ConditionalBranchTarget != null) {

                        ConditionalBranchTarget introBranch = (ConditionalBranchTarget)currentBasicBlock.exitBranch;

                        // search for all semantically equal basic blocks in the modified method CFG (as possible targets)
                        int searchSementicId = introBranch.takenTarget.semanticId;
                        List<BasicBlock> possibleTargetBasicBlocks = new List<BasicBlock>();
                        if (searchSementicId != -1) {
                            foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                                if (searchBasicBlock.semanticId == searchSementicId) {
                                    possibleTargetBasicBlocks.Add(searchBasicBlock);
                                }
                            }
                            if (possibleTargetBasicBlocks.Count() == 0) {
                                throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                            }
                        }
                        else {
                            possibleTargetBasicBlocks.Add(introBranch.takenTarget);
                        }

                        // create a list of target basic blocks of this branch
                        List<Target> listOfTargets = new List<Target>();
                        Target target = new Target();
                        target.basicBlock = introBranch.takenTarget;
                        listOfTargets.Add(target);

                        // generate code for the "state switch"
                        BasicBlock stateBasicBlock = null;
                        SwitchBranchTarget stateExitBranch = null;
                        this.createCodeStateSwitch(ref stateBasicBlock, ref stateExitBranch, intStateLocal, metadata.correspondingGraphNodes);
                        cfgManipulator.insertBasicBlockBetweenBranch(introBranch, true, stateBasicBlock, stateExitBranch, 0);

                        // create for each valid path a branch in the switch statement of the "state switch"
                        for (currentValidPathId = 0; currentValidPathId < this.graph.graphValidPathCount; currentValidPathId++) {

                            // ignore first valid path (with id 0)
                            // => add artificial branch to original branch target (for the current valid path id)
                            if (currentValidPathId != 0) {

                                // fill switch taken branch list with null when index is out of range
                                while (stateExitBranch.takenTarget.Count() <= currentValidPathId) {
                                    stateExitBranch.takenTarget.Add(null);
                                }

                                // randomly chose what the target of the current branch should be (weight to use an existing basic block to have less memory consumption)
                                switch (this.prng.Next(this.duplicateBasicBlockWeight)) {
                                    case 0:
                                    case 1:
                                    case 2:
                                    case 3:
                                    case 4:
                                    case 5: {

                                            // duplicate the target basic block
                                            BasicBlock duplicatedBasicBlock = this.duplicateBasicBlock(originalMethodCfg, methodCfg, listOfTargets.ElementAt(0).basicBlock);
                                            methodCfg.basicBlocks.Add(duplicatedBasicBlock);
                                            basicBlocksToProcess.Add(duplicatedBasicBlock);

                                            // add new basic block as target of the switch case
                                            stateExitBranch.takenTarget[currentValidPathId] = duplicatedBasicBlock;
                                            duplicatedBasicBlock.entryBranches.Add(stateExitBranch);

                                            // add new basic block to the list of target basic blocks
                                            target = new Target();
                                            target.basicBlock = duplicatedBasicBlock;
                                            listOfTargets.Add(target);

                                            // add duplicated basic block to the list of possible target basic blocks
                                            possibleTargetBasicBlocks.Add(duplicatedBasicBlock);

                                            // create metadata for the newly created basic block
                                            if (!createAndAddMetadata(duplicatedBasicBlock)) {
                                                throw new ArgumentException("Creating metadata for the duplicated basic block failed.");
                                            }

                                            break;

                                        }
                                    default: {

                                            // use a random possible basic block as target
                                            int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                                            BasicBlock newTarget = possibleTargetBasicBlocks.ElementAt(randPosition);

                                            target = new Target();
                                            target.basicBlock = newTarget;
                                            listOfTargets.Add(target);

                                            //set switch taken branch for current valid path id to the chosen branch target
                                            stateExitBranch.takenTarget[currentValidPathId] = target.basicBlock;
                                            target.basicBlock.entryBranches.Add(stateExitBranch);

                                            break;

                                        }

                                }

                            }

                            // set current valid path id of the target
                            target.currentValidPathId = currentValidPathId;

                            // get the link from the current basic block to the obfuscation graph
                            BasicBlockGraphNodeLink currentGraphLink = null;
                            foreach (BasicBlockGraphNodeLink tempLink in metadata.correspondingGraphNodes) {
                                if (tempLink.validPathId == currentValidPathId) {
                                    currentGraphLink = tempLink;
                                    break;
                                }
                            }
                            if (currentGraphLink == null) {
                                throw new ArgumentNullException("Could not find link from current basic block to the graph for the given path id.");
                            }

                            // get the metadata for the target basic block
                            GraphTransformerMetadataBasicBlock targetMetadata = null;
                            for (int i = 0; i < target.basicBlock.transformationMetadata.Count(); i++) {
                                // get graph transformer metadata for basic blocks
                                if ((target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock) == null) {
                                    continue;
                                }
                                targetMetadata = (target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock);
                                break;
                            }
                            if (targetMetadata == null) {
                                throw new ArgumentException("Not able to find metadata for target basic block.");
                            }

                            // get the link from the target basic block to the obfuscation graph
                            BasicBlockGraphNodeLink targetGraphLink = null;
                            foreach (BasicBlockGraphNodeLink tempLink in targetMetadata.correspondingGraphNodes) {
                                if (tempLink.validPathId == currentValidPathId) {
                                    targetGraphLink = tempLink;
                                    break;
                                }
                            }
                            if (targetGraphLink == null) {
                                throw new ArgumentNullException("Could not find link from target basic block to the graph for the given path id.");
                            }

                            // choose randomly to either just correct the pointer position or to inject a "state change"
                            switch (this.prng.Next(this.stateChangeWeight)) {

                                // case: "state change"
                                case 0:
                                case 1:
                                case 2:
                                case 3:
                                case 4:
                                case 5: {

                                        // generate code for the "state change"
                                        BasicBlock stateChangeBasicBlock = null;
                                        SwitchBranchTarget stateChangeExitBranch = null;
                                        this.createCodeStateChange(ref stateChangeBasicBlock, ref stateChangeExitBranch, randomStateGenerator, currentGraphLink, intStateLocal);
                                        cfgManipulator.insertBasicBlockBetweenBranch(stateExitBranch, currentValidPathId, stateChangeBasicBlock, stateChangeExitBranch, 0);

                                        // create for each valid path a branch in the switch statement of the "state change"
                                        for (int changedCurrentValidPathId = 0; changedCurrentValidPathId < this.graph.graphValidPathCount; changedCurrentValidPathId++) {

                                            // ignore first valid path (with id 0)
                                            // => add artificial branch to original branch target (for the changed current valid path id)
                                            if (changedCurrentValidPathId != 0) {

                                                // fill switch taken branch list with null when index is out of range
                                                while (stateChangeExitBranch.takenTarget.Count() <= changedCurrentValidPathId) {
                                                    stateChangeExitBranch.takenTarget.Add(null);
                                                }

                                                // randomly chose what the target of the current branch should be (weight to use an existing basic block to have less memory consumption)
                                                switch (this.prng.Next(this.duplicateBasicBlockWeight)) {
                                                    case 0:
                                                    case 1:
                                                    case 2:
                                                    case 3:
                                                    case 4:
                                                    case 5: {

                                                            // duplicate the target basic block
                                                            BasicBlock duplicatedBasicBlock = this.duplicateBasicBlock(originalMethodCfg, methodCfg, listOfTargets.ElementAt(0).basicBlock);
                                                            methodCfg.basicBlocks.Add(duplicatedBasicBlock);
                                                            basicBlocksToProcess.Add(duplicatedBasicBlock);

                                                            // add new basic block as target of the switch case
                                                            stateChangeExitBranch.takenTarget[changedCurrentValidPathId] = duplicatedBasicBlock;
                                                            duplicatedBasicBlock.entryBranches.Add(stateChangeExitBranch);

                                                            // add new basic block to the list of target basic blocks
                                                            target = new Target();
                                                            target.basicBlock = duplicatedBasicBlock;
                                                            listOfTargets.Add(target);

                                                            // add duplicated basic block to the list of possible target basic blocks
                                                            possibleTargetBasicBlocks.Add(duplicatedBasicBlock);

                                                            // create metadata for the newly created basic block
                                                            if (!createAndAddMetadata(duplicatedBasicBlock)) {
                                                                throw new ArgumentException("Creating metadata for the duplicated basic block failed.");
                                                            }

                                                            break;

                                                        }
                                                    default: {

                                                            // use a random possible basic block as target
                                                            int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                                                            BasicBlock newTarget = possibleTargetBasicBlocks.ElementAt(randPosition);

                                                            target = new Target();
                                                            target.basicBlock = newTarget;
                                                            listOfTargets.Add(target);

                                                            // set switch taken branch for current valid path id to the chosen branch target
                                                            stateChangeExitBranch.takenTarget[changedCurrentValidPathId] = target.basicBlock;
                                                            target.basicBlock.entryBranches.Add(stateChangeExitBranch);

                                                            break;

                                                        }
                                                }

                                            }

                                            // set current valid path id of the target
                                            target.currentValidPathId = changedCurrentValidPathId;

                                            // get the metadata for the change target basic block
                                            GraphTransformerMetadataBasicBlock changeTargetMetadata = null;
                                            for (int i = 0; i < target.basicBlock.transformationMetadata.Count(); i++) {
                                                // get graph transformer metadata for basic blocks
                                                if ((target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock) == null) {
                                                    continue;
                                                }
                                                changeTargetMetadata = (target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock);
                                                break;
                                            }
                                            if (changeTargetMetadata == null) {
                                                throw new ArgumentException("Not able to find metadata for target basic block.");
                                            }

                                            // get the link from the change target basic block to the obfuscation graph
                                            BasicBlockGraphNodeLink changeTargetGraphLink = null;
                                            foreach (BasicBlockGraphNodeLink tempLink in changeTargetMetadata.correspondingGraphNodes) {
                                                if (tempLink.validPathId == changedCurrentValidPathId) {
                                                    changeTargetGraphLink = tempLink;
                                                    break;
                                                }
                                            }
                                            if (changeTargetGraphLink == null) {
                                                throw new ArgumentNullException("Could not find link from target basic block to the graph for the given path id.");
                                            }

                                            // correct the pointer position to the obfuscation graph
                                            this.injectLinkMoveCode(cfgManipulator, currentGraphLink, changeTargetGraphLink, stateChangeExitBranch, changedCurrentValidPathId, currentNodeLocal);

                                            // if debugging is activated => dump method cfg and add code to dump current graph
                                            if (this.debugging) {
                                                List<IOperation> debugOperations = new List<IOperation>();
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingNumber.ToString().PadLeft(3, '0') + "_" + target.basicBlock.id.ToString() + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method)));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.debuggingDumpGraphMethod));
                                                target.basicBlock.operations.InsertRange(0, debugOperations);

                                                //this.logger.dumpMethodCfg(methodCfg, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method));
                                                this.debuggingNumber++;
                                            }

                                        }

                                        break;
                                    }

                                // case: correct pointer position
                                default: {

                                        this.injectLinkMoveCode(cfgManipulator, currentGraphLink, targetGraphLink, stateExitBranch, currentGraphLink.validPathId, currentNodeLocal);

                                        // if debugging is activated => dump method cfg and add code to dump current graph
                                        if (this.debugging) {
                                            List<IOperation> debugOperations = new List<IOperation>();
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingNumber.ToString().PadLeft(3, '0') + "_" + target.basicBlock.id.ToString() + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method)));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.debuggingDumpGraphMethod));
                                            target.basicBlock.operations.InsertRange(0, debugOperations);

                                            //this.logger.dumpMethodCfg(methodCfg, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method));
                                            this.debuggingNumber++;
                                        }

                                        break;
                                    }
                            }
                        }

                        // search for all semantically equal basic blocks in the modified method CFG (as possible targets)
                        searchSementicId = introBranch.notTakenTarget.semanticId;
                        possibleTargetBasicBlocks = new List<BasicBlock>();
                        if (searchSementicId != -1) {
                            foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                                if (searchBasicBlock.semanticId == searchSementicId) {
                                    possibleTargetBasicBlocks.Add(searchBasicBlock);
                                }
                            }
                            if (possibleTargetBasicBlocks.Count() == 0) {
                                throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                            }
                        }
                        else {
                            possibleTargetBasicBlocks.Add(introBranch.notTakenTarget);
                        }

                        // create a list of target basic blocks of this branch
                        listOfTargets = new List<Target>();
                        target = new Target();
                        target.basicBlock = introBranch.notTakenTarget;
                        listOfTargets.Add(target);

                        // generate code for the "state switch"
                        stateBasicBlock = null;
                        stateExitBranch = null;
                        this.createCodeStateSwitch(ref stateBasicBlock, ref stateExitBranch, intStateLocal, metadata.correspondingGraphNodes);
                        cfgManipulator.insertBasicBlockBetweenBranch(introBranch, false, stateBasicBlock, stateExitBranch, 0);

                        // create for each valid path a branch in the switch statement of the "state switch"
                        for (currentValidPathId = 0; currentValidPathId < this.graph.graphValidPathCount; currentValidPathId++) {

                            // ignore first valid path (with id 0)
                            // => add artificial branch to original branch target (for the current valid path id)
                            if (currentValidPathId != 0) {

                                // fill switch taken branch list with null when index is out of range
                                while (stateExitBranch.takenTarget.Count() <= currentValidPathId) {
                                    stateExitBranch.takenTarget.Add(null);
                                }

                                // randomly chose what the target of the current branch should be (weight to use an existing basic block to have less memory consumption)
                                switch (this.prng.Next(this.duplicateBasicBlockWeight)) {
                                    case 0:
                                    case 1:
                                    case 2:
                                    case 3:
                                    case 4:
                                    case 5: {

                                            // duplicate the target basic block
                                            BasicBlock duplicatedBasicBlock = this.duplicateBasicBlock(originalMethodCfg, methodCfg, listOfTargets.ElementAt(0).basicBlock);
                                            methodCfg.basicBlocks.Add(duplicatedBasicBlock);
                                            basicBlocksToProcess.Add(duplicatedBasicBlock);

                                            // add new basic block as target of the switch case
                                            stateExitBranch.takenTarget[currentValidPathId] = duplicatedBasicBlock;
                                            duplicatedBasicBlock.entryBranches.Add(stateExitBranch);

                                            // add new basic block to the list of target basic blocks
                                            target = new Target();
                                            target.basicBlock = duplicatedBasicBlock;
                                            listOfTargets.Add(target);

                                            // add duplicated basic block to the list of possible target basic blocks
                                            possibleTargetBasicBlocks.Add(duplicatedBasicBlock);

                                            // create metadata for the newly created basic block
                                            if (!createAndAddMetadata(duplicatedBasicBlock)) {
                                                throw new ArgumentException("Creating metadata for the duplicated basic block failed.");
                                            }

                                            break;

                                        }
                                    default: {

                                            // use a random possible basic block as target
                                            int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                                            BasicBlock newTarget = possibleTargetBasicBlocks.ElementAt(randPosition);

                                            target = new Target();
                                            target.basicBlock = newTarget;
                                            listOfTargets.Add(target);

                                            //set switch taken branch for current valid path id to the chosen branch target
                                            stateExitBranch.takenTarget[currentValidPathId] = target.basicBlock;
                                            target.basicBlock.entryBranches.Add(stateExitBranch);

                                            break;

                                        }

                                }

                            }

                            // set current valid path id of the target
                            target.currentValidPathId = currentValidPathId;

                            // get the link from the current basic block to the obfuscation graph
                            BasicBlockGraphNodeLink currentGraphLink = null;
                            foreach (BasicBlockGraphNodeLink tempLink in metadata.correspondingGraphNodes) {
                                if (tempLink.validPathId == currentValidPathId) {
                                    currentGraphLink = tempLink;
                                    break;
                                }
                            }
                            if (currentGraphLink == null) {
                                throw new ArgumentNullException("Could not find link from current basic block to the graph for the given path id.");
                            }

                            // get the metadata for the target basic block
                            GraphTransformerMetadataBasicBlock targetMetadata = null;
                            for (int i = 0; i < target.basicBlock.transformationMetadata.Count(); i++) {
                                // get graph transformer metadata for basic blocks
                                if ((target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock) == null) {
                                    continue;
                                }
                                targetMetadata = (target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock);
                                break;
                            }
                            if (targetMetadata == null) {
                                throw new ArgumentException("Not able to find metadata for target basic block.");
                            }

                            // get the link from the target basic block to the obfuscation graph
                            BasicBlockGraphNodeLink targetGraphLink = null;
                            foreach (BasicBlockGraphNodeLink tempLink in targetMetadata.correspondingGraphNodes) {
                                if (tempLink.validPathId == currentValidPathId) {
                                    targetGraphLink = tempLink;
                                    break;
                                }
                            }
                            if (targetGraphLink == null) {
                                throw new ArgumentNullException("Could not find link from target basic block to the graph for the given path id.");
                            }

                            // choose randomly to either just correct the pointer position or to inject a "state change"
                            switch (this.prng.Next(this.stateChangeWeight)) {

                                // case: "state change"
                                case 0:
                                case 1:
                                case 2:
                                case 3:
                                case 4:
                                case 5: {

                                        // generate code for the "state change"
                                        BasicBlock stateChangeBasicBlock = null;
                                        SwitchBranchTarget stateChangeExitBranch = null;
                                        this.createCodeStateChange(ref stateChangeBasicBlock, ref stateChangeExitBranch, randomStateGenerator, currentGraphLink, intStateLocal);
                                        cfgManipulator.insertBasicBlockBetweenBranch(stateExitBranch, currentValidPathId, stateChangeBasicBlock, stateChangeExitBranch, 0);

                                        // create for each valid path a branch in the switch statement of the "state change"
                                        for (int changedCurrentValidPathId = 0; changedCurrentValidPathId < this.graph.graphValidPathCount; changedCurrentValidPathId++) {

                                            // ignore first valid path (with id 0)
                                            // => add artificial branch to original branch target (for the changed current valid path id)
                                            if (changedCurrentValidPathId != 0) {

                                                // fill switch taken branch list with null when index is out of range
                                                while (stateChangeExitBranch.takenTarget.Count() <= changedCurrentValidPathId) {
                                                    stateChangeExitBranch.takenTarget.Add(null);
                                                }

                                                // randomly chose what the target of the current branch should be (weight to use an existing basic block to have less memory consumption)
                                                switch (this.prng.Next(this.duplicateBasicBlockWeight)) {
                                                    case 0:
                                                    case 1:
                                                    case 2:
                                                    case 3:
                                                    case 4:
                                                    case 5: {

                                                            // duplicate the target basic block
                                                            BasicBlock duplicatedBasicBlock = this.duplicateBasicBlock(originalMethodCfg, methodCfg, listOfTargets.ElementAt(0).basicBlock);
                                                            methodCfg.basicBlocks.Add(duplicatedBasicBlock);
                                                            basicBlocksToProcess.Add(duplicatedBasicBlock);

                                                            // add new basic block as target of the switch case
                                                            stateChangeExitBranch.takenTarget[changedCurrentValidPathId] = duplicatedBasicBlock;
                                                            duplicatedBasicBlock.entryBranches.Add(stateChangeExitBranch);

                                                            // add new basic block to the list of target basic blocks
                                                            target = new Target();
                                                            target.basicBlock = duplicatedBasicBlock;
                                                            listOfTargets.Add(target);

                                                            // add duplicated basic block to the list of possible target basic blocks
                                                            possibleTargetBasicBlocks.Add(duplicatedBasicBlock);

                                                            // create metadata for the newly created basic block
                                                            if (!createAndAddMetadata(duplicatedBasicBlock)) {
                                                                throw new ArgumentException("Creating metadata for the duplicated basic block failed.");
                                                            }

                                                            break;

                                                        }
                                                    default: {

                                                            // use a random possible basic block as target
                                                            int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                                                            BasicBlock newTarget = possibleTargetBasicBlocks.ElementAt(randPosition);

                                                            target = new Target();
                                                            target.basicBlock = newTarget;
                                                            listOfTargets.Add(target);

                                                            // set switch taken branch for current valid path id to the chosen branch target
                                                            stateChangeExitBranch.takenTarget[changedCurrentValidPathId] = target.basicBlock;
                                                            target.basicBlock.entryBranches.Add(stateChangeExitBranch);

                                                            break;

                                                        }
                                                }

                                            }

                                            // set current valid path id of the target
                                            target.currentValidPathId = changedCurrentValidPathId;

                                            // get the metadata for the change target basic block
                                            GraphTransformerMetadataBasicBlock changeTargetMetadata = null;
                                            for (int i = 0; i < target.basicBlock.transformationMetadata.Count(); i++) {
                                                // get graph transformer metadata for basic blocks
                                                if ((target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock) == null) {
                                                    continue;
                                                }
                                                changeTargetMetadata = (target.basicBlock.transformationMetadata.ElementAt(i) as GraphTransformerMetadataBasicBlock);
                                                break;
                                            }
                                            if (changeTargetMetadata == null) {
                                                throw new ArgumentException("Not able to find metadata for target basic block.");
                                            }

                                            // get the link from the change target basic block to the obfuscation graph
                                            BasicBlockGraphNodeLink changeTargetGraphLink = null;
                                            foreach (BasicBlockGraphNodeLink tempLink in changeTargetMetadata.correspondingGraphNodes) {
                                                if (tempLink.validPathId == changedCurrentValidPathId) {
                                                    changeTargetGraphLink = tempLink;
                                                    break;
                                                }
                                            }
                                            if (changeTargetGraphLink == null) {
                                                throw new ArgumentNullException("Could not find link from target basic block to the graph for the given path id.");
                                            }

                                            // correct the pointer position to the obfuscation graph
                                            this.injectLinkMoveCode(cfgManipulator, currentGraphLink, changeTargetGraphLink, stateChangeExitBranch, changedCurrentValidPathId, currentNodeLocal);

                                            // if debugging is activated => dump method cfg and add code to dump current graph
                                            if (this.debugging) {
                                                List<IOperation> debugOperations = new List<IOperation>();
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingNumber.ToString().PadLeft(3, '0') + "_" + target.basicBlock.id.ToString() + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method)));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));
                                                debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.debuggingDumpGraphMethod));
                                                target.basicBlock.operations.InsertRange(0, debugOperations);

                                                //this.logger.dumpMethodCfg(methodCfg, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method));
                                                this.debuggingNumber++;
                                            }

                                        }

                                        break;
                                    }

                                // case: correct pointer position
                                default: {

                                        this.injectLinkMoveCode(cfgManipulator, currentGraphLink, targetGraphLink, stateExitBranch, currentGraphLink.validPathId, currentNodeLocal);

                                        // if debugging is activated => dump method cfg and add code to dump current graph
                                        if (this.debugging) {
                                            List<IOperation> debugOperations = new List<IOperation>();
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingNumber.ToString().PadLeft(3, '0') + "_" + target.basicBlock.id.ToString() + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method)));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));
                                            debugOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.debuggingDumpGraphMethod));
                                            target.basicBlock.operations.InsertRange(0, debugOperations);

                                            //this.logger.dumpMethodCfg(methodCfg, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method));
                                            this.debuggingNumber++;
                                        }

                                        break;
                                    }
                            }
                        }
                    }

                    // check if the current exit branch is of type "try block target"
                    else if (currentBasicBlock.exitBranch as TryBlockTarget != null) {
                        throw new ArgumentException("Not yet implemented.");
                    }

                    // check if the current exit branch is of type "switch branch target"
                    else if (currentBasicBlock.exitBranch as SwitchBranchTarget != null) {
                        throw new ArgumentException("Not yet implemented.");
                    }

                    // check if the current exit branch is of type "exception branch target"
                    else if (currentBasicBlock.exitBranch as ExceptionBranchTarget != null) {
                        throw new ArgumentException("Not yet implemented.");
                    }

                    // check if the current exit branch is of type "exit branch target"
                    else if (currentBasicBlock.exitBranch as ExitBranchTarget != null) {
                        continue;
                    }

                    // check if the current exit branch is of type "throw branch target"
                    else if (currentBasicBlock.exitBranch as ThrowBranchTarget != null) {
                        continue;
                    }

                    // this case should never be reached
                    else {
                        throw new ArgumentException("Do not know how to handle branch.");
                    }

                }

                System.Console.WriteLine("Basic Blocks to process (Control Flow): " + basicBlocksToProcess.Count());

                // check if basic blocks exist to process => if not break loop
                if (basicBlocksToProcess.Count() == 0) {
                    break;
                }

                // adjust probability to duplicate basic blocks (each processing round the probability drops to duplicate a basic block)
                this.duplicateBasicBlockWeight += this.duplicateBasicBlockCorrectionValue;

                // adjust probability to insert a state change (each processing round the probability drops to insert a state change)
                this.stateChangeWeight += this.stateChangeCorrectionValue;

            }

        }
Exemplo n.º 11
0
        private void addMetadataIter(CfgManipulator cfgManipulator, GraphRandomStateGenerator randomStateGenerator, MethodCfg originalMethodCfg, MethodCfg methodCfg, BasicBlock startBasicBlock, LocalDefinition intStateLocal, LocalDefinition currentNodeLocal) {

            int currentValidPathId;

            // create transformation metadata for the start basic block
            GraphTransformerMetadataBasicBlock metadata = new GraphTransformerMetadataBasicBlock();

            for (currentValidPathId = 0; currentValidPathId < this.graph.graphValidPathCount; currentValidPathId++) {
                BasicBlockGraphNodeLink link = new BasicBlockGraphNodeLink(this.graph.startingNode, currentValidPathId);
                metadata.correspondingGraphNodes.Add(link);
            }

            startBasicBlock.transformationMetadata.Add(metadata);

            // create a list of basic blocks that still have to be processed by the algorithm
            List<BasicBlock> basicBlocksToProcess = new List<BasicBlock>(methodCfg.basicBlocks);
            basicBlocksToProcess.Remove(startBasicBlock);

            System.Console.WriteLine("Basic Blocks to process (Metadata): " + basicBlocksToProcess.Count());

            // add metadata to all basic blocks
            while (true) {

                List<BasicBlock> copiedList = new List<BasicBlock>(basicBlocksToProcess);
                foreach (BasicBlock currentBasicBlock in copiedList) {

                    // check if the current basic block was already visited => it is already used for the graph obfuscation => skip it
                    bool hasGraphMetadata = false;
                    for (int i = 0; i < currentBasicBlock.transformationMetadata.Count(); i++) {
                        // get graph transformer metadata for basic blocks
                        if ((currentBasicBlock.transformationMetadata.ElementAt(i) as IGraphTransformerMetadata) == null) {
                            continue;
                        }
                        hasGraphMetadata = true;
                        break;
                    }
                    if (hasGraphMetadata) {
                        basicBlocksToProcess.Remove(currentBasicBlock);
                        continue;
                    }

                    if (!this.createAndAddMetadata(currentBasicBlock)) { 
                        continue;
                    }

                    // remove current basic block from the list of basic blocks to process
                    basicBlocksToProcess.Remove(currentBasicBlock);

                }

                System.Console.WriteLine("Basic Blocks to process (Metadata): " + basicBlocksToProcess.Count());

                // check if basic blocks exist to process => if not break loop
                if (basicBlocksToProcess.Count() == 0) {
                    break;
                }

            }

        }
Exemplo n.º 12
0
        public void addObfuscationToMethod(MethodCfg methodCfg) {

            MethodCfg copyMethodCfg = new MethodCfg(methodCfg);
            CfgManipulator cfgManipulator = new CfgManipulator(this.module, this.host, this.logger, methodCfg);
            GraphRandomStateGenerator randomStateGenerator = new GraphRandomStateGenerator(this.module, this.host, this.logger, cfgManipulator, this.helperClass, this.graph, methodCfg, this.debugging);

            // DEBUG
            if (this.debugging) {
                //this.logger.dumpMethodCfg(methodCfg, this.debuggingNumber.ToString().PadLeft(3, '0') + "_obfu_" + this.logger.makeFuncSigString(methodCfg.method));
                this.debuggingNumber++;
            }

            // add local state variable
            LocalDefinition intStateLocal = new LocalDefinition();
            intStateLocal.IsReference = false;
            intStateLocal.IsPinned = false;
            intStateLocal.IsModified = false;
            intStateLocal.Type = this.host.PlatformType.SystemInt32;
            intStateLocal.MethodDefinition = methodCfg.method;
            cfgManipulator.addLocalVariable(intStateLocal);

            // add local current graph node variable
            LocalDefinition currentNodeLocal = new LocalDefinition();
            currentNodeLocal.IsReference = false;
            currentNodeLocal.IsPinned = false;
            currentNodeLocal.IsModified = false;
            currentNodeLocal.Type = this.nodeInterface;
            currentNodeLocal.MethodDefinition = methodCfg.method;
            cfgManipulator.addLocalVariable(currentNodeLocal);

            // create new basic block that sets the current node to the start node and get the state
            // (will be the new starting basic block of the method)
            BasicBlock startBasicBlock = new BasicBlock();
            startBasicBlock.startIdx = 0;
            startBasicBlock.endIdx = 0;

            // set the current node pointer to the start node
            startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
            startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceStartPointerGet));
            startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Stloc, currentNodeLocal));

            // initialize the random state generator
            List<IOperation> tempOperations = randomStateGenerator.generateCodeInitializeRandomState();
            startBasicBlock.operations.AddRange(tempOperations);

            // set global state
            tempOperations = randomStateGenerator.generateCodeSetRandomState(intStateLocal);
            startBasicBlock.operations.AddRange(tempOperations);

            // create exit branch for the new start basic block
            NoBranchTarget startExitBranch = new NoBranchTarget();
            startExitBranch.sourceBasicBlock = startBasicBlock;
            startBasicBlock.exitBranch = startExitBranch;

            // set the original start basic block as the target of the exit branch
            startExitBranch.takenTarget = methodCfg.startBasicBlock;
            methodCfg.startBasicBlock.entryBranches.Add(startExitBranch);

            // set new start basic block as start basic block of the method cfg
            methodCfg.startBasicBlock = startBasicBlock;
            methodCfg.basicBlocks.Add(startBasicBlock);

            // obfuscate the control flow
            this.addMetadataIter(cfgManipulator, randomStateGenerator, copyMethodCfg, methodCfg, startBasicBlock, intStateLocal, currentNodeLocal);
            this.processExitBranchesIter(cfgManipulator, randomStateGenerator, copyMethodCfg, methodCfg, startBasicBlock, intStateLocal, currentNodeLocal);
            this.addOpaquePredicatesIter(cfgManipulator, randomStateGenerator, copyMethodCfg, methodCfg, startBasicBlock, intStateLocal, currentNodeLocal);
            this.removeReplaceUnconditionalBranchesIter(cfgManipulator, randomStateGenerator, copyMethodCfg, methodCfg, startBasicBlock, intStateLocal, currentNodeLocal);

            // fill dead code basic blocks with actual dead code
            this.fillDeadCodeBasicBlocks(methodCfg);
            this.obfuscateSemanticallyEquivalentBlocks(methodCfg);

            // TODO QUICK FIX
            // mutateBlocks() does not work when debugging is deactivated
            // but since we only focus on probabilistic control flow, ignore it for now
            this.debugging = true;
            this.mutateBlocks(methodCfg);
            this.debugging = false;
            
            // if debugging is activated => add code that allows to trace the control flow through the method
            if (this.debugging
                || this.trace) {

                List<IOperation> traceWriterOperations = null;

                // add code to the beginning of each basic block that writes to the trace file
                for (int idx = 0; idx < methodCfg.basicBlocks.Count(); idx++) {

                    traceWriterOperations = new List<IOperation>();
                    traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                    traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldfld, this.debuggingTraceWriter));
                    traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, "BB" + idx.ToString() + ";ID" + methodCfg.basicBlocks.ElementAt(idx).id.ToString()));
                    traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.helperClass.textWriterWriteLine));

                    methodCfg.basicBlocks.ElementAt(idx).operations.InsertRange(0, traceWriterOperations);

                    // check if the basic block has an exit branch
                    // => add code that closes the file handler of the trace file before the ret instruction
                    if ((methodCfg.basicBlocks.ElementAt(idx).exitBranch as ExitBranchTarget) != null) {

                        traceWriterOperations = new List<IOperation>();

                        traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                        traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldfld, this.debuggingTraceWriter));
                        traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.helperClass.textWriterClose));

                        methodCfg.basicBlocks.ElementAt(idx).operations.InsertRange(methodCfg.basicBlocks.ElementAt(idx).operations.Count() - 1, traceWriterOperations);

                    }
                }

                // create local integer variable needed for the trace file code
                LocalDefinition intLocal = new LocalDefinition();
                intLocal.IsReference = false;
                intLocal.IsPinned = false;
                intLocal.IsModified = false;
                intLocal.Type = this.host.PlatformType.SystemInt32;
                intLocal.MethodDefinition = methodCfg.method;
                cfgManipulator.addLocalVariable(intLocal);

                traceWriterOperations = new List<IOperation>();

                // get the hash code of this instance as unique object id                    
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.helperClass.objectGetHashCode));
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Stloc, intLocal));

                // initialize io stream writer for trace file (use object hash as id for this trace and only append)
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));

                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, this.debuggingDumpLocation + "\\" + this.debuggingTraceFilePrefix + "_"));

                // cast random integer to string and store in object id
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldloca, intLocal));
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Call, this.helperClass.int32ToString));

                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, ".txt"));
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Call, this.helperClass.stringConcatThree));

                // only append to file
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4_1));

                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Newobj, this.helperClass.streamWriterCtorAppend));
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Stfld, this.debuggingTraceWriter));

                // write marker to trace file that marks the beginning of this trace
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldarg_0));
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldfld, this.debuggingTraceWriter));
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Ldstr, "\n------NEWSTART------\n"));
                traceWriterOperations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.helperClass.textWriterWriteLine));

                // add code to the beginning of the start basic block
                methodCfg.startBasicBlock.operations.InsertRange(0, traceWriterOperations);

            }

            logger.dumpMethodCfg(copyMethodCfg, "copy_final");

            return;
        }
Exemplo n.º 13
0
        // Mutates all blocks in the given method CFG.
        private void mutateBlocks(MethodCfg methodCfg)
        {
            var manipulator = new CfgManipulator(this.module, this.host, this.logger, methodCfg);
            var codeMutator = new CodeMutator(this.module, this.host, this.logger, this.prng, methodCfg, manipulator, this.debugging);

            codeMutator.mutateBlocks(methodCfg.basicBlocks);
        }
Exemplo n.º 14
0
        // Searches semantically equivalent blocks in the given method CFG and obfuscates them.
        private void obfuscateSemanticallyEquivalentBlocks(MethodCfg methodCfg)
        {
            // Group all blocks with same semantic ID.
            var semanticGroups = new Dictionary<int, List<BasicBlock>>();

            foreach(var block in methodCfg.basicBlocks) {
                List<BasicBlock> blockList = null;
                if(!semanticGroups.TryGetValue(block.semanticId, out blockList)) {
                    blockList = new List<BasicBlock>();
                    semanticGroups[block.semanticId] = blockList;
                }

                if(block.semanticId != -1) {
                    semanticGroups[block.semanticId].Add(block);
                }
            }

            // Mutate equivalent blocks.
            var manipulator = new CfgManipulator(this.module, this.host, this.logger, methodCfg);
            var codeMutator = new CodeMutator(this.module, this.host, this.logger, this.prng, methodCfg, manipulator, this.debugging);

            foreach(var blockList in semanticGroups.Values) {
                codeMutator.mutateSemanticallyEquivalentBlocks(blockList); 
            }
        }
Exemplo n.º 15
0
        // this function is used to fill the created dead code basic blocks with actual dead code
        private void fillDeadCodeBasicBlocks(MethodCfg methodCfg) {

            var manipulator = new CfgManipulator(this.module, this.host, this.logger, methodCfg);
            CodeGenerator codeGenerator = new CodeGenerator(this.module, this.host, this.logger, this.prng, methodCfg, this.debugging, manipulator);
            //CodeGenerator codeGenerator = new CodeGenerator(this.module, this.host, this.logger, this.prng, methodCfg, true, manipulator);

            // search through all basic blocks if there are dead code basic blocks
            foreach (BasicBlock currentBasicBlock in methodCfg.basicBlocks) {

                // fill basic block with dead code if it is marked as a dead code basic block
                foreach (ITransformationMetadata metadata in currentBasicBlock.transformationMetadata) {
                    if ((metadata as GraphTransformerDeadCodeBasicBlock) != null) {
                        codeGenerator.generateDeadCode(currentBasicBlock, metadata);
                    }
                }

            }

        }
Exemplo n.º 16
0
        // builds a CFG for the given method and returns it
        public MethodCfg buildCfgForMethod(MethodDefinition method) {

            MethodCfg methodCfg = new MethodCfg();
            methodCfg.method = method;

            // start building the cfg
            BasicBlock firstBasicBlock = new BasicBlock(this.semanticId);
            this.semanticId++;
            methodCfg.startBasicBlock = firstBasicBlock;
            this.buildRecursivelyCfg(methodCfg, method.Body.Operations, 0, null, ref firstBasicBlock);

            // add exception handler to the cfg
            foreach (IOperationExceptionInformation exceptionHandler in method.Body.OperationExceptionInformation) {

                // debugging variables to throw an exception if start/end of try/handler block was not found
                bool tryStartFound = false;
                bool tryEndFound = false;
                bool handlerStartFound = false;
                bool handlerEndFound = false;

                // search each basic block if they reside in an exception handler
                List<BasicBlock> localCopy = new List<BasicBlock>();
                localCopy.AddRange(methodCfg.basicBlocks);
                for (int bbIdx = 0; bbIdx < localCopy.Count(); bbIdx++) {
                    BasicBlock basicBlock = localCopy.ElementAt(bbIdx);
                    int lastOperationIdx = basicBlock.operations.Count() - 1;

                    // ignore basic block if the start of the try block lies behind the current basic block
                    // (catch or finally blocks can never lie before a try block)
                    if (basicBlock.operations.ElementAt(lastOperationIdx).Offset < exceptionHandler.TryStartOffset) {
                        continue;
                    }

                    // check if the current basic block resides in the try block of the exception handler
                    else if ((exceptionHandler.TryStartOffset >= basicBlock.operations.ElementAt(0).Offset && exceptionHandler.TryStartOffset <= basicBlock.operations.ElementAt(lastOperationIdx).Offset)
                        || (exceptionHandler.TryStartOffset <= basicBlock.operations.ElementAt(0).Offset && basicBlock.operations.ElementAt(lastOperationIdx).Offset < exceptionHandler.TryEndOffset)) {

                        TryBlock tempTryBlock = new TryBlock();
                        tempTryBlock.exceptionHandler = exceptionHandler;

                        // check if the try block starts inside this basic block
                        if (exceptionHandler.TryStartOffset >= basicBlock.operations.ElementAt(0).Offset) {

                            // find the index of the operation that starts the try block
                            bool foundIdx = false;
                            for (int idx = 0; idx < basicBlock.operations.Count(); idx++) {
                                if (basicBlock.operations.ElementAt(idx).Offset == exceptionHandler.TryStartOffset) {
                                    
                                    // if the try block does not start at the beginning of the current basic block
                                    // => split basic block and let the try block begin at the second half of the basic block
                                    if (idx != 0) {

                                        // create new basic block which will be the second half of the found one
                                        BasicBlock newBasicBlock = new BasicBlock(this.semanticId);
                                        this.semanticId++;
                                        newBasicBlock.startIdx = basicBlock.startIdx + idx;
                                        newBasicBlock.endIdx = basicBlock.endIdx;
                                        basicBlock.endIdx = basicBlock.startIdx + idx - 1;

                                        // move the exit basic blocks to the new created basic block
                                        // and make the new created basic block the exit of the splitted one   
                                        newBasicBlock.exitBranch = basicBlock.exitBranch;
                                        newBasicBlock.exitBranch.sourceBasicBlock = newBasicBlock;
                                        TryBlockTarget tempExitBranch = new TryBlockTarget();
                                        tempExitBranch.takenTarget = newBasicBlock;
                                        tempExitBranch.sourceBasicBlock = basicBlock;
                                        basicBlock.exitBranch = tempExitBranch;

                                        // add splitted basic block branch to the entry of the new one
                                        newBasicBlock.entryBranches.Add(tempExitBranch);

                                        // distribute the instructions to the basic blocks 
                                        List<IOperation> previousOperations = new List<IOperation>();
                                        List<IOperation> nextOperations = new List<IOperation>();
                                        for (int operationIdx = 0; (operationIdx + basicBlock.startIdx) <= newBasicBlock.endIdx; operationIdx++) {

                                            if ((operationIdx + basicBlock.startIdx) < newBasicBlock.startIdx) {
                                                previousOperations.Add(basicBlock.operations.ElementAt(operationIdx));
                                            }
                                            else {
                                                nextOperations.Add(basicBlock.operations.ElementAt(operationIdx));
                                            }
                                        }
                                        basicBlock.operations = previousOperations;
                                        newBasicBlock.operations = nextOperations;

                                        // add new basic block to the cfg
                                        methodCfg.basicBlocks.Add(newBasicBlock);

                                        // add try block to the new created basic block (it is the start of the try block)
                                        newBasicBlock.tryBlocks.Add(tempTryBlock);

                                        // try block can not end at the first part of the splitted basic block
                                        // (because it starts at the second one), but it can end at the
                                        // second part of the splitted basic block
                                        basicBlock = newBasicBlock;
                                        lastOperationIdx = newBasicBlock.operations.Count() - 1;
                                    }

                                    // the try block starts at the beginning of the current basic block => add the try block
                                    else {
                                        basicBlock.tryBlocks.Add(tempTryBlock);
                                    }
                                    
                                    // mark try block as the beginning of the try block
                                    tempTryBlock.firstBasicBlockOfTryBlock = true;
                                    foundIdx = true;
                                    tryStartFound = true;
                                    break;
                                }
                            }
                            if (!foundIdx) {
                                throw new ArgumentException("Did not find index of operation that starts Try block.");
                            }
                        }
                        else {
                            basicBlock.tryBlocks.Add(tempTryBlock);
                            tempTryBlock.firstBasicBlockOfTryBlock = false;
                        }

                        // check if the try block ends at the end of this basic block (try blocks always end at the end of a basic block)
                        if (basicBlock.operations.ElementAt(lastOperationIdx).Offset + CfgBuilder.getSizeOfOperation(basicBlock.operations.ElementAt(lastOperationIdx)) == exceptionHandler.TryEndOffset) {
                            tempTryBlock.lastBasicBlockOfTryBlock = true;
                            tryEndFound = true;
                        }
                        else {
                            tempTryBlock.lastBasicBlockOfTryBlock = false;
                        }

                        continue;
                    }

                    // check if the current basic block resides in the handler block of the exception handler
                    else if ((exceptionHandler.HandlerStartOffset >= basicBlock.operations.ElementAt(0).Offset && exceptionHandler.HandlerStartOffset <= basicBlock.operations.ElementAt(lastOperationIdx).Offset)
                        || (exceptionHandler.HandlerStartOffset <= basicBlock.operations.ElementAt(0).Offset && basicBlock.operations.ElementAt(lastOperationIdx).Offset < exceptionHandler.HandlerEndOffset)) {

                        // check if the handler block is a catch block
                        if (exceptionHandler.HandlerKind == HandlerKind.Catch) {
                            HandlerBlock tempCatchBock = new HandlerBlock();
                            tempCatchBock.typeOfHandler = HandlerKind.Catch;
                            tempCatchBock.exceptionHandler = exceptionHandler;
                            basicBlock.handlerBlocks.Add(tempCatchBock);

                            // check if the catch block starts inside this basic block
                            if (exceptionHandler.HandlerStartOffset >= basicBlock.operations.ElementAt(0).Offset) {

                                // find the index of the operation that starts the catch block
                                bool foundIdx = false;
                                for (int idx = 0; idx < basicBlock.operations.Count(); idx++) {
                                    if (basicBlock.operations.ElementAt(idx).Offset == exceptionHandler.HandlerStartOffset) {
                                        tempCatchBock.firstBasicBlockOfHandlerBlock = true;
                                        foundIdx = true;
                                        handlerStartFound = true;
                                        break;
                                    }
                                }
                                if (!foundIdx) {
                                    throw new ArgumentException("Did not find index of operation that starts Catch block.");
                                }
                            }
                            else {
                                tempCatchBock.firstBasicBlockOfHandlerBlock = false;
                            }

                            // check if the catch block ends inside this basic block
                            if (basicBlock.operations[0].Offset < exceptionHandler.HandlerEndOffset
                                && exceptionHandler.HandlerEndOffset <= (basicBlock.operations.ElementAt(lastOperationIdx).Offset + CfgBuilder.getSizeOfOperation(basicBlock.operations.ElementAt(lastOperationIdx)))) {

                                // check if the catch block ends at the last instruction of this basic block (this happens usually => optimization)
                                if (basicBlock.operations.ElementAt(lastOperationIdx).Offset + CfgBuilder.getSizeOfOperation(basicBlock.operations.ElementAt(lastOperationIdx)) == exceptionHandler.HandlerEndOffset) {
                                    tempCatchBock.lastBasicBlockOfHandlerBlock = true;
                                    handlerEndFound = true;
                                    continue;
                                }
                                else {
                                    throw new ArgumentException("Did not find the operation that ends Catch block.");
                                }
                            }
                            else {
                                tempCatchBock.lastBasicBlockOfHandlerBlock = false;
                            }

                            continue;
                        }

                            // check if the handler block is a finally block
                        else if (exceptionHandler.HandlerKind == HandlerKind.Finally) {
                            HandlerBlock tempFinallyBock = new HandlerBlock();
                            tempFinallyBock.typeOfHandler = HandlerKind.Finally;
                            tempFinallyBock.exceptionHandler = exceptionHandler;
                            basicBlock.handlerBlocks.Add(tempFinallyBock);

                            // check if the finally block starts inside this basic block
                            if (exceptionHandler.HandlerStartOffset >= basicBlock.operations.ElementAt(0).Offset) {

                                // find the index of the operation that starts the finally block
                                bool foundIdx = false;
                                for (int idx = 0; idx < basicBlock.operations.Count(); idx++) {
                                    if (basicBlock.operations.ElementAt(idx).Offset == exceptionHandler.HandlerStartOffset) {
                                        tempFinallyBock.firstBasicBlockOfHandlerBlock = true;
                                        foundIdx = true;
                                        handlerStartFound = true;
                                        break;
                                    }
                                }
                                if (!foundIdx) {
                                    throw new ArgumentException("Did not find index of operation that starts Finally block.");
                                }
                            }
                            else {
                                tempFinallyBock.firstBasicBlockOfHandlerBlock = false;
                            }

                            // check if the finally block ends inside this basic block
                            if (basicBlock.operations[0].Offset < exceptionHandler.HandlerEndOffset
                                && exceptionHandler.HandlerEndOffset <= (basicBlock.operations.ElementAt(lastOperationIdx).Offset + CfgBuilder.getSizeOfOperation(basicBlock.operations.ElementAt(lastOperationIdx)))) {

                                // check if the finally block ends at the last instruction of this basic block
                                if (basicBlock.operations.ElementAt(lastOperationIdx).Offset + CfgBuilder.getSizeOfOperation(basicBlock.operations.ElementAt(lastOperationIdx)) == exceptionHandler.HandlerEndOffset) {
                                    tempFinallyBock.lastBasicBlockOfHandlerBlock = true;
                                    handlerEndFound = true;
                                    continue;
                                }
                                else {
                                    throw new ArgumentException("Did not find the operation that ends Finally block.");
                                }
                            }

                            continue;
                        }

                        else {
                            throw new ArgumentException("Do not know how to handle exception handler.");
                        }
                    }
                }

                // check if start/end of try/handler block was found
                if(!tryStartFound
                    || !tryEndFound
                    || !handlerStartFound
                    || !handlerEndFound) {
                    throw new ArgumentException("Was not able to find start/end of try/handler block.");
                }

            }



            // TODO
            // DEBUG
            //this.logger.dumpMethodCfg(methodCfg, this.logger.sanitizeString(methodCfg.method.ToString()));

            return methodCfg;
        }
Exemplo n.º 17
0
        private void addOpaquePredicatesIter(CfgManipulator cfgManipulator, GraphRandomStateGenerator randomStateGenerator, MethodCfg originalMethodCfg, MethodCfg methodCfg, BasicBlock startBasicBlock, LocalDefinition intStateLocal, LocalDefinition currentNodeLocal) {

            // create a list of basic blocks that still have to be processed by the algorithm
            List<BasicBlock> basicBlocksToProcess = new List<BasicBlock>(methodCfg.basicBlocks);

            System.Console.WriteLine("Basic Blocks to process (Opaque Predicates): " + basicBlocksToProcess.Count());

            while (true) {

                List<BasicBlock> copiedList = new List<BasicBlock>(basicBlocksToProcess);
                foreach (BasicBlock currentBasicBlock in copiedList) {

                    // process all entry branches of the current basic block
                    List<IBranchTarget> copiedBranchList = new List<IBranchTarget>(currentBasicBlock.entryBranches);
                    foreach (IBranchTarget entryBranch in copiedBranchList) {

                        // get the metadata for the source basic block of the entry branch
                        BasicBlock sourceBasicBlock = entryBranch.sourceBasicBlock;
                        IGraphTransformerMetadata sourceMetadata = null;
                        for (int i = 0; i < sourceBasicBlock.transformationMetadata.Count(); i++) {
                            // get graph transformer metadata for basic blocks
                            if ((sourceBasicBlock.transformationMetadata.ElementAt(i) as IGraphTransformerMetadata) == null) {
                                continue;
                            }
                            sourceMetadata = (sourceBasicBlock.transformationMetadata.ElementAt(i) as IGraphTransformerMetadata);
                            break;
                        }
                        if (sourceMetadata == null) {
                            throw new ArgumentException("Not able to find metadata for source basic block of the entry branch.");
                        }

                        // only process entry branches with only one link to the obfuscation graph
                        if (sourceMetadata.correspondingGraphNodes.Count() != 1) {
                            continue;
                        }

                        // check if the source basic block is a basic block that moves the pointer to the obfuscation graph
                        // => use the link from the current basic block to the obfuscation graph
                        BasicBlockGraphNodeLink link = null;
                        if ((sourceMetadata as GraphTransformerNextNodeBasicBlock) != null) {

                            // get the metadata for the current basic block (because the source basic block has moved the pointer to the obfuscation graph)
                            IGraphTransformerMetadata currentMetadata = null;
                            for (int i = 0; i < currentBasicBlock.transformationMetadata.Count(); i++) {
                                // get graph transformer metadata for basic blocks
                                if ((currentBasicBlock.transformationMetadata.ElementAt(i) as IGraphTransformerMetadata) == null) {
                                    continue;
                                }
                                currentMetadata = (currentBasicBlock.transformationMetadata.ElementAt(i) as IGraphTransformerMetadata);
                                break;
                            }
                            if (currentMetadata == null) {
                                throw new ArgumentException("Not able to find metadata for source basic block of the entry branch.");
                            }

                            // when current basic block also moves the pointer to the obfuscation graph => skip opaque predicate insertion it (for the moment)
                            // (problem with obfuscation graph nodes that do not reside on the vpath because of pointer correction code)
                            if ((currentMetadata as GraphTransformerNextNodeBasicBlock) != null) {
                                continue;
                            }

                            // get the link to the correct obfuscation graph node for the valid path that goes through the source basic block
                            BasicBlockGraphNodeLink sourceLink = sourceMetadata.correspondingGraphNodes.ElementAt(0);
                            foreach (BasicBlockGraphNodeLink tempLink in currentMetadata.correspondingGraphNodes) {
                                if (tempLink.validPathId == sourceLink.validPathId) {
                                    link = tempLink;
                                }
                            }
                            if (link == null) {
                                throw new ArgumentException("Not able to find link from current basic block to the obfuscation graph.");
                            }

                        }

                        // => just use the link from the source basic block to the obfuscation graph
                        else {
                            link = sourceMetadata.correspondingGraphNodes.ElementAt(0);
                        }

                        // decide randomly to add an opaque predicate
                        switch (this.prng.Next(this.insertOpaquePredicateWeight)) {
                            case 0:
                            case 1:
                            case 2:
                            case 3:
                            case 4:
                            case 5: {

                                    // choose randomly which opaque predicate should be added
                                    int opaquePredicate = this.prng.Next(2);
                                    this.injectOpaquePredicateCode(cfgManipulator, methodCfg, currentBasicBlock, entryBranch, link, opaquePredicate, currentNodeLocal);

                                    break;
                                }

                            default: {
                                    break;
                                }
                        }

                    }

                    // remove currently processed basic block from the list of basic blocks to process
                    basicBlocksToProcess.Remove(currentBasicBlock);

                }

                System.Console.WriteLine("Basic Blocks to process (Opaque Predicates): " + basicBlocksToProcess.Count());

                // check if basic blocks exist to process => if not break loop
                if (basicBlocksToProcess.Count() == 0) {
                    break;
                }

            }

        }
Exemplo n.º 18
0
        private void removeReplaceUnconditionalBranchesIter(CfgManipulator cfgManipulator, GraphRandomStateGenerator randomStateGenerator, MethodCfg originalMethodCfg, MethodCfg methodCfg, BasicBlock startBasicBlock, LocalDefinition intStateLocal, LocalDefinition currentNodeLocal) {

            // create a list of basic blocks that still have to be processed by the algorithm
            List<BasicBlock> basicBlocksToProcess = new List<BasicBlock>(methodCfg.basicBlocks);

            System.Console.WriteLine("Basic Blocks to process (Replace Unconditional Branches): " + basicBlocksToProcess.Count());

            while (true) {

                List<BasicBlock> copiedList = new List<BasicBlock>(basicBlocksToProcess);
                foreach (BasicBlock currentBasicBlock in copiedList) {

                    // check if basic block has entry branches that can be optimized
                    bool hasUnconditionalBranchTarget = false;
                    bool hasNoBranchTarget = false;
                    foreach (IBranchTarget entryBranch in currentBasicBlock.entryBranches) {
                        if ((entryBranch as NoBranchTarget) != null) {
                            hasNoBranchTarget = true;
                            continue;
                        }
                        else if ((entryBranch as UnconditionalBranchTarget) != null) {
                            hasUnconditionalBranchTarget = true;
                            continue;
                        }
                    }

                    // skip if basic block already has no branch target
                    if (hasNoBranchTarget) {
                        // remove currently processed basic block from the list of basic blocks to process
                        basicBlocksToProcess.Remove(currentBasicBlock);
                        continue;
                    }

                    // skip if basic block does not have an unconditional branch target
                    if (!hasUnconditionalBranchTarget) {
                        // remove currently processed basic block from the list of basic blocks to process
                        basicBlocksToProcess.Remove(currentBasicBlock);
                        continue;
                    }

                    // replace one unconditional branch by a no branch
                    List<IBranchTarget> copiedBranchList = new List<IBranchTarget>(currentBasicBlock.entryBranches);
                    foreach (IBranchTarget entryBranch in copiedBranchList) {

                        if ((entryBranch as UnconditionalBranchTarget) != null) {
                            BasicBlock sourceBasicBlock = entryBranch.sourceBasicBlock;

                            // create replacement branch
                            NoBranchTarget replacementBranch = new NoBranchTarget();
                            replacementBranch.sourceBasicBlock = sourceBasicBlock;
                            replacementBranch.takenTarget = currentBasicBlock;

                            // replace old branch with new one
                            sourceBasicBlock.exitBranch = replacementBranch;
                            currentBasicBlock.entryBranches.Remove(entryBranch);
                            currentBasicBlock.entryBranches.Add(replacementBranch);

                            // replace unconditional branch instruction with nop
                            IOperation lastOperation = sourceBasicBlock.operations.ElementAt(sourceBasicBlock.operations.Count() - 1);
                            if (!CfgBuilder.isUnconditionalBranchOperation(lastOperation)) {
                                throw new ArgumentException("Last instruction of basic block have to be an unconditional branch.");
                            }
                            IOperation replacementOperation = this.helperClass.createNewOperation(OperationCode.Nop);
                            sourceBasicBlock.operations[sourceBasicBlock.operations.Count() - 1] = replacementOperation;

                            break;
                        }

                    }

                    // remove currently processed basic block from the list of basic blocks to process
                    basicBlocksToProcess.Remove(currentBasicBlock);

                }

                System.Console.WriteLine("Basic Blocks to process (Replace Unconditional Branches): " + basicBlocksToProcess.Count());

                // check if basic blocks exist to process => if not break loop
                if (basicBlocksToProcess.Count() == 0) {
                    break;
                }

            }

        }
Exemplo n.º 19
0
        public void dumpMethodCfg(MethodCfg methodCfg, String fileName) {

            // shorten file name if it is too long
            fileName = fileName.Length >= 230 ? fileName.Substring(0, 230) : fileName;

            // dump cfg created from the exit branches
            System.IO.StreamWriter dotFile = new System.IO.StreamWriter(this.logPath + "\\exitBranches_" + fileName + ".dot");

            // start .dot file graph
            dotFile.WriteLine("digraph G {");

            // write all basic blocks to .dot file
            for (int idx = 0; idx < methodCfg.basicBlocks.Count(); idx++) {

                BasicBlock currentBasicBlock = methodCfg.basicBlocks.ElementAt(idx);

                // write the current basic block to the file and all its instructions
                dotFile.WriteLine("BB" + idx.ToString() + " [shape=record]");
                bool first = true;
                for (int opIdx = 0; opIdx < currentBasicBlock.operations.Count(); opIdx++) {
                    var operation = currentBasicBlock.operations.ElementAt(opIdx);
                    if (first) {
                        dotFile.Write("BB" + idx.ToString() + " [label=\"{");
                        dotFile.Write("NAME: BB" + idx.ToString() + "|");
                        dotFile.Write("ID: " + currentBasicBlock.id.ToString() + "|");
                        dotFile.Write("SEMANTIC ID: " + currentBasicBlock.semanticId.ToString() + "|");
                        first = false;

                        // dump basic block transformation metadata
                        foreach (ITransformationMetadata metadata in currentBasicBlock.transformationMetadata) {
                            if ((metadata as GraphTransformerMetadataBasicBlock) != null) {

                                GraphTransformerMetadataBasicBlock temp = (metadata as GraphTransformerMetadataBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                dotFile.Write("GRAPH_BLOCK (valid ID: " + validPathIdString + ")|");

                                // dump position of the element in the graph (for each valid path)
                                for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                    String positionString = "";
                                    foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                        positionString += position.ToString() + ";";
                                    }
                                    dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                }

                                // dump the valid and invalid interfaces of the graph element (for each valid path)
                                for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {

                                    PathElement pathElement = null;
                                    foreach (PathElement tempElement in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.pathElements) {
                                        if (tempElement.validPathId == temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId) {
                                            pathElement = tempElement;
                                            break;
                                        }
                                    }
                                    if (pathElement == null) {
                                        throw new ArgumentNullException("No path element for valid graph id was found.");
                                    }


                                    String tempOutput = "";
                                    foreach (ITypeReference interfaceInList in pathElement.validInterfaces) {
                                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                                    }
                                    dotFile.Write("valid Interfaces: " + tempOutput + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");

                                    tempOutput = "";
                                    foreach (ITypeReference interfaceInList in pathElement.invalidInterfaces) {
                                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                                    }
                                    dotFile.Write("invalid Interfaces: " + tempOutput + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                }

                            }
                            else if ((metadata as GraphTransformerPredicateBasicBlock) != null) {

                                GraphTransformerPredicateBasicBlock temp = (metadata as GraphTransformerPredicateBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                if (temp.predicateType == GraphOpaquePredicate.True) {
                                    dotFile.Write("TRUE_PREDICATE_BLOCK (valid ID: " + validPathIdString + ")|");

                                    // dump position of the element in the graph (for each valid path)
                                    for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                        String positionString = "";
                                        foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                            positionString += position.ToString() + ";";
                                        }
                                        dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                    }
                                }
                                else if (temp.predicateType == GraphOpaquePredicate.False) {
                                    dotFile.Write("FALSE_PREDICATE_BLOCK (valid ID: " + validPathIdString + ")|");

                                    // dump position of the element in the graph (for each valid path)
                                    for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                        String positionString = "";
                                        foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                            positionString += position.ToString() + ";";
                                        }
                                        dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                    }
                                }
                                else if (temp.predicateType == GraphOpaquePredicate.Random) {
                                    dotFile.Write("RANDOM_PREDICATE_BLOCK (valid ID: " + validPathIdString + ")|");

                                    // dump position of the element in the graph (for each valid path)
                                    for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                        String positionString = "";
                                        foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                            positionString += position.ToString() + ";";
                                        }
                                        dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                    }
                                }
                                else {
                                    throw new ArgumentException("Do not know how to handle opaque predicate type.");
                                }
                            }
                            else if ((metadata as GraphTransformerNextNodeBasicBlock) != null) {

                                GraphTransformerNextNodeBasicBlock temp = (metadata as GraphTransformerNextNodeBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                if (temp.correctNextNode) {
                                    dotFile.Write("CORRECT_NEXT_NODE_BLOCK (valid ID: " + validPathIdString + ")|");

                                    // dump position of the element in the graph (for each valid path)
                                    for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                        String positionString = "";
                                        foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                            positionString += position.ToString() + ";";
                                        }
                                        dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                    }
                                }
                                else {
                                    dotFile.Write("WRONG_NEXT_NODE_BLOCK (valid ID: " + validPathIdString + ")|");

                                    // dump position of the element in the graph (for each valid path)
                                    for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                        String positionString = "";
                                        foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                            positionString += position.ToString() + ";";
                                        }
                                        dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                    }
                                }
                            }
                            else if ((metadata as GraphTransformerDeadCodeBasicBlock) != null) {

                                GraphTransformerDeadCodeBasicBlock temp = (metadata as GraphTransformerDeadCodeBasicBlock);

                                dotFile.Write("DEAD_CODE_BLOCK (template semantic ID: " + temp.semanticId.ToString() + ")|");
                            }
                            else if ((metadata as GraphTransformerStateBasicBlock) != null) {

                                GraphTransformerStateBasicBlock temp = (metadata as GraphTransformerStateBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                dotFile.Write("STATE_BLOCK (valid ID: " + validPathIdString + ")|");

                                // dump position of the element in the graph (for each valid path)
                                for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                    String positionString = "";
                                    foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                        positionString += position.ToString() + ";";
                                    }
                                    dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                }
                            }
                            else if ((metadata as GraphTransformerStateChangeBasicBlock) != null) {

                                GraphTransformerStateChangeBasicBlock temp = (metadata as GraphTransformerStateChangeBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                dotFile.Write("STATE_CHANGE_BLOCK (valid ID: " + validPathIdString + ")|");

                                // dump position of the element in the graph (for each valid path)
                                for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                    String positionString = "";
                                    foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                        positionString += position.ToString() + ";";
                                    }
                                    dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                }
                            }
                            else if ((metadata as GraphTransformerIntermediateBasicBlock) != null) {

                                GraphTransformerIntermediateBasicBlock temp = (metadata as GraphTransformerIntermediateBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                dotFile.Write("INTERMEDIATE_BASIC_BLOCK (valid ID: " + validPathIdString + ")|");

                                // dump position of the element in the graph (for each valid path)
                                for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                    String positionString = "";
                                    foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                        positionString += position.ToString() + ";";
                                    }
                                    dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                }

                            }
                            else if ((metadata as DevBasicBlock) != null) {

                                DevBasicBlock temp = (metadata as DevBasicBlock);

                                dotFile.Write("DEV_NOTE: " + temp.note + "|");
                            }
                            else {
                                throw new ArgumentException("Do not know how to handle transformation metadata.");
                            }
                        }

                    }
                    else {
                        dotFile.Write("|");
                    }

                    // insert try block beginnings
                    foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                        if (tryBlock.firstBasicBlockOfTryBlock && opIdx == 0) {
                            dotFile.Write("TRY START (" + this.sanitizeString(tryBlock.exceptionHandler.ExceptionType.ToString()) + ")|");
                        }
                    }

                    // insert catch block beginnings
                    foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                        if (handlerBlock.firstBasicBlockOfHandlerBlock && opIdx == 0) {
                            if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                dotFile.Write("CATCH START (" + this.sanitizeString(handlerBlock.exceptionHandler.ExceptionType.ToString()) + ")|");
                            }
                            else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                dotFile.Write("FINALLY START (" + this.sanitizeString(handlerBlock.exceptionHandler.ExceptionType.ToString()) + ")|");
                            }
                            else {
                                throw new ArgumentException("Do not know how to handle handler.");
                            }
                        }
                    }

                    // check if instruction has an argument
                    if (operation.Value != null) {
                        dotFile.Write(operation.OperationCode.ToString() + " " + this.sanitizeString(operation.Value.ToString()));
                    }
                    else {
                        dotFile.Write(operation.OperationCode.ToString());
                    }

                    // insert try block endings
                    foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                        if (tryBlock.lastBasicBlockOfTryBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                            dotFile.Write("|TRY END (" + this.sanitizeString(tryBlock.exceptionHandler.ExceptionType.ToString()) + ")");
                        }
                    }

                    // insert catch/finally block endings
                    foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                        if (handlerBlock.lastBasicBlockOfHandlerBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                            if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                dotFile.Write("|CATCH END (" + this.sanitizeString(handlerBlock.exceptionHandler.ExceptionType.ToString()) + ")");
                            }
                            else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                dotFile.Write("|FINALLY END (" + this.sanitizeString(handlerBlock.exceptionHandler.ExceptionType.ToString()) + ")");
                            }
                            else {
                                throw new ArgumentException("Do not know how to handle handler.");
                            }
                        }
                    }
                }
                dotFile.WriteLine("}\"]");

                // write all the exits of the basic block to the file
                if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as NoBranchTarget != null) {
                    NoBranchTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as NoBranchTarget);

                    // search index of exit basic block in cfg
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.takenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"blue\" ]");
                            break;
                        }
                    }
                }
                else if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as TryBlockTarget != null) {
                    TryBlockTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as TryBlockTarget);

                    // search index of exit basic block in cfg
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.takenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"blue\" ]");
                            break;
                        }
                    }
                }
                else if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as UnconditionalBranchTarget != null) {
                    UnconditionalBranchTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as UnconditionalBranchTarget);

                    // search index of exit basic block in cfg
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.takenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"blue\" ]");
                            break;
                        }
                    }
                }
                else if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as ConditionalBranchTarget != null) {
                    ConditionalBranchTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as ConditionalBranchTarget);

                    // search index of exit basic block in cfg
                    bool takenTargetFound = false;
                    bool notTakenTargetFound = false;
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.takenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"green\" ]");
                            takenTargetFound = true;
                        }
                        else if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.notTakenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"red\" ]");
                            notTakenTargetFound = true;
                        }
                        else if (takenTargetFound && notTakenTargetFound) {
                            break;
                        }
                    }
                }
                else if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as SwitchBranchTarget != null) {
                    SwitchBranchTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as SwitchBranchTarget);

                    // search index of exit basic block in cfg
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.notTakenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"red\" ]");
                            break;
                        }
                    }

                    // search index for all exit basic blocks in cfg
                    foreach (BasicBlock exitBasicBlock in tempBranch.takenTarget) {
                        for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                            if (methodCfg.basicBlocks.ElementAt(tempIdx) == exitBasicBlock) {
                                dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"green\" ]");
                                break;
                            }
                        }
                    }
                }
                else if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as ExceptionBranchTarget != null) {
                    ExceptionBranchTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as ExceptionBranchTarget);

                    // search index of exit basic block in cfg
                    bool exitTargetFound = false;
                    bool exceptionTargetFound = false;
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.exitTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"green\" ]");
                            exitTargetFound = true;
                        }
                        else if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.exceptionTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"red\" ]");
                            exceptionTargetFound = true;
                        }
                        else if (exitTargetFound && exceptionTargetFound) {
                            break;
                        }
                    }
                }
            }

            // finish graph
            dotFile.WriteLine("}");

            dotFile.Close();



            // dump cfg created from the entry branches
            dotFile = new System.IO.StreamWriter(this.logPath + "\\entryBranches_" + fileName + ".dot");

            // start .dot file graph
            dotFile.WriteLine("digraph G {");

            // write all basic blocks to .dot file
            for (int idx = 0; idx < methodCfg.basicBlocks.Count(); idx++) {

                BasicBlock currentBasicBlock = methodCfg.basicBlocks.ElementAt(idx);

                // write the current basic block to the file and all its instructions
                dotFile.WriteLine("BB" + idx.ToString() + " [shape=record]");
                bool first = true;
                for (int opIdx = 0; opIdx < currentBasicBlock.operations.Count(); opIdx++) {
                    var operation = currentBasicBlock.operations.ElementAt(opIdx);
                    if (first) {
                        dotFile.Write("BB" + idx.ToString() + " [label=\"{");
                        dotFile.Write("NAME: BB" + idx.ToString() + "|");
                        dotFile.Write("ID: " + currentBasicBlock.id.ToString() + "|");
                        dotFile.Write("SEMANTIC ID: " + currentBasicBlock.semanticId.ToString() + "|");
                        first = false;

                        // dump basic block transformation metadata
                        foreach (ITransformationMetadata metadata in currentBasicBlock.transformationMetadata) {
                            if ((metadata as GraphTransformerMetadataBasicBlock) != null) {

                                GraphTransformerMetadataBasicBlock temp = (metadata as GraphTransformerMetadataBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                dotFile.Write("GRAPH_BLOCK (valid ID: " + validPathIdString + ")|");

                                // dump position of the element in the graph (for each valid path)
                                for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                    String positionString = "";
                                    foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                        positionString += position.ToString() + ";";
                                    }
                                    dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                }

                                // dump the valid and invalid interfaces of the graph element (for each valid path)
                                for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {

                                    PathElement pathElement = null;
                                    foreach (PathElement tempElement in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.pathElements) {
                                        if (tempElement.validPathId == temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId) {
                                            pathElement = tempElement;
                                            break;
                                        }
                                    }
                                    if (pathElement == null) {
                                        throw new ArgumentNullException("No path element for valid graph id was found.");
                                    }


                                    String tempOutput = "";
                                    foreach (ITypeReference interfaceInList in pathElement.validInterfaces) {
                                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                                    }
                                    dotFile.Write("valid Interfaces: " + tempOutput + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");

                                    tempOutput = "";
                                    foreach (ITypeReference interfaceInList in pathElement.invalidInterfaces) {
                                        tempOutput += this.sanitizeString(interfaceInList.ToString()) + "; ";
                                    }
                                    dotFile.Write("invalid Interfaces: " + tempOutput + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                }
                            }
                            else if ((metadata as GraphTransformerPredicateBasicBlock) != null) {

                                GraphTransformerPredicateBasicBlock temp = (metadata as GraphTransformerPredicateBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                if (temp.predicateType == GraphOpaquePredicate.True) {
                                    dotFile.Write("TRUE_PREDICATE_BLOCK (valid ID: " + validPathIdString + ")|");

                                    // dump position of the element in the graph (for each valid path)
                                    for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                        String positionString = "";
                                        foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                            positionString += position.ToString() + ";";
                                        }
                                        dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                    }
                                }
                                else if (temp.predicateType == GraphOpaquePredicate.False) {
                                    dotFile.Write("FALSE_PREDICATE_BLOCK (valid ID: " + validPathIdString + ")|");

                                    // dump position of the element in the graph (for each valid path)
                                    for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                        String positionString = "";
                                        foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                            positionString += position.ToString() + ";";
                                        }
                                        dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                    }
                                }
                                else if (temp.predicateType == GraphOpaquePredicate.Random) {
                                    dotFile.Write("RANDOM_PREDICATE_BLOCK (valid ID: " + validPathIdString + ")|");

                                    // dump position of the element in the graph (for each valid path)
                                    for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                        String positionString = "";
                                        foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                            positionString += position.ToString() + ";";
                                        }
                                        dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                    }
                                }
                                else {
                                    throw new ArgumentException("Do not know how to handle opaque predicate type.");
                                }
                            }
                            else if ((metadata as GraphTransformerNextNodeBasicBlock) != null) {

                                GraphTransformerNextNodeBasicBlock temp = (metadata as GraphTransformerNextNodeBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                if (temp.correctNextNode) {
                                    dotFile.Write("CORRECT_NEXT_NODE_BLOCK (valid ID: " + validPathIdString + ")|");

                                    // dump position of the element in the graph (for each valid path)
                                    for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                        String positionString = "";
                                        foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                            positionString += position.ToString() + ";";
                                        }
                                        dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                    }
                                }
                                else {
                                    dotFile.Write("WRONG_NEXT_NODE_BLOCK (valid ID: " + validPathIdString + ")|");

                                    // dump position of the element in the graph (for each valid path)
                                    for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                        String positionString = "";
                                        foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                            positionString += position.ToString() + ";";
                                        }
                                        dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                    }
                                }
                            }
                            else if ((metadata as GraphTransformerDeadCodeBasicBlock) != null) {

                                GraphTransformerDeadCodeBasicBlock temp = (metadata as GraphTransformerDeadCodeBasicBlock);

                                dotFile.Write("DEAD_CODE_BLOCK (template semantic ID: " + temp.semanticId.ToString() + ")|");
                            }
                            else if ((metadata as GraphTransformerStateBasicBlock) != null) {

                                GraphTransformerStateBasicBlock temp = (metadata as GraphTransformerStateBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                dotFile.Write("STATE_BLOCK (valid ID: " + validPathIdString + ")|");

                                // dump position of the element in the graph (for each valid path)
                                for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                    String positionString = "";
                                    foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                        positionString += position.ToString() + ";";
                                    }
                                    dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                }
                            }
                            else if ((metadata as GraphTransformerStateChangeBasicBlock) != null) {

                                GraphTransformerStateChangeBasicBlock temp = (metadata as GraphTransformerStateChangeBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                dotFile.Write("STATE_CHANGE_BLOCK (valid ID: " + validPathIdString + ")|");

                                // dump position of the element in the graph (for each valid path)
                                for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                    String positionString = "";
                                    foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                        positionString += position.ToString() + ";";
                                    }
                                    dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                }
                            }
                            else if ((metadata as GraphTransformerIntermediateBasicBlock) != null) {

                                GraphTransformerIntermediateBasicBlock temp = (metadata as GraphTransformerIntermediateBasicBlock);
                                String validPathIdString = "";
                                for (int linkIdx = 0; linkIdx < temp.correspondingGraphNodes.Count(); linkIdx++) {
                                    validPathIdString += temp.correspondingGraphNodes.ElementAt(linkIdx).validPathId.ToString() + ";";
                                }

                                dotFile.Write("INTERMEDIATE_BASIC_BLOCK (valid ID: " + validPathIdString + ")|");

                                // dump position of the element in the graph (for each valid path)
                                for (int nodeIdx = 0; nodeIdx < temp.correspondingGraphNodes.Count(); nodeIdx++) {
                                    String positionString = "";
                                    foreach (int position in temp.correspondingGraphNodes.ElementAt(nodeIdx).graphNode.positionInGraph) {
                                        positionString += position.ToString() + ";";
                                    }
                                    dotFile.Write("POSITION " + positionString + " (valid ID: " + temp.correspondingGraphNodes.ElementAt(nodeIdx).validPathId.ToString() + ")|");
                                }

                            }
                            else if ((metadata as DevBasicBlock) != null) {

                                DevBasicBlock temp = (metadata as DevBasicBlock);

                                dotFile.Write("DEV_NOTE: " + temp.note + "|");
                            }
                            else {
                                throw new ArgumentException("Do not know how to handle transformation metadata.");
                            }
                        }

                    }
                    else {
                        dotFile.Write("|");
                    }

                    // insert try block beginnings
                    foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                        if (tryBlock.firstBasicBlockOfTryBlock && opIdx == 0) {
                            dotFile.Write("TRY START (" + this.sanitizeString(tryBlock.exceptionHandler.ExceptionType.ToString()) + ")|");
                        }
                    }

                    // insert catch block beginnings
                    foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                        if (handlerBlock.firstBasicBlockOfHandlerBlock && opIdx == 0) {
                            if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                dotFile.Write("CATCH START (" + this.sanitizeString(handlerBlock.exceptionHandler.ExceptionType.ToString()) + ")|");
                            }
                            else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                dotFile.Write("FINALLY START (" + this.sanitizeString(handlerBlock.exceptionHandler.ExceptionType.ToString()) + ")|");
                            }
                            else {
                                throw new ArgumentException("Do not know how to handle handler.");
                            }
                        }
                    }

                    // check if instruction has an argument
                    if (operation.Value != null) {
                        dotFile.Write(operation.OperationCode.ToString() + " " + this.sanitizeString(operation.Value.ToString()));
                    }
                    else {
                        dotFile.Write(operation.OperationCode.ToString());
                    }

                    // insert try block endings
                    foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                        if (tryBlock.lastBasicBlockOfTryBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                            dotFile.Write("|TRY END (" + this.sanitizeString(tryBlock.exceptionHandler.ExceptionType.ToString()) + ")");
                        }
                    }

                    // insert catch block endings
                    foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                        if (handlerBlock.lastBasicBlockOfHandlerBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                            if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                dotFile.Write("|CATCH END (" + this.sanitizeString(handlerBlock.exceptionHandler.ExceptionType.ToString()) + ")");
                            }
                            else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                dotFile.Write("|FINALLY END (" + this.sanitizeString(handlerBlock.exceptionHandler.ExceptionType.ToString()) + ")");
                            }
                            else {
                                throw new ArgumentException("Do not know how to handle handler.");
                            }
                        }
                    }
                }
                dotFile.WriteLine("}\"]");

                foreach (IBranchTarget entry in methodCfg.basicBlocks.ElementAt(idx).entryBranches) {

                    // search index of exit basic block in cfg
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == entry.sourceBasicBlock) {
                            dotFile.WriteLine("BB" + tempIdx.ToString() + " -> BB" + idx.ToString() + "[ color=\"blue\" ]");
                            break;
                        }
                    }
                }
            }

            // finish graph
            dotFile.WriteLine("}");

            dotFile.Close();


            // dump a clean cfg created from the exit branches
            dotFile = new System.IO.StreamWriter(this.logPath + "\\clean_" + fileName + ".dot");

            // start .dot file graph
            dotFile.WriteLine("digraph G {");

            // write all basic blocks to .dot file
            for (int idx = 0; idx < methodCfg.basicBlocks.Count(); idx++) {

                BasicBlock currentBasicBlock = methodCfg.basicBlocks.ElementAt(idx);

                // write the current basic block to the file
                dotFile.WriteLine("BB" + idx.ToString() + " [shape=record]");
                dotFile.WriteLine("BB" + idx.ToString() + " [label=\"\"]");

                // write all the exits of the basic block to the file
                if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as NoBranchTarget != null) {
                    NoBranchTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as NoBranchTarget);

                    // search index of exit basic block in cfg
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.takenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"black\" ]");
                            break;
                        }
                    }
                }
                else if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as TryBlockTarget != null) {
                    TryBlockTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as TryBlockTarget);

                    // search index of exit basic block in cfg
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.takenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"black\" ]");
                            break;
                        }
                    }
                }
                else if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as UnconditionalBranchTarget != null) {
                    UnconditionalBranchTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as UnconditionalBranchTarget);

                    // search index of exit basic block in cfg
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.takenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"black\" ]");
                            break;
                        }
                    }
                }
                else if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as ConditionalBranchTarget != null) {
                    ConditionalBranchTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as ConditionalBranchTarget);

                    // search index of exit basic block in cfg
                    bool takenTargetFound = false;
                    bool notTakenTargetFound = false;
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.takenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"black\" ]");
                            takenTargetFound = true;
                        }
                        else if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.notTakenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"black\" ]");
                            notTakenTargetFound = true;
                        }
                        else if (takenTargetFound && notTakenTargetFound) {
                            break;
                        }
                    }
                }
                else if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as SwitchBranchTarget != null) {
                    SwitchBranchTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as SwitchBranchTarget);

                    // search index of exit basic block in cfg
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.notTakenTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"black\" ]");
                            break;
                        }
                    }

                    // search index for all exit basic blocks in cfg
                    foreach (BasicBlock exitBasicBlock in tempBranch.takenTarget) {
                        for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                            if (methodCfg.basicBlocks.ElementAt(tempIdx) == exitBasicBlock) {
                                dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"black\" ]");
                                break;
                            }
                        }
                    }
                }
                else if (methodCfg.basicBlocks.ElementAt(idx).exitBranch as ExceptionBranchTarget != null) {
                    ExceptionBranchTarget tempBranch = (methodCfg.basicBlocks.ElementAt(idx).exitBranch as ExceptionBranchTarget);

                    // search index of exit basic block in cfg
                    bool exitTargetFound = false;
                    bool exceptionTargetFound = false;
                    for (int tempIdx = 0; tempIdx < methodCfg.basicBlocks.Count(); tempIdx++) {
                        if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.exitTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"black\" ]");
                            exitTargetFound = true;
                        }
                        else if (methodCfg.basicBlocks.ElementAt(tempIdx) == tempBranch.exceptionTarget) {
                            dotFile.WriteLine("BB" + idx.ToString() + " -> BB" + tempIdx.ToString() + "[ color=\"black\" ]");
                            exceptionTargetFound = true;
                        }
                        else if (exitTargetFound && exceptionTargetFound) {
                            break;
                        }
                    }
                }
            }

            // finish graph
            dotFile.WriteLine("}");

            dotFile.Close();

        }
Exemplo n.º 20
0
        // creates a duplicate of the given source basic block with the branch targets to semantically equivalent basic blocks
        // (not necessary the target basic block of the given source basic block)
        private BasicBlock duplicateBasicBlock(MethodCfg originalMethodCfg, MethodCfg methodCfg, BasicBlock sourceBasicBlock) {

            // search for a semantically equal basic block in the unmodified method CFG
            int searchSementicId = sourceBasicBlock.semanticId;
            BasicBlock copiedOriginalTargetBasicBlock = null;
            if (searchSementicId == -1) {
                throw new ArgumentException("No distinct semantic id given to search for.");
            }
            foreach (BasicBlock searchBasicBlock in originalMethodCfg.basicBlocks) {
                if (searchBasicBlock.semanticId == searchSementicId) {
                    copiedOriginalTargetBasicBlock = searchBasicBlock;
                    break;
                }
            }
            if (copiedOriginalTargetBasicBlock == null) {
                throw new ArgumentException("Not able to find semantically equal basic block in copied CFG.");
            }

            // create a new basic block
            BasicBlock newBasicBlock = new BasicBlock();

            // copy simple values
            newBasicBlock.semanticId = copiedOriginalTargetBasicBlock.semanticId;
            newBasicBlock.startIdx = copiedOriginalTargetBasicBlock.startIdx;
            newBasicBlock.endIdx = copiedOriginalTargetBasicBlock.endIdx;

            // copy all operations of the basic block
            foreach (IOperation operation in copiedOriginalTargetBasicBlock.operations) {
                newBasicBlock.operations.Add(this.helperClass.createNewOperation(operation.OperationCode, operation.Value, operation.Location, operation.Offset));
            }

            if (copiedOriginalTargetBasicBlock.tryBlocks.Count() != 0
                || copiedOriginalTargetBasicBlock.handlerBlocks.Count() != 0) {
                throw new ArgumentException("Not implemented yet.");
            }

            // create an exit branch for the new basic block
            if ((copiedOriginalTargetBasicBlock.exitBranch as NoBranchTarget) != null) {

                //throw new ArgumentException("Not implemented yet."); // TODO: problem here with having 2 no branches before a basic block (but not necessarily because all branches are processed and exchanged)

                NoBranchTarget exitBranch = (copiedOriginalTargetBasicBlock.exitBranch as NoBranchTarget);

                // create a copied exit branch
                NoBranchTarget copiedExitBranch = new NoBranchTarget();
                copiedExitBranch.sourceBasicBlock = newBasicBlock;
                newBasicBlock.exitBranch = copiedExitBranch;

                // search for all semantically equal basic blocks in the modified method CFG (as possible targets)
                searchSementicId = exitBranch.takenTarget.semanticId;
                List<BasicBlock> possibleTargetBasicBlocks = new List<BasicBlock>();
                foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                    if (searchBasicBlock.semanticId == searchSementicId) {
                        possibleTargetBasicBlocks.Add(searchBasicBlock);
                    }
                }
                if (possibleTargetBasicBlocks.Count() == 0) {
                    throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                }

                // use a random possible basic block as target
                int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                BasicBlock targetBasicBlock = possibleTargetBasicBlocks.ElementAt(randPosition);

                // set basic block as target for the branch
                targetBasicBlock.entryBranches.Add(copiedExitBranch);
                copiedExitBranch.takenTarget = targetBasicBlock;

            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as UnconditionalBranchTarget != null) {
                UnconditionalBranchTarget exitBranch = (copiedOriginalTargetBasicBlock.exitBranch as UnconditionalBranchTarget);

                // create a copied exit branch
                UnconditionalBranchTarget copiedExitBranch = new UnconditionalBranchTarget();
                copiedExitBranch.sourceBasicBlock = newBasicBlock;
                newBasicBlock.exitBranch = copiedExitBranch;

                // search for all semantically equal basic blocks in the modified method CFG (as possible targets)
                searchSementicId = exitBranch.takenTarget.semanticId;
                List<BasicBlock> possibleTargetBasicBlocks = new List<BasicBlock>();
                foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                    if (searchBasicBlock.semanticId == searchSementicId) {
                        possibleTargetBasicBlocks.Add(searchBasicBlock);
                    }
                }
                if (possibleTargetBasicBlocks.Count() == 0) {
                    throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                }

                // use a random possible basic block as target
                int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                BasicBlock targetBasicBlock = possibleTargetBasicBlocks.ElementAt(randPosition);

                // set basic block as target for the branch
                targetBasicBlock.entryBranches.Add(copiedExitBranch);
                copiedExitBranch.takenTarget = targetBasicBlock;

            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as ConditionalBranchTarget != null) {
                ConditionalBranchTarget exitBranch = (copiedOriginalTargetBasicBlock.exitBranch as ConditionalBranchTarget);

                // create a copied exit branch
                ConditionalBranchTarget copiedExitBranch = new ConditionalBranchTarget();
                copiedExitBranch.sourceBasicBlock = newBasicBlock;
                newBasicBlock.exitBranch = copiedExitBranch;

                // search for all semantically equal basic blocks in the modified method CFG (as possible targets) (for "taken" branch)
                searchSementicId = exitBranch.takenTarget.semanticId;
                List<BasicBlock> possibleTargetBasicBlocks = new List<BasicBlock>();
                foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                    if (searchBasicBlock.semanticId == searchSementicId) {
                        possibleTargetBasicBlocks.Add(searchBasicBlock);
                    }
                }
                if (possibleTargetBasicBlocks.Count() == 0) {
                    throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                }

                // use a random possible basic block as target
                int randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                BasicBlock targetBasicBlock = possibleTargetBasicBlocks.ElementAt(randPosition);

                // set basic block as target for the branch
                targetBasicBlock.entryBranches.Add(copiedExitBranch);
                copiedExitBranch.takenTarget = targetBasicBlock;

                // search for all semantically equal basic blocks in the modified method CFG (as possible targets) (for "not taken" branch)
                searchSementicId = exitBranch.notTakenTarget.semanticId;
                possibleTargetBasicBlocks = new List<BasicBlock>();
                foreach (BasicBlock searchBasicBlock in methodCfg.basicBlocks) {
                    if (searchBasicBlock.semanticId == searchSementicId) {
                        possibleTargetBasicBlocks.Add(searchBasicBlock);
                    }
                }
                if (possibleTargetBasicBlocks.Count() == 0) {
                    throw new ArgumentException("Not able to find any semantically equal basic block in CFG.");
                }

                // use a random possible basic block as target
                randPosition = this.prng.Next(possibleTargetBasicBlocks.Count());
                targetBasicBlock = possibleTargetBasicBlocks.ElementAt(randPosition);

                // set basic block as target for the branch
                targetBasicBlock.entryBranches.Add(copiedExitBranch);
                copiedExitBranch.notTakenTarget = targetBasicBlock;

            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as SwitchBranchTarget != null) {
                throw new ArgumentException("Not implemented yet.");
            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as ExitBranchTarget != null) {

                // create a copied exit branch
                ExitBranchTarget copiedExitBranch = new ExitBranchTarget();
                copiedExitBranch.sourceBasicBlock = newBasicBlock;
                newBasicBlock.exitBranch = copiedExitBranch;

            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as ThrowBranchTarget != null) {
                throw new ArgumentException("Not implemented yet.");
            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as TryBlockTarget != null) {
                throw new ArgumentException("Not implemented yet.");
            }

            else if (copiedOriginalTargetBasicBlock.exitBranch as ExceptionBranchTarget != null) {
                throw new ArgumentException("Not implemented yet.");
            }

            else {
                throw new ArgumentException("Do not know how to handle exit branch.");
            }

            return newBasicBlock;

        }