예제 #1
0
        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);
        }
예제 #2
0
        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);
        }