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(); }
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; }
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; }
public abstract Expression GenerateInverse(Expression arg);
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(); }
public abstract void VisitPreOrder(Expression exp);
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); }
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); }