/// <summary> /// The meshing algorithm, which will mesh the unconditional jumps in a routine /// </summary> /// <param name="rtn">The routine which will be meshed up</param> public static void MeshUnconditionals(Routine rtn) { /// Meshing of the unconditional jumps foreach (Function funct in rtn.Functions) { List <BasicBlock> basicblocks = funct.BasicBlocks.FindAll(x => x.Instructions.Last().statementType == Objects.Common.StatementType.UnconditionalJump); foreach (BasicBlock bb in basicblocks) { int i = Randomizer.SingleNumber(0, 100); if (i <= Common.UnconditionalMeshingProbability) { BasicBlock originalSuccessor = bb.getSuccessors.First(); BasicBlock falseLane = new BasicBlock(bb.parent); //The false lane involves fake variables only in other to provided the correct output falseLane.Involve = BasicBlock.InvolveInFakeCodeGeneration.FakeVariablesOnly; falseLane.Meshable = false; BasicBlock trueLane = new BasicBlock(bb.parent); //The true lane should involve both fake and original variables in other to provided the wrong output if (funct.containsDivisionModulo == false || originalSuccessor.Instructions.FindAll(x => x.TACtext.Contains("return")).Count > 0) { trueLane.Involve = BasicBlock.InvolveInFakeCodeGeneration.Both; } trueLane.Meshable = false; trueLane.inFakeLane = true; //Linking first the false lane bb.LinkToSuccessor(falseLane, true); //Creating the jump to the true lane MakeInstruction.RandomConditionalJump(bb.Instructions.Last(), Instruction.ConditionType.AlwaysFalse, trueLane); ExpandMainRoute(falseLane, originalSuccessor, false); ExpandFakeRoute(trueLane, originalSuccessor, false); } } } }
/// <summary> /// Expands the Main Route into the CFG, creating the conditional jump for both Main Route and Fake Route /// </summary> /// <param name="fake1">The first fake basic block to be used in the expansion</param> /// <param name="mainLaneBB">The original basic block we should jump to stay in the Main Route</param> /// <param name="atFakeCodeGeneration">Wheter we are or not at the fake code generation phase</param> private static void ExpandMainRoute(BasicBlock fake1, BasicBlock originalSuccessor, bool atFakeCodeGeneration) { //Fetching the Conditional Jump (AlwaysFalse) created in the previous basic block Instruction originalInstruction = fake1.getPredecessors.First().Instructions.Last(); //Defining the constant and relational operator for the fake1 conditional jump Instruction.RelationalOperationType relationalOperation; int rightValue = 0; if (originalInstruction.GetConstFromCondition() >= originalInstruction.GetVarFromCondition().fixedMax.Value) { //If the variable's fixed minimun is diferent from the global min plus the maximun loop range, we should try //to get a value different from the variable's fixed minimun in order to have a more belieavable code do { rightValue = Randomizer.SingleNumber(Common.GlobalMinValue + Common.LoopConditionalJumpMaxRange, originalInstruction.GetVarFromCondition().fixedMin.Value); } while (rightValue == originalInstruction.GetVarFromCondition().fixedMin.Value&& originalInstruction.GetVarFromCondition().fixedMin.Value != Common.GlobalMinValue + Common.LoopConditionalJumpMaxRange); relationalOperation = (Instruction.RelationalOperationType) Randomizer.OneFromMany(Instruction.RelationalOperationType.Smaller, Instruction.RelationalOperationType.SmallerOrEquals); } else { //If the variable's fixed maximun is diferent from the global max minus the maximun loop range, we should try //to get a value different from the variable's fixed maximun in order to have a more belieavable code do { rightValue = Randomizer.SingleNumber(originalInstruction.GetVarFromCondition().fixedMax.Value, Common.GlobalMaxValue - Common.LoopConditionalJumpMaxRange); } while (rightValue == originalInstruction.GetVarFromCondition().fixedMax.Value&& originalInstruction.GetVarFromCondition().fixedMax.Value != Common.GlobalMaxValue - Common.LoopConditionalJumpMaxRange); relationalOperation = (Instruction.RelationalOperationType) Randomizer.OneFromMany(Instruction.RelationalOperationType.Greater, Instruction.RelationalOperationType.GreaterOrEquals); } //Creating and expanding the false lane that stays in the Main Route fake1.LinkToSuccessor(ExpandMainRoute(originalSuccessor), true); //Creating fake2 to hold the true lane for the conditional jump BasicBlock fake2 = new BasicBlock(fake1.parent); fake2.Meshable = false; if (fake2.parent.containsDivisionModulo == false || originalSuccessor.Instructions.FindAll(x => x.TACtext.Contains("return")).Count > 0) { fake2.Involve = BasicBlock.InvolveInFakeCodeGeneration.Both; } //Creating the conditional jump (always false) to fake route Variable var = originalInstruction.GetVarFromCondition(); MakeInstruction.ConditionalJump(fake1.Instructions.Last(), var, rightValue, relationalOperation, fake2); //Expanding the fake route ExpandFakeRoute(fake2, originalSuccessor, atFakeCodeGeneration); }
/// <summary> /// Updates all CALLs according to the number of fake and original parameters of the called functions /// </summary> public static void UpdateAllFunctionCalls(Function func) { //We use a dictionary to store the "call" instruction and its index inside the basic block Dictionary <Instruction, int> allCalls = new Dictionary <Instruction, int>(); List <Instruction> bbCalls = new List <Instruction>(); foreach (BasicBlock bb in func.BasicBlocks) { //We collect all "call" instructions in this basic block bbCalls = bb.Instructions.FindAll(x => x.TACtext.Contains("call") && !x.TACtext.Contains("printf") && !x.TACtext.Contains("scanf")); foreach (Instruction ins in bbCalls) { //Storing all "call" instructions in the actual basic block with their indexes allCalls.Add(ins, bb.Instructions.IndexOf(ins)); } } //We check wheter we have any "call" instruction in this function if (allCalls.Count > 0) { foreach (Instruction call in allCalls.Keys) { //Splitting the call in tokens - tokens[0] = "call", tokens[1] = "function_ID", tokens[2] = "numParams" string[] tokens = call.TACtext.Split(' '); //Checking wheter if the called function is present in our routine (internal function) if (func.parent.Functions.Exists(x => x.ID == tokens[1])) { //Getting the number of parameters to update it later int numParams = int.Parse(tokens[2]); //Fetching fake input parameters List <Variable> fakeInputsParams = func.LocalVariables.FindAll(x => x.kind == Variable.Kind.Input && x.fake == true); //Number of lines that are shifted during the injection of fake "param" instructions int shift = 0; foreach (Variable fakeInputVar in fakeInputsParams) { Instruction param = new Instruction(call.parent); MakeInstruction.ProceduralParam(param, fakeInputVar, null); //Inserting the "param" instruction right before the "call" instruction call.parent.Instructions.Insert(allCalls[call] + shift, param); shift++; //Updating the number of parameters for this call numParams++; } //Updating the TAC text of the call with the new number of parameters call.parent.Instructions[allCalls[call] + shift].TACtext = string.Join(" ", "call", tokens[1], numParams); } } } }
/// <summary> /// Inserts two additional instructions for constant coverage /// </summary> /// <param name="const_inst">The instruction with a constant value</param> /// <param name="const_value">Numerical constant value to be covered</param> private static void ProcessConstant(Instruction const_inst, int const_value) { List <int> two_places = Randomizer.MultipleNumbers(2, 0, const_inst.parent.Instructions.BinarySearch(const_inst), true, true); Instruction nop1 = new Instruction(const_inst.parent); Instruction nop2 = new Instruction(const_inst.parent); // We assume that we need 4 bytes for each constant. Variable t1 = const_inst.parent.parent.NewLocalVariable(Variable.Purpose.ConstRecalculation, Objects.Common.MemoryRegionSize.Integer); Variable t2 = const_inst.parent.parent.NewLocalVariable(Variable.Purpose.ConstRecalculation, Objects.Common.MemoryRegionSize.Integer); int first_number = Randomizer.SingleNumber(Common.GlobalMinValue, Common.GlobalMaxValue); Instruction.ArithmeticOperationType op = first_number < const_value ? Instruction.ArithmeticOperationType.Addition : Instruction.ArithmeticOperationType.Subtraction; int second_number = Math.Abs(first_number - const_value); MakeInstruction.Copy(nop1, t2, null, first_number); MakeInstruction.FullAssignment(nop2, t1, t2, null, second_number, op); const_inst.parent.Instructions.Insert(two_places[1], nop2); const_inst.parent.Instructions.Insert(two_places[0], nop1); const_inst.ModifyConstInstruction(t1, const_value); }
/// <summary> /// Function to make a Conditional Jump out of a Nop. /// </summary> /// <param name="ins">The nop we want to work on.</param> private static void GenerateConditionalJump(Instruction ins) { /* * Before doing anything, we have to split the basic block holding this * instruction, so we can make a conditional jump at the end of the * new basic block, unless it is already the last instruction. */ if (!ins.Equals(ins.parent.Instructions.Last())) { ins.parent.SplitAfterInstruction(ins); } // We create a jump target. BasicBlock jumptarget = new BasicBlock(ins.parent.parent); // We make a random conditional jump here, which has to be always false. MakeInstruction.RandomConditionalJump(ins, Instruction.ConditionType.AlwaysFalse, jumptarget); //We expand the Fake Route as we did during meshing Meshing.ExpandFakeRoute(jumptarget, ins.parent.getSuccessors.Last(), true); }
/// <summary> /// Expands the Main Route into the CFG, inserting "FakeVariablesOnly" basic blocks and random conditional jump /// between them /// </summary> /// <param name="originaltarget">The basic block we should go to stay in the Main Route</param> private static BasicBlock ExpandMainRoute(BasicBlock originaltarget) { // Creating a new basic block BasicBlock fake1 = new BasicBlock(originaltarget.parent); fake1.Instructions.Add(new Instruction(fake1)); fake1.Meshable = false; // Creating the second fake block BasicBlock fake2 = new BasicBlock(originaltarget.parent); fake2.Instructions.Add(new Instruction(fake2)); // Starting the linking MakeInstruction.UnconditionalJump(fake1.Instructions.Last(), fake2); BasicBlock polyrequtarget = null; // Creating a clone of the original target in order to make the CFT more obfuscated if (originaltarget.Instructions.Last().statementType == Objects.Common.StatementType.UnconditionalJump) { polyrequtarget = new BasicBlock(originaltarget, originaltarget.getSuccessors); } else { polyrequtarget = originaltarget; } // And now setting the edges MakeInstruction.UnconditionalJump(fake2.Instructions.Last(), polyrequtarget); // And then converting its nop instruction into a ConditionalJump MakeInstruction.RandomConditionalJump(fake1.Instructions.Last(), Instruction.ConditionType.Random, originaltarget); return(fake1); }
/// <summary> /// Makes random conditional jump instruction + links basic blocks and sets RefVars /// </summary> /// <param name="nop">NoOperation instruction (will be made into ConditionalJump)</param> /// <param name="condition">Type of condition</param> /// <param name="target">Target basic block the control flow is transfered to, if the relation holds true.</param> public static void RandomConditionalJump(Instruction nop, Instruction.ConditionType condition, BasicBlock target) { if (nop.statementType != Objects.Common.StatementType.NoOperation && nop.statementType != Objects.Common.StatementType.UnconditionalJump) { throw new ObfuscatorException("Only NoOperation and UnconditionalJump instructions can be modified to ConditionalJump!"); } if (nop.parent == null || nop.parent.parent == null) { throw new ObfuscatorException("Instruction -> basic block -> function parent link is broken."); } if (nop.parent.parent != target.parent) { throw new ObfuscatorException("The instruction and the basic block should be contained in the same function."); } Variable var = FakeParameters.GetRandom(nop.parent.parent); if (var.fixedMax.HasValue && var.fixedMax.Value > Common.GlobalMaxValue) { throw new ObfuscatorException("The fixedMax value is greated then the globally accepted maximum."); } if (var.fixedMin.HasValue && var.fixedMin.Value < Common.GlobalMinValue) { throw new ObfuscatorException("The fixedMin value is smaller then the globally accepted minimum."); } int right_value = 0; Instruction.RelationalOperationType relop = Instruction.RelationalOperationType.Equals; bool use_min_limit = false; // Here we chose to use a FixedMin or FixedMax for logical relation if (var.fixedMin.HasValue && var.fixedMax.HasValue) { use_min_limit = (bool)Randomizer.OneFromMany(true, false); } else if (var.fixedMin.HasValue) { use_min_limit = true; } if (use_min_limit) // FixedMin will be used { right_value = Randomizer.OneFromSectionWithDescendingProbability(var.fixedMin.Value, Common.GlobalMinValue + Common.LoopConditionalJumpMaxRange); switch (condition) { case Instruction.ConditionType.AlwaysTrue: relop = (Instruction.RelationalOperationType)Randomizer.OneFromMany(Instruction.RelationalOperationType.Greater, Instruction.RelationalOperationType.GreaterOrEquals); break; case Instruction.ConditionType.AlwaysFalse: relop = (Instruction.RelationalOperationType)Randomizer.OneFromMany(Instruction.RelationalOperationType.Smaller, Instruction.RelationalOperationType.SmallerOrEquals); break; case Instruction.ConditionType.Random: relop = (Instruction.RelationalOperationType)Randomizer.OneFromMany(Instruction.RelationalOperationType.Smaller, Instruction.RelationalOperationType.SmallerOrEquals, Instruction.RelationalOperationType.Greater, Instruction.RelationalOperationType.GreaterOrEquals); break; default: throw new ObfuscatorException("Unrecognized condition type."); } } if (!use_min_limit) // FixedMax will be used { right_value = Randomizer.OneFromSectionWithDescendingProbability(var.fixedMax.Value, Common.GlobalMaxValue - Common.LoopConditionalJumpMaxRange); switch (condition) { case Instruction.ConditionType.AlwaysTrue: relop = (Instruction.RelationalOperationType)Randomizer.OneFromMany(Instruction.RelationalOperationType.Smaller, Instruction.RelationalOperationType.SmallerOrEquals); break; case Instruction.ConditionType.AlwaysFalse: relop = (Instruction.RelationalOperationType)Randomizer.OneFromMany(Instruction.RelationalOperationType.Greater, Instruction.RelationalOperationType.GreaterOrEquals); break; case Instruction.ConditionType.Random: relop = (Instruction.RelationalOperationType)Randomizer.OneFromMany(Instruction.RelationalOperationType.Smaller, Instruction.RelationalOperationType.SmallerOrEquals, Instruction.RelationalOperationType.Greater, Instruction.RelationalOperationType.GreaterOrEquals); break; default: throw new ObfuscatorException("Unrecognized condition type."); } } MakeInstruction.ConditionalJump(nop, var, right_value, relop, target); }
/// <summary> /// Function to make an actual fake instruction out of a Nop. /// </summary> /// <param name="ins">The nop we want to work on.</param> private static void _GenerateFakeInstruction(Instruction ins) { /* First we get a left value. */ Variable leftvalue = GetLeftValueForInstruction(ins); /* Then we check how many variables can we use as right value. */ List <Variable> rightvalues = GetRandomRightValues(ins, 2); /* We random generate a statement type which we may not use according to the available right values. */ Objects.Common.StatementType statementType = (Objects.Common.StatementType)Randomizer.OneFromManyWithProbability( new int[3] { 25, 15, 60 }, Objects.Common.StatementType.Copy, Objects.Common.StatementType.UnaryAssignment, Objects.Common.StatementType.FullAssignment); /* * The number of the available right values determines which kind of instructions * can we generate. * * - If we don't have any, then we must make a Copy with a constant. * * - If we have one, and it's the same as the left value, then we have to make * a Unary Assignment. * * - If we have one, but it's different from the left value, then we can make * a Copy (1), a Unary Assignment (2) and a Full Assignment with a constant (3). * * - If we have two, we can make all these and a Full Assignment with two * variables. * * Another important thing is that we cannot fill the variables with a value * without using themselves (like t = t + 1) while inside a loop. */ switch (rightvalues.Count) { case 0: /* If we have no available right values, and we are in a loop, then we can't do anything. */ if (DataAnalysis.isLoopBody[ins.parent]) { return; } /* We don't have any right values, so we have to copy a constant value. */ else { MakeInstruction.Copy(ins, leftvalue, null, Randomizer.SingleNumber(Common.GlobalMinValue, Common.GlobalMaxValue)); } break; case 1: /* We choose Full Assignment, or rightvalue is the same as leftvalue, or we are in a loop body. */ if (DataAnalysis.isLoopBody[ins.parent] || leftvalue.Equals(rightvalues[0]) || statementType == Objects.Common.StatementType.FullAssignment || (ins.DeadVariables.Keys.Contains(leftvalue) && ins.DeadVariables[leftvalue] == Variable.State.Filled)) { /* Here we random generate an operator. */ Instruction.ArithmeticOperationType op = (Instruction.ArithmeticOperationType)Randomizer.OneFromMany(Instruction.ArithmeticOperationType.Addition, Instruction.ArithmeticOperationType.Division, Instruction.ArithmeticOperationType.Multiplication, Instruction.ArithmeticOperationType.Subtraction); int num; if (op == Instruction.ArithmeticOperationType.Addition || op == Instruction.ArithmeticOperationType.Subtraction) { num = Randomizer.SingleNumber(Common.GlobalMinValue, Common.GlobalMaxValue); } else { /* * Here we generate an integer number which is the power of 2, and is * within the boundaries of GlobalMinNumber and GlobalMaxNumber. */ int min = Convert.ToInt32(Math.Ceiling(Math.Log(Common.GlobalMinValue, 2))); int max = Convert.ToInt32(Math.Floor(Math.Log(Common.GlobalMaxValue, 2))); int pow = Randomizer.SingleNumber(min, max); num = Convert.ToInt32(Math.Pow(2, pow)); } MakeInstruction.FullAssignment(ins, leftvalue, rightvalues.First(), null, num, op); } /* If we choose Unary Assignment. */ else if (statementType == Objects.Common.StatementType.UnaryAssignment) { MakeInstruction.UnaryAssignment(ins, leftvalue, rightvalues.First(), Instruction.UnaryOperationType.ArithmeticNegation); } /* If we choose Copy. */ else { MakeInstruction.Copy(ins, leftvalue, rightvalues.First(), null); } break; case 2: /* We make sure that the first right value isn't the same as the left value. */ if (leftvalue.Equals(rightvalues.First())) { Variable tmp = rightvalues[0]; rightvalues[0] = rightvalues[1]; rightvalues[1] = tmp; } /* * If we are in a loop body, then we can only make a full assignment like that: * t1 = t2 op t1 */ if (DataAnalysis.isLoopBody[ins.parent] || statementType == Objects.Common.StatementType.FullAssignment || (ins.DeadVariables.Keys.Contains(leftvalue) && ins.DeadVariables[leftvalue] == Variable.State.Filled)) { /* Here we random generate an operator: + or - */ /* TODO: (efficient) * and / */ Instruction.ArithmeticOperationType op = (Instruction.ArithmeticOperationType)Randomizer.OneFromMany(Instruction.ArithmeticOperationType.Addition, Instruction.ArithmeticOperationType.Subtraction); if (DataAnalysis.isLoopBody[ins.parent] || (ins.DeadVariables.Keys.Contains(leftvalue) && ins.DeadVariables[leftvalue] == Variable.State.Filled)) { MakeInstruction.FullAssignment(ins, leftvalue, rightvalues[0], leftvalue, null, op); } else { MakeInstruction.FullAssignment(ins, leftvalue, rightvalues[0], rightvalues[1], null, op); } } /* If we choose Copy. */ else if (statementType == Objects.Common.StatementType.Copy) { MakeInstruction.Copy(ins, leftvalue, rightvalues.First(), null); } /* If we choose Unary Assignment. */ else { MakeInstruction.UnaryAssignment(ins, leftvalue, rightvalues.First(), Instruction.UnaryOperationType.ArithmeticNegation); } break; } }
/// <summary> /// This function generates the BasicBlocks into the function, based on the condition list /// </summary> /// <param name="bb">The actual basicblock with the conditional jump at the end</param> /// <param name="truelane">The true successor</param> /// <param name="falselane">The false successor</param> /// <param name="condlist">The condition list</param> /// <returns>The list of the generated BasicBlocks</returns> private static void GenerateBlocks(BasicBlock bb, Variable var, BasicBlock truelane, BasicBlock falselane, List <Cond> condlist, int originalconstant, Instruction.RelationalOperationType originalrelop) { List <BasicBlock> bblist = new List <BasicBlock>(); foreach (Cond c in condlist) { bblist.Add(new BasicBlock(bb.parent)); bblist.Last().Instructions.Add(new Instruction(bblist.Last())); } bb.Instructions.Remove(bb.Instructions.Last()); bb.Instructions.Add(new Instruction(bb)); /// Replacing the first one, with the original bb.parent.BasicBlocks.Remove(bblist.First()); bblist.Remove(bblist.First()); bblist.Insert(0, bb); /// Creating the polyRequired list List <BasicBlock> truelist = new List <BasicBlock>(); truelist.Add(truelane); List <BasicBlock> falselist = new List <BasicBlock>(); falselist.Add(falselane); for (int i = 0; i < condlist.Count(); i++) { switch (condlist[i].JumpType) { case Cond.BlockJumpType.True: case Cond.BlockJumpType.Last: if (i != condlist.Count() - 1) { bblist[i].LinkToSuccessor(bblist[i + 1], true); } else { bblist[i].LinkToSuccessor(GeneratePolyReqJumpTarget(falselist), true); } MakeInstruction.ConditionalJump(bblist[i].Instructions.Last(), var, condlist[i].value, condlist[i].relop, GeneratePolyReqJumpTarget(truelist)); break; case Cond.BlockJumpType.False: if (i != condlist.Count() - 1) { bblist[i].LinkToSuccessor(bblist[i + 1], true); } else { bblist[i].LinkToSuccessor(GeneratePolyReqJumpTarget(falselist), true); } MakeInstruction.ConditionalJump(bblist[i].Instructions.Last(), var, condlist[i].value, condlist[i].relop, GeneratePolyReqJumpTarget(falselist)); break; case Cond.BlockJumpType.Ambigious: BasicBlock ambhelper = new BasicBlock(bb.parent); bblist[i].LinkToSuccessor(ambhelper, true); ambhelper.Instructions.Add(new Instruction(ambhelper)); if ((condlist[i].value + 1 == originalconstant || condlist[i].value - 1 == originalconstant) && originalrelop == Instruction.RelationalOperationType.NotEquals) { MakeInstruction.UnconditionalJump(ambhelper.Instructions.Last(), GeneratePolyReqJumpTarget(bblist.GetRange(i + 1, bblist.Count - (i + 1)))); MakeInstruction.ConditionalJump(bblist[i].Instructions.Last(), var, condlist[i].value, condlist[i].relop, truelist.First()); } else { if ((originalconstant > condlist[i].value && (condlist[i].relop == Instruction.RelationalOperationType.Greater || condlist[i].relop == Instruction.RelationalOperationType.GreaterOrEquals) && (originalrelop == Instruction.RelationalOperationType.Greater || originalrelop == Instruction.RelationalOperationType.GreaterOrEquals)) || (originalconstant < condlist[i].value && (condlist[i].relop == Instruction.RelationalOperationType.Smaller || condlist[i].relop == Instruction.RelationalOperationType.SmallerOrEquals) && (originalrelop == Instruction.RelationalOperationType.Smaller || originalrelop == Instruction.RelationalOperationType.SmallerOrEquals)) || (originalconstant < condlist[i].value && (originalrelop == Instruction.RelationalOperationType.Smaller || originalrelop == Instruction.RelationalOperationType.SmallerOrEquals) && (condlist[i].relop == Instruction.RelationalOperationType.NotEquals)) || (originalconstant > condlist[i].value && (originalrelop == Instruction.RelationalOperationType.Greater || originalrelop == Instruction.RelationalOperationType.GreaterOrEquals) && (condlist[i].relop == Instruction.RelationalOperationType.NotEquals))) { MakeInstruction.UnconditionalJump(ambhelper.Instructions.Last(), GeneratePolyReqJumpTarget(falselist)); } else { MakeInstruction.UnconditionalJump(ambhelper.Instructions.Last(), GeneratePolyReqJumpTarget(truelist)); } MakeInstruction.ConditionalJump(bblist[i].Instructions.Last(), var, condlist[i].value, condlist[i].relop, bblist[i + 1]); } break; default: break; } } /// Checking if there is a jump to the original targets, and if there is not, we can delete that /// BasicBlock, there must be a polyRequired clone of that. if (falselane.getPredecessors.Count() == 0) { foreach (BasicBlock succ in falselane.getSuccessors) { succ.getPredecessors.Remove(falselane); } falselane.parent.BasicBlocks.Remove(falselane); } if (truelane.getPredecessors.Count() == 0) { foreach (BasicBlock succ in truelane.getSuccessors) { succ.getPredecessors.Remove(truelane); } truelane.parent.BasicBlocks.Remove(truelane); } }
/// <summary> /// Expands the fake route into the CFG and creates the conditional jumps for both Loop and Fake code /// </summary> /// <param name="fake1">The first fake basic block to be used in the expansion</param> /// <param name="mainLaneBB">The basic block we should go in case of no-loop</param> /// <param name="atFakeCodeGeneration">Wheter we are or not at the fake code generation phase</param> public static void ExpandFakeRoute(BasicBlock fake1, BasicBlock originalSuccessor, bool atFakeJumpGeneration) { //Creating fake2 to hold the next Loop condition BasicBlock fake2 = new BasicBlock(fake1.parent); fake2.Meshable = false; if (fake2.parent.containsDivisionModulo == false || originalSuccessor.Instructions.FindAll(x => x.TACtext.Contains("return")).Count > 0) { fake2.Involve = BasicBlock.InvolveInFakeCodeGeneration.Both; } fake2.inFakeLane = true; //Creating fake3 to hold the extra fake code in case of No-Loop BasicBlock fake3 = new BasicBlock(fake1.parent); if (fake3.parent.containsDivisionModulo == false || originalSuccessor.Instructions.FindAll(x => x.TACtext.Contains("return")).Count > 0) { fake3.Involve = BasicBlock.InvolveInFakeCodeGeneration.Both; } fake3.inFakeLane = true; //Creating the fake3 unconditional jump back to the Main Lane MakeInstruction.UnconditionalJump(fake3.Instructions.Last(), originalSuccessor); //Linking fake3 to fake2 fake2.LinkToSuccessor(fake3); //Creating fake4 to hold the extra fake code in case of No-Loop BasicBlock fake4 = new BasicBlock(fake1.parent); if (fake4.parent.containsDivisionModulo == false || originalSuccessor.Instructions.FindAll(x => x.TACtext.Contains("return")).Count > 0) { fake4.Involve = BasicBlock.InvolveInFakeCodeGeneration.Both; } fake4.inFakeLane = true; //Creating the fake4 unconditional jump back to the Main Lane MakeInstruction.UnconditionalJump(fake4.Instructions.Last(), originalSuccessor); //Linking fake4 to fake1 fake1.LinkToSuccessor(fake4); //Fetching the Conditional Jump (AlwaysFalse) created in the previous basic block Instruction originalInstruction = fake1.getPredecessors.First().Instructions.Last(); //Defining the relational operator for the fake1 conditional jump Instruction.RelationalOperationType relationalOperationEF1 = (Instruction.RelationalOperationType) Randomizer.OneFromMany(Instruction.RelationalOperationType.Smaller, Instruction.RelationalOperationType.SmallerOrEquals, Instruction.RelationalOperationType.Greater, Instruction.RelationalOperationType.GreaterOrEquals); //Defining the constant for the fake1 conditional jump int rightValueEF1 = 0; if (originalInstruction.GetConstFromCondition() >= originalInstruction.GetVarFromCondition().fixedMax.Value) { //If the original instruction's contant is diferent from the global max minus the max loop range, we should try //to get a value different from the original instruction's constant in order to have a more belieavable code do { rightValueEF1 = Randomizer.SingleNumber((int)originalInstruction.GetConstFromCondition(), Common.GlobalMaxValue - Common.LoopConditionalJumpMaxRange); } while (rightValueEF1 == (int)originalInstruction.GetConstFromCondition() && (int)originalInstruction.GetConstFromCondition() != Common.GlobalMaxValue - Common.LoopConditionalJumpMaxRange); } else { //If the original instruction's contant is diferent from the global min plus the max loop range, we should try //to get a value different from the original instruction's constant in order to have a more belieavable code do { rightValueEF1 = Randomizer.SingleNumber(Common.GlobalMinValue + Common.LoopConditionalJumpMaxRange, (int)originalInstruction.GetConstFromCondition()); } while (rightValueEF1 == (int)originalInstruction.GetConstFromCondition() && (int)originalInstruction.GetConstFromCondition() != Common.GlobalMinValue + Common.LoopConditionalJumpMaxRange); } //Creating the fake1 conditional jump Variable var = originalInstruction.GetVarFromCondition(); MakeInstruction.ConditionalJump(fake1.Instructions.Last(), var, rightValueEF1, relationalOperationEF1, fake2); //Defining the range for the fake2 conditional jump constant int range = Randomizer.SingleNumber(0, Common.LoopConditionalJumpMaxRange); //Defining relational operation for the extraFake2 conditional jump based on the extraFake1 condtional jump relational operation and the range Instruction.RelationalOperationType relationalOperationEF2 = Instruction.RelationalOperationType.Equals; switch (relationalOperationEF1) { case Instruction.RelationalOperationType.Smaller: case Instruction.RelationalOperationType.SmallerOrEquals: if (range <= 1) { relationalOperationEF2 = Instruction.RelationalOperationType.Equals; } else if (range == 2) { relationalOperationEF2 = (Instruction.RelationalOperationType) Randomizer.OneFromMany(Instruction.RelationalOperationType.GreaterOrEquals, Instruction.RelationalOperationType.Equals); } else { relationalOperationEF2 = (Instruction.RelationalOperationType) Randomizer.OneFromMany(Instruction.RelationalOperationType.Greater, Instruction.RelationalOperationType.GreaterOrEquals, Instruction.RelationalOperationType.Equals); } break; case Instruction.RelationalOperationType.Greater: case Instruction.RelationalOperationType.GreaterOrEquals: if (range <= 1) { relationalOperationEF2 = Instruction.RelationalOperationType.Equals; } else if (range == 2) { relationalOperationEF2 = (Instruction.RelationalOperationType) Randomizer.OneFromMany(Instruction.RelationalOperationType.SmallerOrEquals, Instruction.RelationalOperationType.Equals); } else { relationalOperationEF2 = (Instruction.RelationalOperationType) Randomizer.OneFromMany(Instruction.RelationalOperationType.Smaller, Instruction.RelationalOperationType.SmallerOrEquals, Instruction.RelationalOperationType.Equals); } break; } //Defining the constant for the fake2 conditional jump int rightValueEF2 = 0; if (rightValueEF1 == Common.GlobalMinValue || rightValueEF1 == Common.GlobalMaxValue) { rightValueEF2 = rightValueEF1; } else { switch (relationalOperationEF2) { case Instruction.RelationalOperationType.Smaller: case Instruction.RelationalOperationType.SmallerOrEquals: if (rightValueEF1 + range > Common.GlobalMaxValue) { rightValueEF2 = Randomizer.SingleNumber(rightValueEF1, Common.GlobalMaxValue); } else if (rightValueEF1 + range > (int)originalInstruction.GetConstFromCondition() && (originalInstruction.GetRelopFromCondition() == Instruction.RelationalOperationType.Smaller || originalInstruction.GetRelopFromCondition() == Instruction.RelationalOperationType.SmallerOrEquals)) { rightValueEF2 = Randomizer.SingleNumber(rightValueEF1, (int)originalInstruction.GetConstFromCondition()); } else { rightValueEF2 = Randomizer.SingleNumber(rightValueEF1, rightValueEF1 + range); } break; case Instruction.RelationalOperationType.Greater: case Instruction.RelationalOperationType.GreaterOrEquals: if (rightValueEF1 - range < Common.GlobalMinValue) { rightValueEF2 = Randomizer.SingleNumber(Common.GlobalMinValue, rightValueEF1); } else if (rightValueEF1 - range < (int)originalInstruction.GetConstFromCondition() && (originalInstruction.GetRelopFromCondition() == Instruction.RelationalOperationType.Greater || originalInstruction.GetRelopFromCondition() == Instruction.RelationalOperationType.GreaterOrEquals)) { rightValueEF2 = Randomizer.SingleNumber((int)originalInstruction.GetConstFromCondition(), rightValueEF1); } else { rightValueEF2 = Randomizer.SingleNumber(rightValueEF1 - range, rightValueEF1); } break; case Instruction.RelationalOperationType.Equals: { switch (relationalOperationEF1) { case Instruction.RelationalOperationType.Smaller: case Instruction.RelationalOperationType.SmallerOrEquals: if (rightValueEF1 - range < Common.GlobalMinValue) { rightValueEF2 = Randomizer.SingleNumber(Common.GlobalMinValue, rightValueEF1); } else if (rightValueEF1 - range < (int)originalInstruction.GetConstFromCondition() && (originalInstruction.GetRelopFromCondition() == Instruction.RelationalOperationType.Greater || originalInstruction.GetRelopFromCondition() == Instruction.RelationalOperationType.GreaterOrEquals)) { rightValueEF2 = Randomizer.SingleNumber((int)originalInstruction.GetConstFromCondition(), rightValueEF1); } else { rightValueEF2 = Randomizer.SingleNumber(rightValueEF1 - range, rightValueEF1); } break; case Instruction.RelationalOperationType.Greater: case Instruction.RelationalOperationType.GreaterOrEquals: if (rightValueEF1 + range > Common.GlobalMaxValue) { rightValueEF2 = Randomizer.SingleNumber(rightValueEF1, Common.GlobalMaxValue); } else if (rightValueEF1 + range > (int)originalInstruction.GetConstFromCondition() && (originalInstruction.GetRelopFromCondition() == Instruction.RelationalOperationType.Smaller || originalInstruction.GetRelopFromCondition() == Instruction.RelationalOperationType.SmallerOrEquals)) { rightValueEF2 = Randomizer.SingleNumber(rightValueEF1, (int)originalInstruction.GetConstFromCondition()); } else { rightValueEF2 = Randomizer.SingleNumber(rightValueEF1, rightValueEF1 + range); } break; } break; } } } //Selecting the target for fake2 in order to create a loop List <BasicBlock> reacheableBasicBlocks = DataAnalysis.GetReachableBasicBlocks(fake2, Common.Direction.Up); //In case we are at fake jump generation, we should try to choose reachable basic blocks in a loop body //in order to make the CFG irreducible if (atFakeJumpGeneration) { List <BasicBlock> loopReachableBasicBlocks = reacheableBasicBlocks.FindAll(x => DataAnalysis.isLoopBody.Keys.Contains(x) && DataAnalysis.isLoopBody[x] == true); //If we have reachable basic blocks in a loop body, we can use them if (loopReachableBasicBlocks.Count > 0) { int i = Randomizer.SingleNumber(0, 100); if (!fake2.parent.irreducibleCFG || i <= Common.JumpLoopBodyProbability) { reacheableBasicBlocks = loopReachableBasicBlocks; fake2.parent.irreducibleCFG = true; } } } //Check whether the amount of reachable basic blocks we have is greater than MaxJumpForLoop. //This parameter is used to control the chance of problems ("nops" left in the end) during //fake instructions generation. if (reacheableBasicBlocks.Count > Common.MaxJumpBackForLoop) { reacheableBasicBlocks.RemoveRange(Common.MaxJumpBackForLoop, reacheableBasicBlocks.Count - Common.MaxJumpBackForLoop); } //Defining the target basic block for the conditional jump BasicBlock loopTarget = (BasicBlock)Randomizer.OneFromMany(reacheableBasicBlocks.ToArray()); //Creating the fake2 conditional jump to the loop target MakeInstruction.ConditionalJump(fake2.Instructions.Last(), var, rightValueEF2, relationalOperationEF2, loopTarget); }