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

            }

        }
Пример #2
0
        // this function generates and injects code into the given entry branch that moves the pointer from the source node to the target node
        private void injectLinkMoveCode(CfgManipulator cfgManipulator, BasicBlockGraphNodeLink startGraphLink, BasicBlockGraphNodeLink targetGraphLink, IBranchTarget entryBranch, int currentValidPathId, LocalDefinition currentNodeLocal) {

            NodeObject targetNode = targetGraphLink.graphNode;
            NodeObject startNode = startGraphLink.graphNode;
            IBranchTarget branchToManipulate = entryBranch;

            // do nothing if the source node is already the same as the target node
            if (startNode == targetNode) {
                return;
            }

            // check if the pointer have to be moved to the start pointer before it can be moved to the target element
            bool goToStart = false;
            if (startNode.positionInGraph.Count() >= targetNode.positionInGraph.Count()) {
                goToStart = true;
            }
            else {
                for (int idx = 0; idx < startNode.positionInGraph.Count(); idx++) {
                    if (startNode.positionInGraph.ElementAt(idx) != targetNode.positionInGraph.ElementAt(idx)) {
                        goToStart = true;
                        break;
                    }
                }
            }

            // set current graph link (is used for the metadata of the pointer correcting basic blocks
            BasicBlockGraphNodeLink currentGraphLink = new BasicBlockGraphNodeLink(startGraphLink.graphNode, currentValidPathId);

            // check how to move the pointer to the target element
            // => first go to the start pointer
            if (goToStart) {

                // generate and inject code that moves the pointer on a random path forward until the start node of the graph is reached
                while (startNode != this.graph.startingNode) {

                    // generate code to move the pointer to the next node in the graph and inject it
                    int nextNodeIdx = this.prng.Next(this.graphDimension);
                    UnconditionalBranchTarget injectedExitBranch = new UnconditionalBranchTarget();
                    BasicBlock injectedBasicBlock = this.createCodeNextNode(injectedExitBranch, currentGraphLink, currentNodeLocal, nextNodeIdx, true);
                    if ((branchToManipulate as UnconditionalBranchTarget) != null) {
                        UnconditionalBranchTarget tempBranchToManipulate = (branchToManipulate as UnconditionalBranchTarget);
                        cfgManipulator.insertBasicBlockBetweenBranch(tempBranchToManipulate, injectedBasicBlock, injectedExitBranch);
                    }
                    else if ((branchToManipulate as SwitchBranchTarget) != null) {
                        SwitchBranchTarget tempBranchToManipulate = (branchToManipulate as SwitchBranchTarget);
                        cfgManipulator.insertBasicBlockBetweenBranch(tempBranchToManipulate, currentValidPathId, injectedBasicBlock, injectedExitBranch);
                    }
                    else {
                        throw new ArgumentException("Not yet implemented."); // TODO
                    }

                    // set the next branch to manipulate as the newly created exit branch
                    branchToManipulate = injectedExitBranch;

                    // move pointer to the next node in the graph or to the start node if it does not exist
                    if (startNode.nodeObjects[nextNodeIdx] == null) {
                        startNode = this.graph.startingNode;
                    }
                    else {
                        startNode = startNode.nodeObjects[nextNodeIdx];
                    }

                    // create new graph link for the current node
                    currentGraphLink = new BasicBlockGraphNodeLink(startNode, currentValidPathId);
                }

                // generate and inject code that moves the pointer to the correct position of the given graph node
                foreach (int nextNodeIdx in targetNode.positionInGraph) {

                    // generate code to move the pointer to the next node in the graph and inject it
                    UnconditionalBranchTarget injectedExitBranch = new UnconditionalBranchTarget();
                    BasicBlock injectedBasicBlock = this.createCodeNextNode(injectedExitBranch, currentGraphLink, currentNodeLocal, nextNodeIdx, true);
                    if ((branchToManipulate as UnconditionalBranchTarget) != null) {
                        UnconditionalBranchTarget tempBranchToManipulate = (branchToManipulate as UnconditionalBranchTarget);
                        cfgManipulator.insertBasicBlockBetweenBranch(tempBranchToManipulate, injectedBasicBlock, injectedExitBranch);
                    }
                    else if ((branchToManipulate as SwitchBranchTarget) != null) {
                        SwitchBranchTarget tempBranchToManipulate = (branchToManipulate as SwitchBranchTarget);
                        cfgManipulator.insertBasicBlockBetweenBranch(tempBranchToManipulate, currentValidPathId, injectedBasicBlock, injectedExitBranch);
                    }
                    else {
                        throw new ArgumentException("Not yet implemented."); // TODO
                    }

                    // set the next branch to manipulate as the newly created exit branch
                    branchToManipulate = injectedExitBranch;

                    // move pointer to the next node in the graph or to the start node if it does not exist
                    if (startNode.nodeObjects[nextNodeIdx] == null) {
                        startNode = this.graph.startingNode;
                    }
                    else {
                        startNode = startNode.nodeObjects[nextNodeIdx];
                    }

                    // create new graph link for the current node
                    currentGraphLink = new BasicBlockGraphNodeLink(startNode, currentValidPathId);
                }
            }

            // => go on a direct path to the target element
            else {

                // generate and inject code that moves the pointer to the correct position of the given graph node
                for (int idx = startNode.positionInGraph.Count(); idx < targetNode.positionInGraph.Count(); idx++) {

                    // generate code to move the pointer to the next node in the graph and inject it
                    UnconditionalBranchTarget injectedExitBranch = new UnconditionalBranchTarget();
                    BasicBlock injectedBasicBlock = this.createCodeNextNode(injectedExitBranch, currentGraphLink, currentNodeLocal, targetNode.positionInGraph.ElementAt(idx), true);
                    if ((branchToManipulate as UnconditionalBranchTarget) != null) {
                        UnconditionalBranchTarget tempBranchToManipulate = (branchToManipulate as UnconditionalBranchTarget);
                        cfgManipulator.insertBasicBlockBetweenBranch(tempBranchToManipulate, injectedBasicBlock, injectedExitBranch);
                    }
                    else if ((branchToManipulate as SwitchBranchTarget) != null) {
                        SwitchBranchTarget tempBranchToManipulate = (branchToManipulate as SwitchBranchTarget);
                        cfgManipulator.insertBasicBlockBetweenBranch(tempBranchToManipulate, currentValidPathId, injectedBasicBlock, injectedExitBranch);
                    }
                    else {
                        throw new ArgumentException("Not yet implemented."); // TODO
                    }

                    // set the next branch to manipulate as the newly created exit branch
                    branchToManipulate = injectedExitBranch;

                    // move pointer to the next node in the graph or to the start node if it does not exist
                    if (startNode.nodeObjects[targetNode.positionInGraph.ElementAt(idx)] == null) {
                        startNode = this.graph.startingNode;
                    }
                    else {
                        startNode = startNode.nodeObjects[targetNode.positionInGraph.ElementAt(idx)];
                    }

                    // create new graph link for the current node
                    currentGraphLink = new BasicBlockGraphNodeLink(startNode, currentValidPathId);
                }

            }

            // check if the final reached node is the same as the target node
            if (startNode != targetNode) {
                throw new ArgumentException("Current node and target node are not the same.");
            }

        }
Пример #3
0
        // this functions creates metadata for the given basic block and adds it
        private bool createAndAddMetadata(BasicBlock currentBasicBlock) {

            // get metadata of entry basic block (if exists)
            IGraphTransformerMetadata previousMetadata = null;
            BasicBlock previousBasicBlock = null;
            IBranchTarget previousExitBranch = null;
            for (int i = 0; i < currentBasicBlock.entryBranches.Count(); i++) {

                previousBasicBlock = currentBasicBlock.entryBranches.ElementAt(i).sourceBasicBlock;

                for (int j = 0; j < previousBasicBlock.transformationMetadata.Count(); j++) {
                    // get graph transformer metadata for basic blocks
                    if ((previousBasicBlock.transformationMetadata.ElementAt(j) as IGraphTransformerMetadata) == null) {
                        continue;
                    }
                    previousMetadata = (previousBasicBlock.transformationMetadata.ElementAt(j) as IGraphTransformerMetadata);
                    previousExitBranch = currentBasicBlock.entryBranches.ElementAt(i);
                    break;
                }
                if (previousMetadata != null) {
                    break;
                }
            }
            // skip basic block if there is no metadata in one of the entry basic blocks
            if (previousMetadata == null) { // TODO: here is room for optimization => do not skip it
                return false;
            }
            List<BasicBlockGraphNodeLink> previousLinks = previousMetadata.correspondingGraphNodes;

            // choose the next nodes of the obfuscation graph for the current basic block
            NodeObject[] currentNodes = new NodeObject[this.graph.graphValidPathCount];

            // check if previous basic block has links to the obfuscation graph for all existing valid paths
            // (if previous basic block for example was a "state change" basic block it can only have one link to the obfuscation graph)
            // => just copy obfuscation graph nodes of previous basic block if it contains all valid paths
            if (previousLinks.Count() == this.graph.graphValidPathCount) {
                for (int currentValidPathId = 0; currentValidPathId < this.graph.graphValidPathCount; currentValidPathId++) {
                    bool found = false;
                    for (int i = 0; i < previousLinks.Count(); i++) {
                        if (previousLinks.ElementAt(i).validPathId == currentValidPathId) {
                            currentNodes[currentValidPathId] = previousLinks.ElementAt(i).graphNode;
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        throw new ArgumentException("Was not able to find link to obfuscation graph in previous basic block for at least one valid path.");
                    }
                }
            }

            // previous basic block does not contain all valid paths
            // => copy all existing valid paths links and choose random links for the missing ones
            else {

                for (int currentValidPathId = 0; currentValidPathId < this.graph.graphValidPathCount; currentValidPathId++) {
                    bool found = false;
                    for (int i = 0; i < previousLinks.Count(); i++) {
                        if (previousLinks.ElementAt(i).validPathId == currentValidPathId) {
                            currentNodes[currentValidPathId] = previousLinks.ElementAt(i).graphNode;
                            found = true;
                            break;
                        }
                    }

                    // if a link for the current valid path does not exist
                    // => choose randomly a node in the obfuscation graph on the current valid path
                    if (!found) {
                        int moveCount = this.prng.Next(this.graphDepth);
                        NodeObject nextNode = this.graph.startingNode;
                        for (int move = 0; move < moveCount; move++) {
                            for (int i = 0; i < nextNode.nodeObjects.Count(); i++) {

                                // if the child node does not belong to a valid path
                                // => skip it
                                if (nextNode.nodeObjects[i].elementOfValidPath.Count() == 0) {
                                    continue;
                                }

                                // the child node belongs to a valid path
                                // => check if it is the correct valid path
                                else {
                                    // if the child node belongs to the correct valid path
                                    // => set next node to it
                                    if (nextNode.nodeObjects[i].elementOfValidPath.Contains(currentValidPathId)) {
                                        nextNode = nextNode.nodeObjects[i];
                                        break;
                                    }
                                }
                            }
                            if (nextNode == null) {
                                throw new ArgumentException("Not able to find correct child node.");
                            }
                        }

                        currentNodes[currentValidPathId] = nextNode;

                    }
                }
            }

            NodeObject[] nextNodes = new NodeObject[this.graph.graphValidPathCount];
            for (int currentValidPathId = 0; currentValidPathId < currentNodes.Count(); currentValidPathId++) {

                // choose randomly if the pointer of the current valid path should be moved forward
                // => move the pointer of the current valid path forward
                if (this.prng.Next(2) == 0) {

                    // get the next node of the valid path
                    NodeObject nextNode = null;
                    int nextNodeIdx = 0;
                    this.getNextNode(ref nextNode, ref nextNodeIdx, currentNodes, currentValidPathId);
                    nextNodes[currentValidPathId] = nextNode;

                }

                // => do not move the pointer of the current valid path forward
                else {

                    // set next node in the graph to the current one (it was not changed)
                    nextNodes[currentValidPathId] = currentNodes[currentValidPathId];

                }
            }

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

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

            currentBasicBlock.transformationMetadata.Add(metadata);

            return true;

        }
Пример #4
0
        // this function injects an opaque predicate to the target branch
        private void injectOpaquePredicateCode(CfgManipulator cfgManipulator, Target target, ref ConditionalBranchTarget opaqueExitBranch, IBranchTarget targetBranch, BasicBlockGraphNodeLink link, int currentValidPathId, int opaquePredicate, LocalDefinition currentNodeLocal) {

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

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

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

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

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

                        break;
                    }

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

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

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

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

                        break;
                    }

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

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

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

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

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

        }
Пример #5
0
        // this function injects an opaque predicate to the target branch
        private void injectOpaquePredicateCode(CfgManipulator cfgManipulator, MethodCfg methodCfg, BasicBlock targetBasicBlock, IBranchTarget targetBranch, BasicBlockGraphNodeLink link, int opaquePredicate, LocalDefinition currentNodeLocal) {

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

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

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

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

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

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

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

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

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

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

                        break;
                    }

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

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

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

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

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

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

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

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

                        break;
                    }

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

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

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

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

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

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

        }
Пример #7
0
        // this function generates code to move the current pointer to the next child node (or start node if there is no next child node)
        private BasicBlock createCodeNextNode(IBranchTarget usedExitBranch, BasicBlockGraphNodeLink graphLink, LocalDefinition currentNodeLocal, int index, bool correctNextNode) {

            // create graph transformer metadata for the basic blocks
            GraphTransformerNextNodeBasicBlock metadata = new GraphTransformerNextNodeBasicBlock();
            metadata.correctNextNode = correctNextNode;
            metadata.correspondingGraphNodes.Add(graphLink);
            
            // create new basic block
            BasicBlock nextNodeBasicBlock = new BasicBlock();
            nextNodeBasicBlock.startIdx = 0;
            nextNodeBasicBlock.endIdx = 0;
            nextNodeBasicBlock.transformationMetadata.Add(metadata);

            nextNodeBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));
            nextNodeBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4, index)); // TODO perhaps a more dynamically calculated index?
            nextNodeBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Callvirt, this.interfaceChildNodesGet));
            nextNodeBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Stloc, currentNodeLocal));

            // check which exit branch is used to inject the code to the cfg and generate code for it accordingly
            if ((usedExitBranch as NoBranchTarget) != null) {
                nextNodeBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Nop));
            }
            else if ((usedExitBranch as UnconditionalBranchTarget) != null) {
                nextNodeBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Br));
            }
            else {
                throw new ArgumentException("Do not know how to generate code for given exit branch.");
            }

            // add exit branch to newly created basic block
            nextNodeBasicBlock.exitBranch = usedExitBranch;
            usedExitBranch.sourceBasicBlock = nextNodeBasicBlock;

            return nextNodeBasicBlock;

        }
Пример #8
0
        // this function generates code for an opaque predicate that evaluates to "true"
        // => the "taken" branch of the conditional branch have to be taken for the correct code path
        private void createCodeTruePredicate(ref BasicBlock outStartBasicBlock, ref ConditionalBranchTarget outConditionalBranch,
            BasicBlockGraphNodeLink link, LocalDefinition currentNodeLocal) {

            // create a basic block that checks the opaque predicate (this check evaluates to "true")
            BasicBlock startBasicBlock = new BasicBlock();
            startBasicBlock.startIdx = 0;
            startBasicBlock.endIdx = 0;

            // add graph transformer metadata to the basic block
            GraphTransformerPredicateBasicBlock metadata = new GraphTransformerPredicateBasicBlock();
            metadata.predicateType = GraphOpaquePredicate.True;
            metadata.correspondingGraphNodes.Add(link);
            startBasicBlock.transformationMetadata.Add(metadata);

            // search for the valid and invalid interfaces list of the current valid path id
            List<ITypeReference> validInterfaces = null;
            List<ITypeReference> invalidInterfaces = null;
            foreach (PathElement pathElement in link.graphNode.pathElements) {
                if (pathElement.validPathId == link.validPathId) {
                    validInterfaces = pathElement.validInterfaces;
                    invalidInterfaces = pathElement.invalidInterfaces;
                }
            }
            if (validInterfaces == null
                || invalidInterfaces == null) {
                throw new ArgumentException("No valid/invalid interface list was found.");
            }

            emitPredicateCode(startBasicBlock, currentNodeLocal, validInterfaces, invalidInterfaces);

            // create the conditional branch for the checking basic block (taken => correct code; not taken => dead code)
            ConditionalBranchTarget startBasicBlockExitBranch = new ConditionalBranchTarget();
            startBasicBlockExitBranch.sourceBasicBlock = startBasicBlock;
            startBasicBlock.exitBranch = startBasicBlockExitBranch;

            // create the dead code for this opaque predicate
            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(startBasicBlockExitBranch);
            startBasicBlockExitBranch.notTakenTarget = deadCodeBasicBlock;

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

            // set the created basic block and conditional jumps as output
            outStartBasicBlock = startBasicBlock;
            outConditionalBranch = startBasicBlockExitBranch;

        }
Пример #9
0
 // Generates code for an opaque predicate evaluating to a random value.
 // => Both branches point to basic blocks with equal semantics.
 private void createCodeRandomPredicate(ref BasicBlock outStartBasicBlock, ref ConditionalBranchTarget outConditionalBranch,
     BasicBlockGraphNodeLink link, LocalDefinition currentNodeLocal)
 {
     throw new ArgumentException("Not implemented."); // TODO: will improve the probabilistic control flow
 }
Пример #10
0
        // this function generates code for an opaque predicate that evaluates to "false"
        // => the "not taken" branch of the conditional branch have to be taken for the correct code path
        private void createCodeFalsePredicate(ref BasicBlock outStartBasicBlock, ref ConditionalBranchTarget outConditionalBranch, BasicBlockGraphNodeLink link, LocalDefinition currentNodeLocal) {

            // create a basic block that checks the opaque predicate (this check evaluates to "false")
            BasicBlock startBasicBlock = new BasicBlock();
            startBasicBlock.startIdx = 0;
            startBasicBlock.endIdx = 0;

            // add graph transformer metadata to the basic block
            GraphTransformerPredicateBasicBlock metadata = new GraphTransformerPredicateBasicBlock();
            metadata.predicateType = GraphOpaquePredicate.False;
            metadata.correspondingGraphNodes.Add(link);
            startBasicBlock.transformationMetadata.Add(metadata);

            // search for the valid and invalid interfaces list of the current valid path id
            List<ITypeReference> validInterfaces = null;
            List<ITypeReference> invalidInterfaces = null;
            foreach (PathElement pathElement in link.graphNode.pathElements) {
                if (pathElement.validPathId == link.validPathId) {
                    validInterfaces = pathElement.validInterfaces;
                    invalidInterfaces = pathElement.invalidInterfaces;
                }
            }
            if(validInterfaces == null
                || invalidInterfaces == null) {
                    throw new ArgumentException("No valid/invalid interface list was found.");
            }

            // add a random check to the code
            // important: for this predicate the dead code is reached by the "taken" branch and the correct code is reached by the "not taken" branch
            int randPosition;
            ITypeReference interfaceToCheck = null;
            switch (this.prng.Next(8)) {
                case 0:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(validInterfaces.Count());
                    interfaceToCheck = validInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brfalse, 0));
                    break;

                case 1:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(validInterfaces.Count());
                    interfaceToCheck = validInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4_0));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brtrue, 0));
                    break;

                case 2:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(validInterfaces.Count());
                    interfaceToCheck = validInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4_1));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brfalse, 0));
                    break;

                case 3:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(validInterfaces.Count());
                    interfaceToCheck = validInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brtrue, 0));
                    break;

                case 4:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(invalidInterfaces.Count());
                    interfaceToCheck = invalidInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brtrue, 0));
                    break;

                case 5:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(invalidInterfaces.Count());
                    interfaceToCheck = invalidInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4_0));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brfalse, 0));
                    break;

                case 6:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(invalidInterfaces.Count());
                    interfaceToCheck = invalidInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Cgt_Un));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldc_I4_1));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brtrue, 0));
                    break;

                case 7:
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldloc, currentNodeLocal));

                    randPosition = this.prng.Next(invalidInterfaces.Count());
                    interfaceToCheck = invalidInterfaces.ElementAt(randPosition);
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Isinst, interfaceToCheck));

                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ldnull));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Ceq));
                    startBasicBlock.operations.Add(this.helperClass.createNewOperation(OperationCode.Brfalse, 0));
                    break;

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

            // create the conditional branch for the checking basic block (not taken => correct code; taken => dead code)
            ConditionalBranchTarget startBasicBlockExitBranch = new ConditionalBranchTarget();
            startBasicBlockExitBranch.sourceBasicBlock = startBasicBlock;
            startBasicBlock.exitBranch = startBasicBlockExitBranch;


            // create the dead code for this opaque predicate
            BasicBlock deadCodeBasicBlock = new BasicBlock();
            deadCodeBasicBlock.startIdx = 0;
            deadCodeBasicBlock.endIdx = 0;

            // set the dead code basic block as "taken" target for the conditional branch of the checking basic block
            deadCodeBasicBlock.entryBranches.Add(startBasicBlockExitBranch);
            startBasicBlockExitBranch.takenTarget = deadCodeBasicBlock;

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

            // set the created basic block and conditional jumps as output
            outStartBasicBlock = startBasicBlock;
            outConditionalBranch = startBasicBlockExitBranch;

        }