Exemple #1
0
        public static MethodAttributes ConvertToHookAttributes(this MethodAttributes originalAttrs)
        {
            var newAttrs = originalAttrs;

            newAttrs &= ~(MethodAttributes.Assembly | MethodAttributes.Private);
            newAttrs |= MethodAttributes.Public;
            return(newAttrs);
        }
        static void RemoveCall(MethodDef method)
        {
            var instructions = method.Body.Instructions;

            foreach (var instr in instructions)
            {
                if (instr.OpCode != OpCodes.Call)
                {
                    continue;
                }

                var tamperMethod = instr.Operand as MethodDef;
                if (tamperMethod == null)
                {
                    continue;
                }
                if (!tamperMethod.DeclaringType.IsGlobalModuleType)
                {
                    continue;
                }

                const MethodAttributes attributes = MethodAttributes.Assembly | MethodAttributes.Static |
                                                    MethodAttributes.HideBySig;
                if (tamperMethod.Attributes != attributes)
                {
                    continue;
                }
                if (tamperMethod.CodeType != MethodImplAttributes.IL)
                {
                    continue;
                }

                if (tamperMethod.ReturnType.ElementType != ElementType.Void)
                {
                    continue;
                }

                // The decrypter method just have 1 call to VirtualProtect
                if (tamperMethod.FindInstructionsNumber(OpCodes.Call, "(System.IntPtr,System.UInt32,System.UInt32,System.UInt32&)") != 1)
                {
                    continue;
                }
                instr.OpCode  = OpCodes.Nop;
                instr.Operand = null;
                Logger.Verbose("Anti-tamper decrypter call was removed from .cctor.");
                return;
            }
        }
        /// <summary>
        /// Creates a property method (getter or setter).
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="returnType">Type of the return.</param>
        /// <param name="parameters">The parameters.</param>
        /// <returns></returns>
        private static MethodDefUser CreatePropertyMethod(string name, TypeSig returnType, params Tuple <TypeSig, string>[] parameters)
        {
            const MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
            var methodSig        = new MethodSig(CallingConvention.HasThis, 0, returnType, parameters.Select(p => p.Item1).ToArray());
            var methodDefinition = new MethodDefUser(name, methodSig, methodAttributes);
            var methodParameters = new MethodParameters(methodDefinition);

            for (int index = 0; index < parameters.Length; index++)
            {
                methodParameters[0].ParamDef.Name = parameters[index].Item2;
            }
            methodDefinition.Body = new CilBody {
                InitLocals = true
            };
            return(methodDefinition);
        }
Exemple #4
0
        void FindDecrypterMethods(ModuleDef module)
        {
            foreach (var method in module.GlobalType.Methods)
            {
                const MethodAttributes attributes =
                    MethodAttributes.Assembly | MethodAttributes.Static | MethodAttributes.HideBySig;
                if (method.Attributes != attributes)
                {
                    continue;
                }

                if (method.GenericParameters.Count != 1)
                {
                    continue;
                }
                if (method.Parameters.Count != 1)
                {
                    continue;
                }
                if (method.Parameters[0].Type.ElementType != ElementType.U4)
                {
                    continue;
                }
                if (method.FindInstructionsNumber(OpCodes.Call,
                                                  "System.Buffer::BlockCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32)") != 2)
                {
                    continue;
                }
                if (method.FindInstructionsNumber(OpCodes.Call,
                                                  "System.Array::CreateInstance(System.Type,System.Int32)") != 1)
                {
                    continue;
                }
                if (method.FindInstructionsNumber(OpCodes.Callvirt,
                                                  "System.Text.Encoding::GetString(System.Byte[],System.Int32,System.Int32)") != 1)
                {
                    continue;
                }

                decrypterMethods.Add(method);
                Logger.Verbose($"Constant decrypter method detected: {method.FullName}.");
            }
            Logger.Verbose($"Decrypter methods detected: {decrypterMethods.Count}.");
        }
        static void RemoveCall(MethodDef method)
        {
            var instructions = method.Body.Instructions;

            foreach (var instr in instructions)
            {
                if (instr.OpCode != OpCodes.Call)
                {
                    continue;
                }

                var tamperMethod = instr.Operand as MethodDef;
                if (tamperMethod == null)
                {
                    continue;
                }

                const MethodAttributes attributes = MethodAttributes.Assembly | MethodAttributes.Static |
                                                    MethodAttributes.HideBySig;
                if (tamperMethod.Attributes != attributes)
                {
                    continue;
                }
                if (tamperMethod.CodeType != dnlib.DotNet.MethodImplAttributes.IL)
                {
                    continue;
                }

                if (tamperMethod.ReturnType.ElementType != ElementType.Void)
                {
                    continue;
                }

                instr.OpCode  = OpCodes.Nop;
                instr.Operand = null;
                return;
            }
        }
Exemple #6
0
        void RemoveInitializeCall(ModuleDef module)
        {
            var cctor        = module.GlobalType.FindStaticConstructor();
            var instructions = cctor.Body.Instructions;

            foreach (var instruction in instructions)
            {
                if (instruction.OpCode != OpCodes.Call)
                {
                    continue;
                }

                var initializeMethod = instruction.Operand as MethodDef;
                if (initializeMethod == null)
                {
                    continue;
                }
                if (!initializeMethod.DeclaringType.IsGlobalModuleType)
                {
                    continue;
                }

                const MethodAttributes attributes =
                    MethodAttributes.Assembly | MethodAttributes.Static | MethodAttributes.HideBySig;
                if (initializeMethod.Attributes != attributes)
                {
                    continue;
                }

                if (initializeMethod.ReturnType.ElementType != ElementType.Void)
                {
                    continue;
                }
                if (initializeMethod.HasParamDefs)
                {
                    continue;
                }

                if (initializeMethod.FindInstructionsNumber(OpCodes.Call,
                                                            "System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(System.Array,System.RuntimeFieldHandle)") != 1)
                {
                    continue;
                }

                var field   = FindArrayField(module);
                var operand = (from instr in initializeMethod.Body.Instructions
                               where instr.OpCode == OpCodes.Stsfld
                               let fieldArray = instr.Operand as FieldDef
                                                where fieldArray != null
                                                where field == fieldArray
                                                select instr.Operand.ToString()).FirstOrDefault();

                if (initializeMethod.FindInstructionsNumber(OpCodes.Stsfld, operand) != 1)
                {
                    continue;
                }

                instruction.OpCode  = OpCodes.Nop;
                instruction.Operand = null;
                Logger.Verbose("Removed constans initialize call.");
            }
        }
        /// <summary>
        /// Weaves the interface.
        /// What we do here is:
        /// - creating a class (which is named after the interface name)
        /// - this class implements all interface members
        /// - all members invoke Invocation.ProcessInterfaceMethod
        /// </summary>
        /// <param name="moduleDefinition">The module definition.</param>
        /// <param name="interfaceType">Type of the interface.</param>
        /// <param name="context">The context.</param>
        private void WeaveInterface(ModuleDefMD moduleDefinition, TypeDef interfaceType, WeavingContext context)
        {
            var importedInterfaceType = moduleDefinition.Import(interfaceType);

            Logging.WriteDebug("Weaving interface '{0}'", interfaceType.FullName);
            TypeDef implementationType;
            TypeDef advisedInterfaceType;

            lock (moduleDefinition)
            {
                // ensure we're creating the interface only once
                var implementationTypeName      = GetImplementationTypeName(interfaceType.Name);
                var implementationTypeNamespace = interfaceType.Namespace;
                if (moduleDefinition.GetTypes().Any(t => t.Namespace == implementationTypeNamespace && t.Name == implementationTypeName))
                {
                    return;
                }

                // now, create the implementation type
                var typeAttributes = (InjectAsPrivate ? TypeAttributes.NotPublic : TypeAttributes.Public) | TypeAttributes.Class |
                                     TypeAttributes.BeforeFieldInit;
                advisedInterfaceType = TypeResolver.Resolve(moduleDefinition, typeof(AdvisedInterface));
                // TODO: this should work using TypeImporter.Import
                var advisedInterfaceTypeReference = moduleDefinition.Import(advisedInterfaceType);
                implementationType = new TypeDefUser(implementationTypeNamespace, implementationTypeName, advisedInterfaceTypeReference)
                {
                    Attributes = typeAttributes
                };
                implementationType.Interfaces.Add(new InterfaceImplUser(importedInterfaceType));

                lock (moduleDefinition)
                    moduleDefinition.Types.Add(implementationType);
            }

            // create empty .ctor. This .NET mofo wants it!
            var baseEmptyConstructor = moduleDefinition.SafeImport(advisedInterfaceType.FindConstructors().Single());
            const MethodAttributes ctorAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName |
                                                    MethodAttributes.RTSpecialName;
            var method = new MethodDefUser(".ctor", baseEmptyConstructor.MethodSig, ctorAttributes);

            method.Body = new CilBody();
            method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
            method.Body.Instructions.Add(Instruction.Create(OpCodes.Call, baseEmptyConstructor));
            method.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
            implementationType.Methods.Add(method);

            // create implementation methods
            foreach (var currentInterfaceType in interfaceType.GetAllInterfaces(TypeResolver))
            {
                foreach (var interfaceMethod in currentInterfaceType.Methods.Where(m => !m.IsSpecialName))
                {
                    WeaveInterfaceMethod(interfaceMethod, implementationType, true, context);
                }

                // create implementation properties
                foreach (var interfaceProperty in currentInterfaceType.Properties)
                {
                    var implementationProperty = new PropertyDefUser(interfaceProperty.Name, interfaceProperty.PropertySig);
                    implementationType.Properties.Add(implementationProperty);
                    if (interfaceProperty.GetMethod != null)
                    {
                        implementationProperty.GetMethod = WeaveInterfaceMethod(interfaceProperty.GetMethod, implementationType, InjectAsPrivate, context);
                    }
                    if (interfaceProperty.SetMethod != null)
                    {
                        implementationProperty.SetMethod = WeaveInterfaceMethod(interfaceProperty.SetMethod, implementationType, InjectAsPrivate, context);
                    }
                }

                // create implementation events
                foreach (var interfaceEvent in currentInterfaceType.Events)
                {
                    var implementationEvent = new EventDefUser(interfaceEvent.Name, interfaceEvent.EventType);
                    implementationType.Events.Add(implementationEvent);
                    if (interfaceEvent.AddMethod != null)
                    {
                        implementationEvent.AddMethod = WeaveInterfaceMethod(interfaceEvent.AddMethod, implementationType, InjectAsPrivate, context);
                    }
                    if (interfaceEvent.RemoveMethod != null)
                    {
                        implementationEvent.RemoveMethod = WeaveInterfaceMethod(interfaceEvent.RemoveMethod, implementationType, InjectAsPrivate, context);
                    }
                }
            }
        }
        /// <summary>
        /// Weaves the specified method.
        /// </summary>
        /// <param name="markedMethod">The marked method.</param>
        /// <param name="context">The context.</param>
        private void WeaveAdvices(MarkedNode markedMethod, WeavingContext context)
        {
            var method = markedMethod.Node.Method;

            // sanity check
            if (!method.HasReturnType)
            {
                var customAttributes = method.CustomAttributes;
                if (customAttributes.Any(c => c.AttributeType.Name == "AsyncStateMachineAttribute"))
                {
                    Logging.WriteWarning("Advising async void method '{0}' could confuse async advices. Consider switching its return type to async Task.", method.FullName);
                }
            }

            if (method.IsAbstract)
            {
                method.Attributes = (method.Attributes & ~MethodAttributes.Abstract) | MethodAttributes.Virtual;
                Logging.WriteDebug("Weaving abstract method '{0}'", method.FullName);
                WritePointcutBody(method, null, false, context);
            }
            else if (markedMethod.AbstractTarget)
            {
                Logging.WriteDebug("Weaving and abstracting method '{0}'", method.FullName);
                WritePointcutBody(method, null, true, context);
            }
            else
            {
                Logging.WriteDebug("Weaving method '{0}'", method.FullName);

                var methodName = method.Name;

                // create inner method
                const MethodAttributes attributesToKeep = MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.PInvokeImpl |
                                                          MethodAttributes.UnmanagedExport | MethodAttributes.HasSecurity |
                                                          MethodAttributes.RequireSecObject;
                var innerMethodAttributes = method.Attributes & attributesToKeep |
                                            (InjectAsPrivate ? MethodAttributes.Private : MethodAttributes.Public);
                string innerMethodName;
                if (method.IsGetter)
                {
                    innerMethodName = GetPropertyInnerGetterName(GetSpecialOwnerName(methodName));
                }
                else if (method.IsSetter)
                {
                    innerMethodName = GetPropertyInnerSetterName(GetSpecialOwnerName(methodName));
                }
                else if (method.IsAddOn)
                {
                    innerMethodName = GetEventInnerAdderName(GetSpecialOwnerName(methodName));
                }
                else if (method.IsRemoveOn)
                {
                    innerMethodName = GetEventInnerRemoverName(GetSpecialOwnerName(methodName));
                }
                else
                {
                    innerMethodName = GetInnerMethodName(methodName);
                }
                var innerMethod = new MethodDefUser(innerMethodName, method.MethodSig, innerMethodAttributes);
                new MethodParameters(method).SetParamDefs(innerMethod);
                innerMethod.GenericParameters.AddRange(method.GenericParameters.Select(p => p.Clone(innerMethod)));
                innerMethod.ImplAttributes      = method.ImplAttributes;
                innerMethod.SemanticsAttributes = method.SemanticsAttributes;
                if (method.IsPinvokeImpl)
                {
                    innerMethod.ImplMap  = method.ImplMap;
                    method.ImplMap       = null;
                    method.IsPreserveSig = false;
                    method.IsPinvokeImpl = false;
                }
                else
                {
                    innerMethod.Body = method.Body;
                    method.Body      = new CilBody();
                }

                AddGeneratedAttribute(innerMethod, context);

                lock (method.DeclaringType)
                    method.DeclaringType.Methods.Add(innerMethod);

                var stepInfos = innerMethod.CustomDebugInfos.OfType <PdbAsyncMethodCustomDebugInfo>().SelectMany(d => d.StepInfos).ToArray();
                for (var stepInfoIndex = 0; stepInfoIndex < stepInfos.Length; stepInfoIndex++)
                {
                    var stepInfo = stepInfos[stepInfoIndex];
                    Logging.WriteDebug("Found stepInfo for '{0}'", stepInfo.BreakpointMethod.ToString());
                    if (stepInfo.BreakpointMethod.SafeEquivalent(method))
                    {
                        Logging.WriteDebug("Replacing '{0}' with '{1}'", stepInfo.BreakpointMethod.ToString(), innerMethod.ToString());
                        stepInfo.BreakpointMethod = innerMethod;
                        stepInfos[stepInfoIndex]  = stepInfo;
                    }
                }

                WritePointcutBody(method, innerMethod, false, context);
            }
        }
Exemple #9
0
        /// <summary>
        /// Weaves the specified method.
        /// </summary>
        /// <param name="markedMethod">The marked method.</param>
        /// <param name="context">The context.</param>
        private void WeaveAdvices(MarkedNode markedMethod, WeavingContext context)
        {
            var method = markedMethod.Node.Method;

            // sanity check
            var moduleDefinition = (ModuleDefMD)method.Module;

            if (method.ReturnType.SafeEquivalent(moduleDefinition.CorLibTypes.Void))
            {
                var customAttributes = method.CustomAttributes;
                if (customAttributes.Any(c => c.AttributeType.Name == "AsyncStateMachineAttribute"))
                {
                    Logging.WriteWarning("Advising async void method '{0}' could confuse async advices. Consider switching its return type to async Task.",
                                         method.FullName);
                }
            }

            if (method.IsAbstract)
            {
                method.Attributes = (method.Attributes & ~MethodAttributes.Abstract) | MethodAttributes.Virtual;
                Logging.WriteDebug("Weaving abstract method '{0}'", method.FullName);
                WritePointcutBody(method, null, false, context);
            }
            else if (markedMethod.AbstractTarget)
            {
                Logging.WriteDebug("Weaving and abstracting method '{0}'", method.FullName);
                WritePointcutBody(method, null, true, context);
            }
            else
            {
                Logging.WriteDebug("Weaving method '{0}'", method.FullName);

                var methodName = method.Name;

                // create inner method
                const MethodAttributes attributesToKeep = MethodAttributes.Static | MethodAttributes.HideBySig | MethodAttributes.PInvokeImpl |
                                                          MethodAttributes.UnmanagedExport | MethodAttributes.HasSecurity |
                                                          MethodAttributes.RequireSecObject;
                var innerMethodAttributes = method.Attributes & attributesToKeep |
                                            (InjectAsPrivate ? MethodAttributes.Private : MethodAttributes.Public);
                string innerMethodName;
                if (method.IsGetter)
                {
                    innerMethodName = GetPropertyInnerGetterName(GetSpecialOwnerName(methodName));
                }
                else if (method.IsSetter)
                {
                    innerMethodName = GetPropertyInnerSetterName(GetSpecialOwnerName(methodName));
                }
                else if (method.IsAddOn)
                {
                    innerMethodName = GetEventInnerAdderName(GetSpecialOwnerName(methodName));
                }
                else if (method.IsRemoveOn)
                {
                    innerMethodName = GetEventInnerRemoverName(GetSpecialOwnerName(methodName));
                }
                else
                {
                    innerMethodName = GetInnerMethodName(methodName);
                }
                var innerMethod = new MethodDefUser(innerMethodName, method.MethodSig, innerMethodAttributes);
                new MethodParameters(method).SetParamDefs(innerMethod);
                innerMethod.GenericParameters.AddRange(method.GenericParameters.Select(p => p.Clone(innerMethod)));
                innerMethod.ImplAttributes      = method.ImplAttributes;
                innerMethod.SemanticsAttributes = method.SemanticsAttributes;
                if (method.IsPinvokeImpl)
                {
                    innerMethod.ImplMap  = method.ImplMap;
                    method.ImplMap       = null;
                    method.IsPreserveSig = false;
                    method.IsPinvokeImpl = false;
                }
                else
                {
                    innerMethod.Body = method.Body;
                    method.Body      = new CilBody();
                }

                AddGeneratedAttribute(innerMethod, context);

                lock (method.DeclaringType)
                    method.DeclaringType.Methods.Add(innerMethod);

                WritePointcutBody(method, innerMethod, false, context);
            }
        }