Exemplo n.º 1
0
        /// <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);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Makes FullAssignment instruction type from NoOperation
        /// </summary>
        /// <param name="left_value">Left value (variable only)</param>
        /// <param name="right_value1">Right value before operator</param>
        /// <param name="right_value2">Right value after operator (for variable), null for number</param>
        /// <param name="right_value_int">Right value after operator (for number), null for variable</param>
        /// <param name="operation">Desired arithmetic operation</param>
        public static void FullAssignment(Instruction ins, Variable left_value, Variable right_value1, Variable right_value2, int?right_value_int, Instruction.ArithmeticOperationType operation)
        {
            if (ins.statementType != Objects.Common.StatementType.NoOperation)
            {
                throw new ObfuscatorException("Only NoOperation instruction can be modified to other type!");
            }

            if (right_value2 == null && right_value_int == null)
            {
                throw new ObfuscatorException("Wrong parameter passing: one of the second right value and the constant must be null.");
            }
            if (right_value2 != null && right_value_int != null)
            {
                throw new ObfuscatorException("Wrong parameter passing: both second right value and constant is null.");
            }
            if (left_value == null)
            {
                throw new ObfuscatorException("Wrong parameter passing: left value missing.");
            }
            if (right_value1 == null)
            {
                throw new ObfuscatorException("Wrong parameter passing: first right value missing.");
            }

            string left1  = left_value.name;
            string right1 = right_value1.name;
            string right2 = right_value_int == null ? right_value2.name : right_value_int.ToString();
            string op;

            switch (operation)
            {
            case Instruction.ArithmeticOperationType.Addition:
                op = "+";
                break;

            case Instruction.ArithmeticOperationType.Subtraction:
                op = "-";
                break;

            case Instruction.ArithmeticOperationType.Multiplication:
                op = "*";
                break;

            case Instruction.ArithmeticOperationType.Division:
                op = @"/";
                break;

            default:
                throw new ObfuscatorException("Unsupported arithmetic operation type.");
            }
            ins.RefVariables.Clear();
            ins.RefVariables.Add(left_value);
            ins.RefVariables.Add(right_value1);
            if (right_value_int == null)
            {
                ins.RefVariables.Add(right_value2);
            }
            ins.statementType = Objects.Common.StatementType.FullAssignment;
            ins.TACtext       = string.Join(" ", left1, ":=", right1, op, right2);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Parses a full assignment instruction
        /// </summary>
        /// <param name="inst">Instruction to be parsed</param>
        /// <param name="left_value">Left value of the assignment (variable only)</param>
        /// <param name="right_value1">Right value before arithmetic operator</param>
        /// <param name="right_value2">Right value after arithmetic operator (for variable), null for number</param>
        /// <param name="right_value_int">Right value after arithmetic operator (for number), null for variable</param>
        /// <param name="operation">Arithmetic operator</param>
        public static void FullAssignment(Instruction inst, out Variable left_value, out Variable right_value1, out Variable right_value2, out int?right_value_int, out Instruction.ArithmeticOperationType operation)
        {
            Validate(inst, Objects.Common.StatementType.FullAssignment);
            System.Collections.Specialized.StringCollection refvarIDs = new System.Collections.Specialized.StringCollection();
            Match matchResult = Regex.Match(inst.TACtext, "ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}", RegexOptions.None);

            while (matchResult.Success)
            {
                refvarIDs.Add(matchResult.Value);
                matchResult = matchResult.NextMatch();
            }

            left_value   = inst.RefVariables.Find(x => x.ID == refvarIDs[0]);
            right_value1 = inst.RefVariables.Find(x => x.ID == refvarIDs[1]);
            if (refvarIDs.Count == 3)
            {
                right_value2    = inst.RefVariables.Find(x => x.ID == refvarIDs[2]);
                right_value_int = null;
            }
            else
            {
                right_value_int = Convert.ToInt32(inst.TACtext.Split(' ')[4]);
                right_value2    = null;
            }
            switch (inst.TACtext.Split(' ')[3])
            {
            case "+":
                operation = Instruction.ArithmeticOperationType.Addition;
                break;

            case "-":
                operation = Instruction.ArithmeticOperationType.Subtraction;
                break;

            case "*":
                operation = Instruction.ArithmeticOperationType.Multiplication;
                break;

            case @"/":
                operation = Instruction.ArithmeticOperationType.Division;
                break;

            case "%":
                operation = Instruction.ArithmeticOperationType.Modulo;
                break;

            default:
                throw new ParserException("Cannot parse arithmetic operation type.");
            }
        }
Exemplo n.º 4
0
        /// <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;
            }
        }