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; } }
// 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."); } }