387 lines
16 KiB
C#
387 lines
16 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using BMDevs.Runtime;
|
|
using dnlib.DotNet;
|
|
using dnlib.DotNet.Emit;
|
|
|
|
namespace BMDevs.Mutations
|
|
{
|
|
public class Add : iMutation
|
|
{
|
|
public void Prepare(TypeDef type) { }
|
|
|
|
public void Process(MethodDef method, ref int index)
|
|
{
|
|
var defvalue = method.Body.Instructions[index].GetLdcI4Value();
|
|
var inda = RuntimeHelper.Random.Next((int)((double)defvalue / 1.5));
|
|
method.Body.Instructions[index].OpCode = OpCodes.Ldc_I4;
|
|
method.Body.Instructions[index].Operand = defvalue - inda;
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldc_I4, inda));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Add));
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return Utils.CheckArithmetic(instr);
|
|
}
|
|
}
|
|
|
|
public class Sub : iMutation
|
|
{
|
|
public void Prepare(TypeDef type) { }
|
|
|
|
public void Process(MethodDef method, ref int index)
|
|
{
|
|
var defvalue = method.Body.Instructions[index].GetLdcI4Value();
|
|
var two = RuntimeHelper.Random.Next((int)((double)defvalue / 1.5));
|
|
method.Body.Instructions[index].OpCode = OpCodes.Ldc_I4;
|
|
method.Body.Instructions[index].Operand = defvalue + two;
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldc_I4, two));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Sub));
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return Utils.CheckArithmetic(instr);
|
|
}
|
|
}
|
|
|
|
public class Mul : iMutation
|
|
{
|
|
public void Prepare(TypeDef type) { }
|
|
|
|
public void Process(MethodDef method, ref int index)
|
|
{
|
|
var defvalue = method.Body.Instructions[index].GetLdcI4Value();
|
|
var two = RuntimeHelper.Random.Next(1, (int)((double)defvalue / 1.5));
|
|
var one = defvalue / two;
|
|
//ERROR HERE DONT USE THIS WHILE LOOP
|
|
while (two * one != defvalue)
|
|
{
|
|
two = RuntimeHelper.Random.Next(1, (int)((double)defvalue / 1.5));
|
|
one = defvalue / two;
|
|
}
|
|
method.Body.Instructions[index].OpCode = OpCodes.Ldc_I4;
|
|
method.Body.Instructions[index].Operand = one;
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldc_I4, two));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Mul));
|
|
index += 1;
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return Utils.CheckArithmetic(instr);
|
|
}
|
|
}
|
|
|
|
public class Div : iMutation
|
|
{
|
|
public void Prepare(TypeDef type) { }
|
|
|
|
public void Process(MethodDef method, ref int index)
|
|
{
|
|
var defvalue = method.Body.Instructions[index].GetLdcI4Value();
|
|
var two = RuntimeHelper.Random.Next(1, 5);
|
|
method.Body.Instructions[index].OpCode = OpCodes.Ldc_I4;
|
|
method.Body.Instructions[index].Operand = defvalue * two;
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldc_I4, two));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Div));
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return Utils.CheckArithmetic(instr);
|
|
}
|
|
}
|
|
|
|
public class Abs : iMutation
|
|
{
|
|
public void Prepare(TypeDef type) { }
|
|
|
|
public void Process(MethodDef method, ref int index)
|
|
{
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Call, method.Module.Import(typeof(Math).GetMethod("Abs", new Type[] { typeof(int) }))));
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return Utils.CheckArithmetic(instr);
|
|
}
|
|
}
|
|
|
|
public class StringLen : iMutation
|
|
{
|
|
public void Prepare(TypeDef type) { }
|
|
|
|
public void Process(MethodDef method, ref int index)
|
|
{
|
|
if (method.DeclaringType == method.Module.GlobalType)
|
|
{
|
|
index--;
|
|
return;
|
|
}
|
|
int defval = method.Body.Instructions[index].GetLdcI4Value();
|
|
int needed = RuntimeHelper.Random.Next(4, 15);
|
|
//string ch = Renamer.GetFuckedString(needed);
|
|
string ch = Renamer.GetFuckedString2(needed);
|
|
method.Body.Instructions[index].OpCode = OpCodes.Ldc_I4;
|
|
method.Body.Instructions[index].Operand = defval - needed;
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldstr, ch));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Call, method.Module.Import(typeof(string).GetMethod("get_Length"))));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Add));
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return Utils.CheckArithmetic(instr);
|
|
}
|
|
}
|
|
|
|
public class Func : iMutation
|
|
{
|
|
public FieldDef Decryptor { get; set; }
|
|
|
|
public void Process(MethodDef method, ref int index)
|
|
{
|
|
int nde = method.Body.Instructions[index].GetLdcI4Value();
|
|
method.Body.Instructions[index].OpCode = OpCodes.Ldsfld;
|
|
method.Body.Instructions[index].Operand = Decryptor;
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldc_I4, nde));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Callvirt, method.Module.Import(typeof(Func<int, int>).GetMethod("Invoke"))));
|
|
index -= 2;
|
|
}
|
|
|
|
public FieldDef CreateProperField(TypeDef type)
|
|
{
|
|
var cotype = RuntimeHelper.GetRuntimeType("BMDevs.Runtime.FuncMutation");
|
|
FieldDef field = cotype.Fields.FirstOrDefault(x => x.Name == "prao");
|
|
Renamer.Rename(field, Renamer.RenameMode.Base64, 3);
|
|
field.DeclaringType = null;
|
|
type.Fields.Add(field);
|
|
MethodDef funcmethod = cotype.FindMethod("RET");
|
|
funcmethod.DeclaringType = null;
|
|
Renamer.Rename(funcmethod, Renamer.RenameMode.Base64, 3);
|
|
type.Methods.Add(funcmethod);
|
|
|
|
var cctor = type.FindOrCreateStaticConstructor();
|
|
cctor.Body.Instructions.Insert(0, new Instruction(OpCodes.Ldnull));
|
|
cctor.Body.Instructions.Insert(1, new Instruction(OpCodes.Ldftn, funcmethod));
|
|
cctor.Body.Instructions.Insert(2, new Instruction(OpCodes.Newobj, type.Module.Import(typeof(Func<int, int>).GetConstructors().First())));
|
|
cctor.Body.Instructions.Insert(3, new Instruction(OpCodes.Stsfld, field));
|
|
cctor.Body.Instructions.Insert(4, new Instruction(OpCodes.Nop));
|
|
return field;
|
|
}
|
|
|
|
public void Prepare(TypeDef type)
|
|
{
|
|
Decryptor = CreateProperField(type);
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return Utils.CheckArithmetic(instr);
|
|
}
|
|
}
|
|
|
|
//thanks to TheProxy#5615 for explanation
|
|
public class CharMutations : iMutation
|
|
{
|
|
public MethodDef Converter { get; set; }
|
|
|
|
public void Prepare(TypeDef type)
|
|
{
|
|
var cotype = RuntimeHelper.GetRuntimeType("BMDevs.Runtime.FuncMutation");
|
|
MethodDef todef = cotype.FindMethod("CharToInt");
|
|
todef.Name = Renamer.GetRandomName().Base64Representation();
|
|
todef.DeclaringType = null;
|
|
type.Methods.Add(todef);
|
|
Converter = todef;
|
|
}
|
|
|
|
public void Process(MethodDef method, ref int index)
|
|
{
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Call, Converter));
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return Utils.CheckArithmetic(instr);
|
|
}
|
|
}
|
|
|
|
public class VariableMutation : iMutation
|
|
{
|
|
public void Prepare(TypeDef type) { }
|
|
|
|
public void Process(MethodDef method, ref int index)
|
|
{
|
|
var value = method.Body.Instructions[index].GetLdcI4Value();
|
|
Local lcl = new Local(method.Module.CorLibTypes.Int32);
|
|
method.Body.Variables.Add(lcl);
|
|
method.Body.Instructions.Insert(0, new Instruction(OpCodes.Stloc, lcl));
|
|
method.Body.Instructions.Insert(0, new Instruction(OpCodes.Ldc_I4, value));
|
|
index += 2;
|
|
method.Body.Instructions[index] = new Instruction(OpCodes.Ldloc, lcl);
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return Utils.CheckArithmetic(instr);
|
|
}
|
|
}
|
|
|
|
public class ComparerMutation : iMutation
|
|
{
|
|
public void Prepare(TypeDef type)
|
|
{
|
|
if (type != type.Module.GlobalType)
|
|
for (int i = 0; i < type.Methods.Count; i++)
|
|
{
|
|
var mDef = type.Methods[i];
|
|
if (!mDef.HasBody || mDef.IsConstructor) continue;
|
|
mDef.Body.SimplifyBranches();
|
|
for (int x = 0; x < mDef.Body.Instructions.Count; x++)
|
|
{
|
|
if (Utils.CheckArithmetic(mDef.Body.Instructions[x]))
|
|
{
|
|
Execute(mDef, ref x);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Execute(MethodDef method, ref int index)
|
|
{
|
|
if (method.Body.Instructions[index].OpCode != OpCodes.Call)
|
|
{
|
|
var value = method.Body.Instructions[index].GetLdcI4Value();
|
|
Local lcl = new Local(method.Module.CorLibTypes.Int32);
|
|
Local lcl2 = new Local(method.Module.CorLibTypes.Int32);
|
|
method.Body.Variables.Add(lcl);
|
|
method.Body.Variables.Add(lcl2);
|
|
|
|
var initial = RuntimeHelper.Random.Next();
|
|
var ifstate = RuntimeHelper.Random.Next();
|
|
int initial2;
|
|
|
|
bool shouldBeEqual = Convert.ToBoolean(RuntimeHelper.Random.Next(2));
|
|
if (shouldBeEqual)
|
|
initial2 = ifstate - initial;
|
|
else
|
|
{
|
|
initial2 = RuntimeHelper.Random.Next();
|
|
while (initial2 + initial == ifstate)
|
|
initial2 = RuntimeHelper.Random.Next();
|
|
}
|
|
|
|
|
|
method.Body.Instructions[index] = Instruction.CreateLdcI4(initial);
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Stloc, lcl));
|
|
method.Body.Instructions.Insert(++index, Instruction.CreateLdcI4(initial2));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Stloc, lcl2));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldloc, lcl));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldloc, lcl2));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Add));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldc_I4, ifstate));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ceq));
|
|
Instruction nop = OpCodes.Nop.ToInstruction();
|
|
method.Body.Instructions.Insert(++index, new Instruction(shouldBeEqual ? OpCodes.Brfalse : OpCodes.Brtrue, nop));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Nop));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldc_I4, value));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Stloc, lcl));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Nop));
|
|
Instruction ldloc = OpCodes.Ldloc_S.ToInstruction(lcl);
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Br, ldloc));
|
|
method.Body.Instructions.Insert(++index, nop);
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldc_I4, RuntimeHelper.Random.Next()));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Stloc, lcl));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Nop));
|
|
method.Body.Instructions.Insert(++index, ldloc);
|
|
}
|
|
}
|
|
|
|
public void Process(MethodDef method, ref int index) { }
|
|
|
|
public static void InsertInstructions(IList<Instruction> instructions, Dictionary<Instruction, int> keyValuePairs)
|
|
{
|
|
foreach (KeyValuePair<Instruction, int> kv in keyValuePairs)
|
|
{
|
|
Instruction instruction = kv.Key;
|
|
int index = kv.Value;
|
|
instructions.Insert(index, instruction);
|
|
}
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return Utils.CheckArithmetic(instr);
|
|
}
|
|
}
|
|
|
|
public class MulToShift : iMutation
|
|
{
|
|
public void Prepare(TypeDef type) { }
|
|
|
|
//this shit converts expressions like num * 5 into num + num << 1 + num << 2
|
|
|
|
public void Process(MethodDef method, ref int index)
|
|
{
|
|
if (method.Body.Instructions[index - 1].IsLdcI4() && method.Body.Instructions[index - 2].IsLdcI4())
|
|
{
|
|
var wl = method.Body.Instructions[index - 2].GetLdcI4Value();
|
|
|
|
var val = method.Body.Instructions[index - 1].GetLdcI4Value();
|
|
if (val >= 3)
|
|
{
|
|
Local lcl = new Local(method.Module.CorLibTypes.Int32);
|
|
method.Body.Variables.Add(lcl);
|
|
|
|
method.Body.Instructions.Insert(0, new Instruction(OpCodes.Stloc, lcl));
|
|
method.Body.Instructions.Insert(0, new Instruction(OpCodes.Ldc_I4, wl));
|
|
index += 2;
|
|
|
|
method.Body.Instructions[index - 2].OpCode = OpCodes.Ldloc;
|
|
method.Body.Instructions[index - 2].Operand = lcl;
|
|
|
|
//now we have lcl * val
|
|
method.Body.Instructions[index - 1].OpCode = OpCodes.Nop;
|
|
method.Body.Instructions[index].OpCode = OpCodes.Nop;
|
|
|
|
int count = 0;
|
|
int curval = val;
|
|
while (curval > 0)
|
|
{
|
|
// check for set bit and left
|
|
// shift n, count times
|
|
if ((curval & 1) == 1)
|
|
{
|
|
if (count != 0)
|
|
{
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldloc, lcl));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldc_I4, count));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Shl));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Add));
|
|
}
|
|
}
|
|
count++;
|
|
curval = curval >> 1;
|
|
}
|
|
if ((val & 1) == 0)
|
|
{
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Ldloc, lcl));
|
|
method.Body.Instructions.Insert(++index, new Instruction(OpCodes.Sub));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool Supported(Instruction instr)
|
|
{
|
|
return instr.OpCode == OpCodes.Mul;
|
|
}
|
|
}
|
|
}
|