Пример #1
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;
                }

            }

        }
Пример #2
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;
                }

            }

        }
Пример #3
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;

            }

        }
Пример #4
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;
                }

            }

        }
Пример #5
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;
        }
Пример #6
0
        // this function generates code for the "state change"
        private void createCodeStateChange(ref BasicBlock outStateChangeBasicBlock, ref SwitchBranchTarget outStateChangeExitBranch, GraphRandomStateGenerator randomStateGenerator, BasicBlockGraphNodeLink link, LocalDefinition intStateLocal) {

            // create a basic block to change the current global state
            BasicBlock stateChangeBasicBlock = new BasicBlock();
            stateChangeBasicBlock.startIdx = 0;
            stateChangeBasicBlock.endIdx = 0;

            // create graph transformer metadata for the basic block
            GraphTransformerStateChangeBasicBlock metadataChange = new GraphTransformerStateChangeBasicBlock();
            metadataChange.correspondingGraphNodes.Add(link);
            stateChangeBasicBlock.transformationMetadata.Add(metadataChange);

            // generate code for setting the new global state
            List<IOperation> tempOperations = randomStateGenerator.generateCodeSetRandomState(intStateLocal);
            stateChangeBasicBlock.operations.AddRange(tempOperations);

            // create switch statement for the "state switch"
            stateChangeBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, intStateLocal));
            uint[] switchSize = new uint[this.graph.graphValidPathCount];
            stateChangeBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Switch, switchSize));

            // create exit branch for the new state basic block
            SwitchBranchTarget stateChangeExitBranch = new SwitchBranchTarget();
            stateChangeExitBranch.sourceBasicBlock = stateChangeBasicBlock;
            stateChangeBasicBlock.exitBranch = stateChangeExitBranch;

            // create the dead code for this "state switch"
            BasicBlock deadCodeBasicBlock = new BasicBlock();
            deadCodeBasicBlock.startIdx = 0;
            deadCodeBasicBlock.endIdx = 0;

            // set the dead code basic block as "not taken" target for the conditional branch of the checking basic block
            deadCodeBasicBlock.entryBranches.Add(stateChangeExitBranch);
            stateChangeExitBranch.notTakenTarget = deadCodeBasicBlock; // TODO at the moment always the not taken branch of the switch statement is the dead code basic block

            // generate dead code for the dead code basic block
            GraphTransformerDeadCodeBasicBlock deadCodeMetadata = new GraphTransformerDeadCodeBasicBlock();
            deadCodeBasicBlock.transformationMetadata.Add(deadCodeMetadata);

            outStateChangeBasicBlock = stateChangeBasicBlock;
            outStateChangeExitBranch = stateChangeExitBranch;

        }