Example #1
0
 /// <summary>
 /// Checking for collisions of FILLED vs. NOT_INITIALIZED and residual NOPs
 /// </summary>
 /// <param name="routine">A routine to be checked</param>
 public static void CheckForProblems(Routine routine)
 {
     foreach (Function func in routine.Functions)
     {
         /* Now we check for forbidden state collisions at every basic blocks' beginning. */
         foreach (BasicBlock bb in func.BasicBlocks)
         {
             if (DataAnalysis.ForbiddenStateCollision(bb.Instructions.First()))
             {
                 throw new ObfuscatorException("Forbidden state collision: FILLED meets NOT_INITIALIZED.");
             }
         }
         //Checking whether we have "nops" left
         if (GetAllNops(func).Count > 0)
         {
             throw new ObfuscatorException("Lack of available dead variables.");
         }
     }
 }
Example #2
0
        private static void Obfuscation(Routine routine)
        {
            Logging.WriteComplexityMetrics(routine, "Original");

            //Checking whether the functions have either "division" or "modulo" operations
            //If they do, fake instructions with original variables should be inserted only before the return
            //to avoid problems with the these operations
            foreach (Function func in routine.Functions)
            {
                func.CheckDivisionModulo();
            }

            //Creating fake input parameters in all functions
            FakeParameters.CreateFakeParameters(routine);

            //Checking for Multiple Obfuscation
            for (int i = 0; i < Convert.ToInt32(ConfigurationManager.AppSettings["MultipleRuns"]); i++)
            {
                //Creating fake variables
                foreach (Function func in routine.Functions)
                {
                    for (int j = 0; j < (Common.PercentageFakeVars * func.LocalVariables.FindAll(x => !x.fake).Count) / 100; j++)
                    {
                        func.LocalVariables.Add(new Variable(Variable.Kind.Local, Variable.Purpose.Fake, Objects.Common.MemoryRegionSize.Integer));
                    }
                }

                if (ConfigurationManager.AppSettings["ConstCoverAlgInMultipleRuns"].Split('-')[i].Equals("1"))
                {
                    Console.Write("Step 1: Constants coverage");
                    ConstCoverage.CoverConstants(routine);
                    routine.Validate();
                    PrintSuccess();
                    Logging.WriteReadableTAC(routine, "CONST");
                    Logging.DrawCFG(routine, "CONST");
                }

                if (ConfigurationManager.AppSettings["UncMeshingAlgInMultipleRuns"].Split('-')[i].Equals("1"))
                {
                    Console.Write("Step 2: Meshing unconditional jumps");
                    Meshing.MeshUnconditionals(routine);
                    routine.Validate();
                    PrintSuccess();
                    Logging.WriteReadableTAC(routine, "MeshingUNC");
                    Logging.DrawCFG(routine, "MeshingUNC");
                }

                if (ConfigurationManager.AppSettings["CondMeshingAlgInMultipleRuns"].Split('-')[i].Equals("1"))
                {
                    Console.Write("Step 3: Meshing conditional jumps");
                    Meshing.MeshConditionals(routine);
                    routine.Validate();
                    PrintSuccess();
                    Logging.WriteReadableTAC(routine, "MeshingCOND");
                    Logging.DrawCFG(routine, "MeshingCOND");
                }

                Console.Write("Step 4: Generation of fake NOP instructions");
                foreach (Function func in routine.Functions)
                {
                    FakeCode.GenerateNoOperations(func);
                }
                routine.Validate();
                PrintSuccess();
                Logging.WriteRoutine(routine, "NoOpersGeneration");
                Logging.WriteReadableTAC(routine, "FakeNOPs");

                Console.Write("Step 5: Partial data analysis");
                DataAnalysis.GatherBasicBlockInfo(routine);
                PrintSuccess();

                if (ConfigurationManager.AppSettings["FakeJumpsAlgInMultipleRuns"].Split('-')[i].Equals("1"))
                {
                    Console.Write("Step 6: Generation of fake conditional jumps from NOPs");
                    foreach (Function func in routine.Functions)
                    {
                        FakeCode.GenerateConditionalJumps(func);
                    }
                    Logging.WriteRoutine(routine, "CondJumps");
                    foreach (Function func in routine.Functions)
                    {
                        FakeCode.GenerateNoOperations(func);
                    }
                    routine.Validate();
                    PrintSuccess();
                }

                Console.Write("Step 7: Complete data analysis");
                foreach (Function func in routine.Functions)
                {
                    DataAnalysis.DeadVarsAlgortihm(func);
                }
                DataAnalysis.GatherBasicBlockInfo(routine);
                PrintSuccess();


                Console.Write("Step 8: Generation of fake instructions from NOPs");
                foreach (Function func in routine.Functions)
                {
                    FakeCode.GenerateFakeInstructions(func);
                }
                Logging.WriteRoutine(routine, "FakeIns");
                Logging.DrawCFG(routine, "CondJumps");
                Logging.WriteComplexityMetrics(routine, "Final");
                FakeCode.CheckForProblems(routine);
                routine.Validate();
                PrintSuccess();

                Logging.WriteReadableTAC(routine, "FakeInstrFromNOPs");
            }
        }
Example #3
0
        /*
         * This function is called when we encounter a change in a dead variable's state.
         * So we want to push this change through all the instructions, and deal with
         * this variable only.
         *
         * However we can't just overwrite the statement without any check...
         */
        private static void RefreshNext(Instruction ins, Variable var, Variable.State state)
        {
            /*
             * If this instruction uses this variable as well, or this instruction
             * uses a pointer that points to this variable then its state must not
             * be changed, because it's perfect as it is right now.
             */
            if (ins.RefVariables.Contains(var))
            {
                /* This instruction uses this variable. */
                return;
            }

            /*
             * We have to do anything only if the variable is in this instruction is
             * dead, and it's state differs from the new state.
             */
            if (ins.DeadVariables.ContainsKey(var) &&   // This variable is dead.
                ins.DeadVariables[var] != state)        // The state differs.
            {
                foreach (Variable v in ins.RefVariables)
                {
                    if (ins.DeadPointers.ContainsKey(v) && ins.DeadPointers[v].PointsTo.Equals(var))
                    {
                        /* The instruction uses a pointer that points to this variable. */
                        return;
                    }
                }

                /*
                 * Now we are at the point, that maybe we have to change the state.
                 * Although it's not sure, because if the instruction has more than one predecessors,
                 * then the actual state might not change anything.
                 * For example: NOT_INITIALIZED meets FREE, or FREE meets FILLED.
                 *
                 * NOTE: we don't know right now what to do if NOT_INIT meets FILLED...
                 */
                state = DataAnalysis.CheckPrecedingStates(ins, var, state);

                ins.DeadVariables[var] = state;
                foreach (Instruction inst in ins.GetFollowingInstructions())
                {
                    RefreshNext(inst, var, state);
                }
            }

            /*
             * Another case for doing something when we pass a dead pointer with changed state.
             * In this case we do not have to look for variables pointing to that one.
             *
             * WARNING FOR FUTURE: (1)
             */
            if (ins.DeadPointers.ContainsKey(var) &&        // This is a dead pointer.
                ins.DeadPointers[var].State != state)       // The states differ.
            {
                /* Just like in the previous case, we have to check all the preceding states for collisions. */
                state = DataAnalysis.CheckPrecedingStates(ins, var, state);

                ins.DeadPointers[var].State = state;
                foreach (Instruction inst in ins.GetFollowingInstructions())
                {
                    RefreshNext(inst, var, state);
                }
            }
        }
Example #4
0
        /// <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);
        }