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