public static int Execute(ModuleDef module, Module reflModule) { if (module is null) { throw new ArgumentNullException(nameof(module)); } if (reflModule is null) { throw new ArgumentNullException(nameof(reflModule)); } var decrypters = new HashSet <MethodDef>(); foreach (var method in module.GlobalType.Methods) { if (!method.HasBody) { continue; } if (!method.IsStatic || !method.HasGenericParameters) { continue; } if (method.ReturnType.ElementType != ElementType.MVar || method.Parameters.Count != 1 || method.Parameters[0].Type.ElementType != ElementType.U4) { continue; } decrypters.Add(method); } var oldAssemblyResolver = module.Context.AssemblyResolver; var oldResolver = module.Context.Resolver; module.Context.AssemblyResolver = NullResolver.Instance; module.Context.Resolver = new Resolver(NullResolver.Instance); int count = 0; foreach (var method in module.EnumerateMethods()) { if (!method.HasBody) { continue; } if (decrypters.Contains(method)) { continue; } method.Body.SimplifyMacros(method.Parameters); for (int i = 1; i < method.Body.Instructions.Count; i++) { var instructions = method.Body.Instructions; var instruction = instructions[i]; if (instruction.OpCode.Code != Code.Call) { continue; } if (!(instruction.Operand is MethodSpec operandMethod)) { continue; } if (!(operandMethod.Method is MethodDef operandMethodDef)) { continue; } if (!decrypters.Contains(operandMethodDef)) { continue; } var ldKeyInstr = default(Instruction); int key = 0; for (int j = 1; j <= i; j++) { var instr = instructions[i - j]; if (instr.OpCode.Code == Code.Nop) { continue; } if (instr.OpCode.Code != Code.Ldc_I4) { break; } ldKeyInstr = instr; key = (int)instr.Operand; break; } if (ldKeyInstr is null) { Logger.LogError($"[0x{method.MDToken.Raw:X8}] 无法找到常量解密器参数"); continue; } var constantType = operandMethod.GenericInstMethodSig.GenericArguments[0].RemoveModifiers(); var elementType = constantType.ElementType; var arrayType = default(TypeSig); var arrayElementType = default(ElementType); var reflType = ToType(elementType); if (reflType is null) { if (elementType != ElementType.SZArray) { Logger.LogError($"[0x{method.MDToken.Raw:X8}] 无效常量解密器泛型参数"); continue; } var arraySig = (SZArraySig)operandMethod.GenericInstMethodSig.GenericArguments[0]; arrayType = arraySig.Next.RemoveModifiers(); arrayElementType = arrayType.ElementType; reflType = ToType(arrayElementType); if (reflType is null) { Logger.LogError($"[0x{method.MDToken.Raw:X8}] 无效常量解密器泛型参数"); continue; } } object value; try { var reflMethod = reflModule.ResolveMethod(operandMethod.MDToken.ToInt32()); value = reflMethod.Invoke(null, new object[] { (uint)key }); } catch (Exception ex) { Logger.LogError($"[0x{method.MDToken.Raw:X8}] 调用常量解密器失败"); Logger.LogException(ex); continue; } if (value is null) { Logger.LogError($"[0x{method.MDToken.Raw:X8}] 常量解密器返回值为空"); continue; } if (elementType != ElementType.SZArray) { switch (elementType) { case ElementType.Boolean: case ElementType.Char: case ElementType.I1: case ElementType.U1: case ElementType.I2: case ElementType.U2: case ElementType.I4: case ElementType.U4: instruction.OpCode = OpCodes.Ldc_I4; instruction.Operand = Convert.ToInt32(value); break; case ElementType.I8: case ElementType.U8: instruction.OpCode = OpCodes.Ldc_I8; instruction.Operand = Convert.ToInt64(value); break; case ElementType.R4: instruction.OpCode = OpCodes.Ldc_R4; instruction.Operand = value; break; case ElementType.R8: instruction.OpCode = OpCodes.Ldc_R8; instruction.Operand = value; break; case ElementType.String: instruction.OpCode = OpCodes.Ldstr; instruction.Operand = value; break; default: throw new InvalidOperationException(); } } else { int elementSize; switch (arrayElementType) { case ElementType.Boolean: case ElementType.I1: case ElementType.U1: elementSize = 1; break; case ElementType.Char: case ElementType.I2: case ElementType.U2: elementSize = 2; break; case ElementType.I4: case ElementType.U4: case ElementType.R4: elementSize = 4; break; case ElementType.I8: case ElementType.U8: case ElementType.R8: elementSize = 8; break; default: throw new InvalidOperationException(); } byte[] data = new byte[((Array)value).Length * elementSize]; Buffer.BlockCopy((Array)value, 0, data, 0, data.Length); var arrayInitializer = CreateArrayInitializer(module, arrayType.ToTypeDefOrRef(), ((Array)value).Length, data); instructions.InsertRange(i, arrayInitializer); instruction.OpCode = OpCodes.Nop; instruction.Operand = null; i += arrayInitializer.Count; } ldKeyInstr.OpCode = OpCodes.Nop; ldKeyInstr.Operand = null; count++; } } module.Context.AssemblyResolver = oldAssemblyResolver; module.Context.Resolver = oldResolver; foreach (var decrypter in decrypters) { decrypter.DeclaringType.Methods.Remove(decrypter); } return(count); }
public static int Execute(ModuleDef module, bool ignoreAccess, bool removeProxyMethods) { if (module is null) { throw new ArgumentNullException(nameof(module)); } var proxyMethods = new Dictionary <MethodDef, Instruction>(); foreach (var method in module.EnumerateMethods()) { if (!method.HasBody) { continue; } if (!(ignoreAccess || method.IsPrivateScope)) { continue; } bool isProxy = true; var realInstruction = default(Instruction); foreach (var instruction in method.Body.Instructions) { switch (instruction.OpCode.Code) { case Code.Nop: case Code.Ldarg: case Code.Ldarg_0: case Code.Ldarg_1: case Code.Ldarg_2: case Code.Ldarg_3: case Code.Ldarg_S: case Code.Ldarga: case Code.Ldarga_S: case Code.Ret: continue; case Code.Call: case Code.Callvirt: case Code.Newobj: if (realInstruction is null) { realInstruction = instruction; continue; } break; } isProxy = false; break; } if (!isProxy) { Logger.LogWarning($"[0x{method.MDToken.Raw:X8}] {method} 不是代理方法(可能判断错误)"); continue; } proxyMethods.Add(method, realInstruction); } var oldAssemblyResolver = module.Context.AssemblyResolver; var oldResolver = module.Context.Resolver; module.Context.AssemblyResolver = NullResolver.Instance; module.Context.Resolver = new Resolver(NullResolver.Instance); foreach (var method in module.EnumerateMethods()) { if (!method.HasBody) { continue; } if (proxyMethods.ContainsKey(method)) { continue; } foreach (var instruction in method.Body.Instructions) { if (instruction.OpCode.Code != Code.Call) { continue; } var operandMethod = ((IMethod)instruction.Operand).ResolveMethodDef(); if (operandMethod is null) { continue; } if (!proxyMethods.TryGetValue(operandMethod, out var realCall)) { continue; } instruction.OpCode = realCall.OpCode; instruction.Operand = realCall.Operand; } } module.Context.AssemblyResolver = oldAssemblyResolver; module.Context.Resolver = oldResolver; if (removeProxyMethods) { foreach (var proxyMethod in proxyMethods.Keys) { proxyMethod.DeclaringType.Methods.Remove(proxyMethod); } } return(proxyMethods.Count); }