void Decrypt(IBinaryReader reader, int delegateTypeToken, ISimpleDeobfuscator simpleDeobfuscator)
        {
            var delegateType = module.ResolveToken(delegateTypeToken) as TypeDef;

            if (delegateType == null)
            {
                throw new ApplicationException("Couldn't find delegate type");
            }

            int delToken, encMethToken, encDeclToken;

            if (!GetTokens(delegateType, out delToken, out encMethToken, out encDeclToken))
            {
                throw new ApplicationException("Could not find encrypted method tokens");
            }
            if (delToken != delegateTypeToken)
            {
                throw new ApplicationException("Invalid delegate type token");
            }
            var encType = module.ResolveToken(encDeclToken) as ITypeDefOrRef;

            if (encType == null)
            {
                throw new ApplicationException("Invalid declaring type token");
            }
            var encMethod = module.ResolveToken(encMethToken) as MethodDef;

            if (encMethod == null)
            {
                throw new ApplicationException("Invalid encrypted method token");
            }

            var bodyReader = new MethodBodyReader(module, reader);

            bodyReader.Read(encMethod);
            bodyReader.RestoreMethod(encMethod);
            Logger.v("Restored method {0} ({1:X8}). Instrs:{2}, Locals:{3}, Exceptions:{4}",
                     Utils.RemoveNewlines(encMethod.FullName),
                     encMethod.MDToken.ToInt32(),
                     encMethod.Body.Instructions.Count,
                     encMethod.Body.Variables.Count,
                     encMethod.Body.ExceptionHandlers.Count);
            delegateTypes.Add(delegateType);
            simpleDeobfuscator.MethodModified(encMethod);
        }
		void RestoreMethodBodies(ISimpleDeobfuscator simpleDeobfuscator) {
			var methodToOrigMethods = new MethodDefAndDeclaringTypeDict<List<MethodDef>>();
			foreach (var t in module.Types) {
				var types = new List<TypeDef>(AllTypesHelper.Types(new List<TypeDef> { t }));
				foreach (var type in types) {
					if (methodsTypes.Find(type))
						continue;
					foreach (var method in type.Methods) {
						if (method.Name == ".ctor" || method.Name == ".cctor")
							continue;

						MethodDef calledMethod;
						if (!CheckRestoreBody(method, out calledMethod))
							continue;
						if (!CheckSameMethods(method, calledMethod))
							continue;
						if (!methodsTypes.Find(calledMethod.DeclaringType))
							continue;
						if (types.IndexOf(calledMethod.DeclaringType) < 0)
							continue;

						var list = methodToOrigMethods.Find(calledMethod);
						if (list == null)
							methodToOrigMethods.Add(calledMethod, list = new List<MethodDef>());
						list.Add(method);
					}
				}
			}

			foreach (var calledMethod in methodToOrigMethods.GetKeys()) {
				var list = methodToOrigMethods.Find(calledMethod);
				var method = list[0];

				Logger.v("Restored method body {0:X8} from method {1:X8}",
							method.MDToken.ToInt32(),
							calledMethod.MDToken.ToInt32());
				DotNetUtils.CopyBodyFromTo(calledMethod, method);
				classMethods.Add(calledMethod, method);
				simpleDeobfuscator.MethodModified(method);
			}
		}
		void Decrypt(IBinaryReader reader, int delegateTypeToken, ISimpleDeobfuscator simpleDeobfuscator) {
			var delegateType = module.ResolveToken(delegateTypeToken) as TypeDef;
			if (delegateType == null)
				throw new ApplicationException("Couldn't find delegate type");

			int delToken, encMethToken, encDeclToken;
			if (!GetTokens(delegateType, out delToken, out encMethToken, out encDeclToken))
				throw new ApplicationException("Could not find encrypted method tokens");
			if (delToken != delegateTypeToken)
				throw new ApplicationException("Invalid delegate type token");
			var encType = module.ResolveToken(encDeclToken) as ITypeDefOrRef;
			if (encType == null)
				throw new ApplicationException("Invalid declaring type token");
			var encMethod = module.ResolveToken(encMethToken) as MethodDef;
			if (encMethod == null)
				throw new ApplicationException("Invalid encrypted method token");

			var bodyReader = new MethodBodyReader(module, reader);
			bodyReader.Read(encMethod);
			bodyReader.RestoreMethod(encMethod);
			Logger.v("Restored method {0} ({1:X8}). Instrs:{2}, Locals:{3}, Exceptions:{4}",
					Utils.RemoveNewlines(encMethod.FullName),
					encMethod.MDToken.ToInt32(),
					encMethod.Body.Instructions.Count,
					encMethod.Body.Variables.Count,
					encMethod.Body.ExceptionHandlers.Count);
			delegateTypes.Add(delegateType);
			simpleDeobfuscator.MethodModified(encMethod);
		}
        void RestoreMethodBodies(ISimpleDeobfuscator simpleDeobfuscator)
        {
            var methodToOrigMethods = new MethodDefAndDeclaringTypeDict <List <MethodDef> >();

            foreach (var t in module.Types)
            {
                var types = new List <TypeDef>(AllTypesHelper.Types(new List <TypeDef> {
                    t
                }));
                foreach (var type in types)
                {
                    if (methodsTypes.Find(type))
                    {
                        continue;
                    }
                    foreach (var method in type.Methods)
                    {
                        if (method.Name == ".ctor" || method.Name == ".cctor")
                        {
                            continue;
                        }

                        MethodDef calledMethod;
                        if (!CheckRestoreBody(method, out calledMethod))
                        {
                            continue;
                        }
                        if (!CheckSameMethods(method, calledMethod))
                        {
                            continue;
                        }
                        if (!methodsTypes.Find(calledMethod.DeclaringType))
                        {
                            continue;
                        }
                        if (types.IndexOf(calledMethod.DeclaringType) < 0)
                        {
                            continue;
                        }

                        var list = methodToOrigMethods.Find(calledMethod);
                        if (list == null)
                        {
                            methodToOrigMethods.Add(calledMethod, list = new List <MethodDef>());
                        }
                        list.Add(method);
                    }
                }
            }

            foreach (var calledMethod in methodToOrigMethods.GetKeys())
            {
                var list   = methodToOrigMethods.Find(calledMethod);
                var method = list[0];

                Logger.v("Restored method body {0:X8} from method {1:X8}",
                         method.MDToken.ToInt32(),
                         calledMethod.MDToken.ToInt32());
                DotNetUtils.CopyBodyFromTo(calledMethod, method);
                classMethods.Add(calledMethod, method);
                simpleDeobfuscator.MethodModified(method);
            }
        }