Exemple #1
0
 public static int Evaluate(Expression exp, int var)
 {
     if (exp is ConstantExpression)
     {
         ConstantExpression tExp = exp as ConstantExpression;
         return (int)(exp as ConstantExpression).Value;
     }
     else if (exp is VariableExpression)
     {
         return var;
     }
     else if (exp is AddExpression)
     {
         AddExpression nExp = (AddExpression)exp;
         return Evaluate(nExp.OperandA, var) + Evaluate(nExp.OperandB, var);
     }
     else if (exp is SubExpression)
     {
         SubExpression nExp = (SubExpression)exp;
         return Evaluate(nExp.OperandA, var) - Evaluate(nExp.OperandB, var);
     }
     else if (exp is MulExpression)
     {
         MulExpression nExp = (MulExpression)exp;
         return Evaluate(nExp.OperandA, var) * Evaluate(nExp.OperandB, var);
     }
     else if (exp is DivExpression)
     {
         DivExpression nExp = (DivExpression)exp;
         return Evaluate(nExp.OperandA, var) / Evaluate(nExp.OperandB, var);
     }
     else if (exp is NegExpression)
     {
         NegExpression nExp = (NegExpression)exp;
         return -Evaluate(nExp.Value, var);
     }
     else if (exp is InvExpression)
     {
         InvExpression nExp = (InvExpression)exp;
         return ~Evaluate(nExp.Value, var);
     }
     else if (exp is XorExpression)
     {
         XorExpression nExp = (XorExpression)exp;
         return Evaluate(nExp.OperandA, var) ^ Evaluate(nExp.OperandB, var);
     }
     throw new NotSupportedException();
 }
Exemple #2
0
 public static Expression InverseExpression(Expression exp)
 {
     Expression ret = new VariableExpression();
     Expression s = exp;
     do
     {
         ret = s.GenerateInverse(ret);
         foreach (var i in s.Children)
             if (i.HasVariable)
             {
                 s = i;
                 break;
             }
     }
     while (!(s is VariableExpression));
     return ret;
 }
Exemple #3
0
 internal Expression Generate(Expression parent, int level, Random rand)
 {
     Expression ret = null;
     if (level == 0)
     {
         if (!g)
         {
             ret = new VariableExpression();
             g = true;
         }
         else
         {
             ret = new ConstantExpression();
             ret.Generate(this, level, rand);
         }
     }
     else
     {
         ret = (Expression)Activator.CreateInstance(ExpressionTypes[rand.Next(0, ExpressionTypes.Length)]);
         ret.Generate(this, level - 1, rand);
     }
     ret.Parent = parent;
     return ret;
 }
Exemple #4
0
 public abstract Expression GenerateInverse(Expression arg);
Exemple #5
0
        private static byte[] Encrypt(byte[] bytes, Expression exp)
        {
            MemoryStream ret = new MemoryStream();
            using (BinaryWriter wtr = new BinaryWriter(ret))
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    int en = (int)ExpressionEvaluator.Evaluate(exp, bytes[i]);
                    Write7BitEncodedInt(wtr, en);
                }
            }

            return ret.ToArray();
        }
Exemple #6
0
 public abstract void VisitPreOrder(Expression exp);
Exemple #7
0
        private static string Decrypt(byte[] bytes, int len, Expression exp)
        {
            byte[] ret = new byte[(len + 7) & ~7];

            using (BinaryReader rdr = new BinaryReader(new MemoryStream(bytes)))
            {
                for (int i = 0; i < ret.Length; i++)
                {
                    int r = Read7BitEncodedInt(rdr);
                    ret[i] = (byte)LongExpressionEvaluator.Evaluate(exp, r);
                }
            }

            return Encoding.Unicode.GetString(ret, 0, len);
        }
Exemple #8
0
        private static byte[] Encrypt(string str, Expression exp, out int len)
        {
            byte[] bs = Encoding.Unicode.GetBytes(str);
            byte[] tmp = new byte[(bs.Length + 7) & ~7];
            Buffer.BlockCopy(bs, 0, tmp, 0, bs.Length);
            len = bs.Length;

            MemoryStream ret = new MemoryStream();
            using (BinaryWriter wtr = new BinaryWriter(ret))
            {
                for (int i = 0; i < tmp.Length; i++)
                {
                    int en = (int)LongExpressionEvaluator.Evaluate(exp, tmp[i]);
                    Write7BitEncodedInt(wtr, en);
                }
            }

            return ret.ToArray();
        }
        public override void Process(ConfusionParameter parameter)
        {
            method = parameter.Target as MethodDefinition;
            if (!method.HasBody || method.Body.Instructions.Count == 0) return;

            level = 5;
            if (Array.IndexOf(parameter.Parameters.AllKeys, "level") != -1)
            {
                if (!int.TryParse(parameter.Parameters["level"], out level) && (level <= 0 || level > 10))
                {
                    Log("Invalid level, 5 will be used.");
                    level = 5;
                }
            }

            genJunk = false;
            if (method.Module.Architecture != TargetArchitecture.I386)
                genJunk = false;
            else if (Array.IndexOf(parameter.Parameters.AllKeys, "genjunk") != -1)
            {
                if (!bool.TryParse(parameter.Parameters["genjunk"], out genJunk))
                {
                    Log("Invalid junk code parameter, junk code would not be generated.");
                    genJunk = false;
                }
            }

            fakeBranch = false;
            if (Array.IndexOf(parameter.Parameters.AllKeys, "fakebranch") != -1)
            {
                if (!bool.TryParse(parameter.Parameters["fakebranch"], out fakeBranch))
                {
                    Log("Invalid fake branch parameter, fake branch would not be generated.");
                    fakeBranch = false;
                }
            }

            MethodBody body = method.Body;
            body.SimplifyMacros();
            body.ComputeHeader();
            body.MaxStackSize += 0x10;

            PropagateSeqPoints(body);

            VariableDefinition stateVar = new VariableDefinition(method.Module.TypeSystem.Int32);
            body.Variables.Add(stateVar);
            body.InitLocals = true;

            //Compute stacks
            var stacks = GetStacks(body);

            Dictionary<Instruction, Instruction> ReplTbl = new Dictionary<Instruction, Instruction>();
            List<Scope> scopes = new List<Scope>();
            foreach (var scope in ScopeDetector.DetectScopes(body))
            {
                scopes.Add(scope);

                //Split statements when stack = empty
                //First statement maybe have non-empty stack because of handlers/filter
                List<Statement> sts = new List<Statement>();
                foreach (var i in SplitStatements(body, scope.Instructions, stacks))
                    sts.Add(new Statement()
                    {
                        Instructions = i,
                        Type = StatementType.Normal,
                        Key = 0,
                        BeginStack = stacks[i[0].Index]
                    });

                //Constructor fix
                if (body.Method.IsConstructor && body.Method.HasThis)
                {
                    Statement init = new Statement();
                    init.Type = StatementType.Normal;
                    List<Instruction> z = new List<Instruction>();
                    while (sts.Count != 0)
                    {
                        z.AddRange(sts[0].Instructions);
                        Instruction lastInst = sts[0].Instructions[sts[0].Instructions.Length - 1];
                        sts.RemoveAt(0);
                        if (lastInst.OpCode == OpCodes.Call &&
                            (lastInst.Operand as MethodReference).Name == ".ctor")
                            break;
                    }
                    init.Instructions = z.ToArray();
                    sts.Insert(0, init);
                }

                if (sts.Count == 1 || sts.All(st => st.BeginStack != 0)) continue;

                //Merge statements for level
                for (int i = 0; i < sts.Count - 1; i++)
                {
                    if (Random.Next(1, 10) > level || sts[i + 1].BeginStack != 0)
                    {
                        Statement newSt = new Statement();
                        newSt.Type = sts[i + 1].Type;
                        newSt.BeginStack = sts[i].BeginStack;
                        newSt.Instructions = new Instruction[sts[i].Instructions.Length + sts[i + 1].Instructions.Length];
                        Array.Copy(sts[i].Instructions, 0, newSt.Instructions, 0, sts[i].Instructions.Length);
                        Array.Copy(sts[i + 1].Instructions, 0, newSt.Instructions, sts[i].Instructions.Length, sts[i + 1].Instructions.Length);
                        sts[i] = newSt;
                        sts.RemoveAt(i + 1);
                        i--;
                    }
                }

                //Detect branches
                int k = 0;
                foreach (var st in sts)
                {
                    Instruction last = st.Instructions[st.Instructions.Length - 1];
                    if (last.Operand is Instruction &&
                        sts.Exists(_ => _.Instructions[0] == last.Operand))
                        st.Type = StatementType.Branch;
                    st.Key = k; k++;
                }

                //Shuffle the statements
                List<Instruction> insts = new List<Instruction>();
                for (int i = 1; i < sts.Count; i++)
                {
                    int j = Random.Next(1, sts.Count);
                    var tmp = sts[j];
                    sts[j] = sts[i];
                    sts[i] = tmp;
                }
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < sts.Count; i++)
                {
                    if (i != 0) sb.Append(", ");
                    sb.Append(sts[i].Key);
                }
                Database.AddEntry("CtrlFlow", method.FullName, sb);

                Instruction[] stHdrs = new Instruction[sts.Count];
                k = 0;
                for (int i = 0; i < sts.Count; i++)
                {
                    sts[i].Key = k;
                    if (sts[i].BeginStack == 0)
                        k++;

                    if (sts[i].Instructions.Length > 0)
                        stHdrs[i] = sts[i].Instructions[0];
                }
                Func<object, Statement> resolveHdr = inst =>
                {
                    int _ = Array.IndexOf(stHdrs, inst as Instruction);
                    return _ == -1 ? null : sts[_];
                };

                exp = generator.Generate(level);
                invExp = ExpressionInverser.InverseExpression(exp);
                Instruction[] ldloc = new Instruction[] { Instruction.Create(OpCodes.Ldloc, stateVar) };// new CecilVisitor(invExp, new Instruction[] { Instruction.Create(OpCodes.Ldloc, stateVar) }).GetInstructions();
                Instruction begin = ldloc[0];
                Instruction swit = Instruction.Create(OpCodes.Switch, Empty<Instruction>.Array);
                Instruction end = Instruction.Create(OpCodes.Nop);
                List<Instruction> targets = new List<Instruction>();
                Statement beginSt = resolveHdr(scope.Instructions[0]);

                //Convert branches -> switch
                bool firstSt = true;
                foreach (var st in sts)
                {
                    List<Instruction> stInsts = new List<Instruction>(st.Instructions);
                    Instruction last = st.Instructions[st.Instructions.Length - 1];
                    if (st.Type == StatementType.Branch)
                    {
                        if (last.OpCode.Code == Code.Br)  //uncond
                        {
                            int index = stInsts.Count - 1;
                            stInsts.RemoveAt(index);
                            Statement targetSt = resolveHdr(last.Operand);
                            Statement fallSt;
                            if (fakeBranch && (fallSt = resolveHdr(last.Next)) != null)
                            {
                                ReplTbl[last] = GenFakeBranch(st, targetSt, fallSt, stInsts, stateVar, begin);
                            }
                            else
                            {
                                ReplTbl[last] = EncryptNum(st.Key, stateVar, targetSt.Key, stInsts);
                                stInsts.Add(Instruction.Create(OpCodes.Br, begin));
                                stInsts.AddRange(GetJunk(stateVar));
                            }
                            stInsts[index].SequencePoint = last.SequencePoint;
                        }
                        else if (last.OpCode.Code != Code.Leave)  //cond
                        {
                            int index = stInsts.Count - 1;
                            stInsts.RemoveAt(index);
                            Statement targetSt = resolveHdr(last.Operand);
                            Statement fallSt = resolveHdr(last.Next);

                            if (fallSt == null) //fall into exception block
                            {
                                ReplTbl[last] = EncryptNum(st.Key, stateVar, targetSt.Key, stInsts);
                                stInsts.Add(Instruction.Create(last.OpCode, begin));
                                stInsts.Add(Instruction.Create(OpCodes.Br, last.Next));
                                stInsts.AddRange(GetJunk(stateVar));
                            }
                            else
                            {
                                ReplTbl[last] = EncryptNum(st.Key, stateVar, targetSt.Key, stInsts);
                                stInsts.Add(Instruction.Create(last.OpCode, begin));
                                EncryptNum(st.Key, stateVar, fallSt.Key, stInsts);
                                stInsts.Add(Instruction.Create(OpCodes.Br, begin));
                                stInsts.AddRange(GetJunk(stateVar));
                            }
                            stInsts[index].SequencePoint = last.SequencePoint;
                        }
                    }
                    else
                    {
                        Statement fallSt = resolveHdr(last.Next);
                        if (fallSt != null)
                        {
                            if (fakeBranch)
                            {
                                Statement fakeSt = sts[Random.Next(0, sts.Count)];
                                GenFakeBranch(st, fallSt, fakeSt, stInsts, stateVar, begin);
                            }
                            else
                            {
                                EncryptNum(st.Key, stateVar, fallSt.Key, stInsts);
                                stInsts.Add(Instruction.Create(OpCodes.Br, begin));
                                stInsts.AddRange(GetJunk(stateVar));
                            }
                        }
                        else
                            stInsts.Add(Instruction.Create(OpCodes.Br, end));
                    }
                    if (!firstSt)
                    {
                        targets.Add(stInsts[0]);
                        insts.AddRange(stInsts.ToArray());
                    }
                    else
                    {
                        insts.AddRange(stInsts.ToArray());
                        insts.AddRange(ldloc);
                        insts.Add(swit);
                        if (st.BeginStack == 0)
                            targets.Add(stInsts[0]);
                        firstSt = false;
                    }
                }
                swit.Operand = targets.ToArray();
                insts.Add(end);

                //fix peverify
                foreach (var i in scope.Type.Scopes)
                {
                    if (ScopeDetector.IsFilter(i.Item2) &&
                        (ScopeDetector.IsOnly(i.Item2) || ScopeDetector.IsEnd(i.Item2)))
                    {
                        insts.Add(Instruction.Create(OpCodes.Ldc_I4, Random.Next()));
                        insts.Add(Instruction.Create(OpCodes.Endfilter));
                        break;
                    }
                    else if (ScopeDetector.IsTry(i.Item2) &&
                             (ScopeDetector.IsOnly(i.Item2) || ScopeDetector.IsEnd(i.Item2)))
                    {
                        if (i.Item1.HandlerEnd == null)
                        {
                            insts.Add(Instruction.Create(OpCodes.Ldnull));
                            insts.Add(Instruction.Create(OpCodes.Throw));
                        }
                        else
                        {
                            Instruction last = scope.Instructions[scope.Instructions.Length - 1];
                            insts.Add(Instruction.Create(OpCodes.Leave, last.OpCode != OpCodes.Leave ? i.Item1.HandlerEnd : last.Operand as Instruction));
                        }
                        break;
                    }
                    else if (ScopeDetector.IsHandler(i.Item2) &&
                             (ScopeDetector.IsOnly(i.Item2) || ScopeDetector.IsEnd(i.Item2)))
                    {
                        //it must either finally/fault or catch, not both
                        if (i.Item1.HandlerType == ExceptionHandlerType.Finally ||
                            i.Item1.HandlerType == ExceptionHandlerType.Fault)
                            insts.Add(Instruction.Create(OpCodes.Endfinally));
                        else if (i.Item1.HandlerEnd == null)
                        {
                            insts.Add(Instruction.Create(OpCodes.Ldnull));
                            insts.Add(Instruction.Create(OpCodes.Throw));
                        }
                        else
                        {
                            Instruction last = i.Item1.TryEnd.Previous;
                            insts.Add(Instruction.Create(OpCodes.Leave, last.OpCode != OpCodes.Leave ? i.Item1.HandlerEnd : last.Operand as Instruction));
                        }
                        break;
                    }
                }

                ReplTbl[scope.Instructions[0]] = insts[0];
                scope.Instructions = insts.ToArray();
            }

            //emit
            body.Instructions.Clear();
            foreach (var scope in scopes)
                foreach (var i in scope.Instructions)
                {
                    if (i.Operand is Instruction &&
                        ReplTbl.ContainsKey(i.Operand as Instruction))
                    {
                        i.Operand = ReplTbl[i.Operand as Instruction];
                    }
                    else if (i.Operand is Instruction[])
                    {
                        Instruction[] insts = i.Operand as Instruction[];
                        for (int j = 0; j < insts.Length; j++)
                            if (ReplTbl.ContainsKey(insts[j]))
                                insts[j] = ReplTbl[insts[j]];
                    }
                }
            foreach (var scope in scopes)
            {
                SetLvHandler(scope, body, scope.Instructions);
                foreach (var i in scope.Instructions)
                    body.Instructions.Add(i);
            }

            //fix peverify
            if (!method.ReturnType.IsTypeOf("System", "Void"))
            {
                body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
                body.Instructions.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType));
            }
            body.Instructions.Add(Instruction.Create(OpCodes.Ret));

            foreach (ExceptionHandler eh in body.ExceptionHandlers)
            {
                eh.TryEnd = eh.TryEnd.Next;
                eh.HandlerEnd = eh.HandlerEnd.Next;
            }

            body.ComputeOffsets();
            body.PreserveMaxStackSize = true;

            ReduceSeqPoints(body);
        }