private void PatchTyped(ModuleDef module, MethodDef method, int id) { var body = new CilBody(); method.Body = body; id = 45 * id; body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, id * 10)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, id * 5)); body.Instructions.Add(Instruction.Create(OpCodes.Ldtoken, method.DeclaringType)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, id * 20)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, id * 15)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, method.Parameters.Count)); body.Instructions.Add(Instruction.Create(OpCodes.Newarr, new PtrSig(method.Module.CorLibTypes.Void).ToTypeDefOrRef())); foreach (Parameter param in method.Parameters) { body.Instructions.Add(Instruction.Create(OpCodes.Dup)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, param.Index)); if (!param.Type.IsByRef) { body.Instructions.Add(Instruction.Create(OpCodes.Ldarga, param)); body.Instructions.Add(Instruction.Create(OpCodes.Mkrefany, param.Type.ToTypeDefOrRef())); } else { body.Instructions.Add(Instruction.Create(OpCodes.Ldarg, param)); body.Instructions.Add(Instruction.Create(OpCodes.Mkrefany, param.Type.Next.ToTypeDefOrRef())); } var local = new Local(method.Module.CorLibTypes.TypedReference); body.Variables.Add(local); body.Instructions.Add(Instruction.Create(OpCodes.Stloc, local)); body.Instructions.Add(Instruction.Create(OpCodes.Ldloca, local)); body.Instructions.Add(Instruction.Create(OpCodes.Conv_I)); body.Instructions.Add(Instruction.Create(OpCodes.Stelem_I)); } if (method.ReturnType.GetElementType() != ElementType.Void) { var retVar = new Local(method.ReturnType); var retRef = new Local(method.Module.CorLibTypes.TypedReference); body.Variables.Add(retVar); body.Variables.Add(retRef); body.Instructions.Add(Instruction.Create(OpCodes.Ldloca, retVar)); body.Instructions.Add(Instruction.Create(OpCodes.Mkrefany, method.ReturnType.ToTypeDefOrRef())); body.Instructions.Add(Instruction.Create(OpCodes.Stloc, retRef)); body.Instructions.Add(Instruction.Create(OpCodes.Ldloca, retRef)); body.Instructions.Add(Instruction.Create(OpCodes.Call, method.Module.Import(this.vmEntryTyped))); body.Instructions.Add(Instruction.Create(OpCodes.Ldloc, retVar)); } else { body.Instructions.Add(Instruction.Create(OpCodes.Ldnull)); body.Instructions.Add(Instruction.Create(OpCodes.Call, method.Module.Import(this.vmEntryTyped))); } body.Instructions.Add(Instruction.Create(OpCodes.Ret)); body.OptimizeMacros(); }
private void PatchNormal(ModuleDef module, MethodDef method, int id) { var body = new CilBody(); method.Body = body; id = 63493 * id; body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, id * 10)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, id * 5)); body.Instructions.Add(Instruction.Create(OpCodes.Ldtoken, method.DeclaringType)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, id * 20)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, id * 15)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, method.Parameters.Count)); body.Instructions.Add(Instruction.Create(OpCodes.Newarr, method.Module.CorLibTypes.Object.ToTypeDefOrRef())); foreach (Parameter param in method.Parameters) { body.Instructions.Add(Instruction.Create(OpCodes.Dup)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, param.Index)); body.Instructions.Add(Instruction.Create(OpCodes.Ldarg, param)); if (!param.Type.IsValueType) { if (param.Type.IsPointer) { body.Instructions.Add(Instruction.Create(OpCodes.Conv_U)); body.Instructions.Add(Instruction.Create(OpCodes.Box, method.Module.CorLibTypes.UIntPtr.ToTypeDefOrRef())); } } else { body.Instructions.Add(Instruction.Create(OpCodes.Box, param.Type.ToTypeDefOrRef())); } body.Instructions.Add(Instruction.Create(OpCodes.Stelem_Ref)); } body.Instructions.Add(Instruction.Create(OpCodes.Call, method.Module.Import(this.vmEntryNormal))); if (method.ReturnType.ElementType != ElementType.Void) { if (!method.ReturnType.IsValueType) { body.Instructions.Add(Instruction.Create(OpCodes.Castclass, method.ReturnType.ToTypeDefOrRef())); } else { body.Instructions.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType.ToTypeDefOrRef())); } } else { body.Instructions.Add(Instruction.Create(OpCodes.Pop)); } body.Instructions.Add(Instruction.Create(OpCodes.Ret)); body.OptimizeMacros(); }
public static Action <MethodDef> ApplyInject(this MethodBase inject, PatchConfiguration patch) => stub => { CilBody stubBody = stub.Body; MethodBody injectBody = inject.GetMethodBody(); List <Instruction> originalIL = new List <Instruction>(stubBody.Instructions); List <Local> originalLocals = new List <Local>(stubBody.Variables); stubBody.Variables.Clear(); foreach (LocalVariableInfo local in injectBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex)) { stubBody.Variables.Add(stub.Module.ToDNLib(local)); } List <Instruction> mixinIL = new CilParser(inject.Module, stubBody.Variables, injectBody.GetILAsByteArray()).Parse(); mixinIL.SimplifyMacros(stubBody.Variables, stub.Parameters); IList <Instruction> newIL = stubBody.Instructions; newIL.Clear(); foreach (Instruction inst in mixinIL) { switch (inst.Operand) { case FieldInfo field: inst.Operand = patch.ResolveOrImport(stub.Module, field); break; case MethodBase method: if (method.IsDefined(typeof(BaseDependencyAttribute))) { throw new InvalidOperationException("attempt to inject a body with a base dependency call"); } inst.Operand = patch.ResolveOrImport(stub.Module, method); break; case Type type: inst.Operand = patch.ResolveOrImport(stub.Module, type); break; case byte[] blob: throw new NotImplementedException("how do you import this?"); case MemberInfo member: throw new NotImplementedException("how do you import this?"); } newIL.Add(inst); } stubBody.ExceptionHandlers.Clear(); foreach (ExceptionHandlingClause ehc in injectBody.ExceptionHandlingClauses) { stubBody.ExceptionHandlers.Add(ehc.ToDNLib(stub.Module, newIL)); } stubBody.OptimizeMacros(); };
void PatchNormal(ModuleDef module, MethodDef method, int id) { var body = new CilBody(); method.Body = body; body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, id)); body.Instructions.Add(Instruction.Create(OpCodes.Ldstr, "cracked.to/AndyLarkin | AndyLarkin#3553")); body.Instructions.Add(Instruction.Create(OpCodes.Ldtoken, method.DeclaringType)); body.Instructions.Add(Instruction.Create(OpCodes.Ldstr, gx(id))); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, method.Parameters.Count)); body.Instructions.Add(Instruction.Create(OpCodes.Newarr, method.Module.CorLibTypes.Object.ToTypeDefOrRef())); foreach (var param in method.Parameters) { body.Instructions.Add(Instruction.Create(OpCodes.Dup)); body.Instructions.Add(Instruction.Create(OpCodes.Ldc_I4, param.Index)); body.Instructions.Add(Instruction.Create(OpCodes.Ldarg, param)); if (param.Type.IsValueType) { body.Instructions.Add(Instruction.Create(OpCodes.Box, param.Type.ToTypeDefOrRef())); } else if (param.Type.IsPointer) { body.Instructions.Add(Instruction.Create(OpCodes.Conv_U)); body.Instructions.Add(Instruction.Create(OpCodes.Box, method.Module.CorLibTypes.UIntPtr.ToTypeDefOrRef())); } body.Instructions.Add(Instruction.Create(OpCodes.Stelem_Ref)); } body.Instructions.Add(Instruction.Create(OpCodes.Call, method.Module.Import(vmEntryNormal))); if (method.ReturnType.ElementType == ElementType.Void) { body.Instructions.Add(Instruction.Create(OpCodes.Pop)); } else if (method.ReturnType.IsValueType) { body.Instructions.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType.ToTypeDefOrRef())); } else { body.Instructions.Add(Instruction.Create(OpCodes.Castclass, method.ReturnType.ToTypeDefOrRef())); } body.Instructions.Add(Instruction.Create(OpCodes.Ret)); body.OptimizeMacros(); }
public static Action <MethodDef> ApplyMixin(this MethodBase mixin, PatchConfiguration patch) => original => { CilBody originalBody = original.Body; MethodBody mixinBody = mixin.GetMethodBody(); List <Instruction> originalIL = new List <Instruction>(originalBody.Instructions); List <Local> originalLocals = new List <Local>(originalBody.Variables); originalBody.Variables.Clear(); foreach (LocalVariableInfo local in mixinBody.LocalVariables.OrderBy(lvi => lvi.LocalIndex)) { originalBody.Variables.Add(original.Module.ToDNLib(local)); } List <Instruction> mixinIL = new CilParser(mixin.Module, originalBody.Variables, mixinBody.GetILAsByteArray()).Parse(); mixinIL.SimplifyMacros(originalBody.Variables, original.Parameters); IList <Instruction> newIL = originalBody.Instructions; newIL.Clear(); int ilStart = 0; if (mixin.IsConstructor) { foreach (Instruction inst in mixin.IsDefined(typeof(RewriteBaseAttribute)) ? mixinIL : originalIL) { ilStart++; newIL.Add(inst); if (inst.OpCode.FlowControl == FlowControl.Call) { break; } } RemoveCall(originalIL); RemoveCall(mixinIL); } MethodDef baseCopy = new MethodDefUser(original.DeclaringType.FindUnusedMethodName(original.Name + "<Base>$"), original.MethodSig, original.ImplAttributes, original.Attributes & CopyMask | CopyAttr); bool useBase = false; foreach (Instruction inst in mixinIL) { switch (inst.Operand) { case FieldInfo field: inst.Operand = patch.ResolveOrImport(original.Module, field); break; case MethodBase method: if (method.IsDefined(typeof(BaseDependencyAttribute))) { useBase = true; inst.Operand = baseCopy; break; } inst.Operand = patch.ResolveOrImport(original.Module, method); break; case Type type: inst.Operand = patch.ResolveOrImport(original.Module, type); break; case byte[] blob: throw new NotImplementedException("how do you import this?"); case MemberInfo member: throw new NotImplementedException("how do you import this?"); } newIL.Add(inst); } if (useBase) { baseCopy.Body = new CilBody(originalBody.InitLocals, originalIL, new List <ExceptionHandler>(originalBody.ExceptionHandlers), originalBody.Variables); original.DeclaringType.Methods.Add(baseCopy); } originalBody.ExceptionHandlers.Clear(); foreach (ExceptionHandlingClause ehc in mixinBody.ExceptionHandlingClauses) { originalBody.ExceptionHandlers.Add(ehc.ToDNLib(original.Module, newIL)); } originalBody.OptimizeMacros(); void RemoveCall(List <Instruction> il) { for (int index = 0; index < il.Count; index++) { if (il[index].OpCode.FlowControl != FlowControl.Call) { continue; } il.RemoveRange(0, index + 1); break; } } };