Пример #1
0
        /// <summary>Executes the task.</summary>
        /// <param name="includePatterns">The include patterns.</param>
        /// <param name="excludePatterns">The exclude patterns.</param>
        /// <param name="keyFileName">Name of the key file.</param>
        /// <param name="password">The password.</param>
        /// <param name="force">
        ///     if set to <c>true</c> assemblies will be signed even if they are already signed.
        /// </param>
        public virtual void Execute(
            string[] includePatterns, string[] excludePatterns,
            string keyFileName, string password,
            bool force)
        {
            var keyPair = MsilUtilities.LoadKeyPair(keyFileName, password);

            foreach (var fileName in FindFiles(includePatterns, excludePatterns))
            {
                var assembly = MsilUtilities.LoadAssembly(fileName);

                if (!MsilUtilities.IsManaged(assembly))
                {
                    Log.Warn("Assembly '{0}' is unmanaged, thus cannot be resigned", fileName);
                    continue;
                }

                if (MsilUtilities.IsSigned(assembly))
                {
                    if (force)
                    {
                        Log.Warn("Assembly '{0}' was previously signed, but it going to be resigned with new key", fileName);
                    }
                    else
                    {
                        Log.Debug("Assembly '{0}' is already signed so it does not need resigning", fileName);
                        continue;
                    }
                }

                MsilUtilities.SaveAssembly(assembly, fileName, keyPair);
            }
        }
Пример #2
0
        /// <summary>
        ///     Initializes a new instance of the <see cref="InstrumentHelper" /> class.
        /// </summary>
        /// <param name="targetAssembly">The target assembly.</param>
        /// <param name="bootstrapAssembly">The bootstrap assembly (optional).</param>
        public InstrumentHelper(
            AssemblyDefinition targetAssembly,
            AssemblyDefinition bootstrapAssembly = null)
        {
            var frameworkVersion = MsilUtilities.GetFrameworkVersion(targetAssembly);

            _sourceAssemblyImage = GetInjectedAssemblyImage(frameworkVersion);
            _sourceAssembly      = MsilUtilities.LoadAssembly(_sourceAssemblyImage);

            if (bootstrapAssembly == null)
            {
                _bootstrapAssemblyImage = GetBootstrapAssemblyImage(frameworkVersion);
                _bootstrapAssembly      = MsilUtilities.LoadAssembly(_bootstrapAssemblyImage);
            }
            else
            {
                _bootstrapAssembly = bootstrapAssembly;
                // TODO:MAK it should not be needed, but it would be nice if it gets populated in the future
                _bootstrapAssemblyImage = null;
            }

            if (_sourceAssembly == null || _bootstrapAssembly == null)
            {
                throw new ArgumentException(string.Format(
                                                "Instrumentation assembly could not be found for framework version '{0}'", frameworkVersion));
            }

            _targetAssembly = targetAssembly;
        }
Пример #3
0
        private void SignAndFixAssemblies(StrongNameKeyPair keyPair)
        {
            var sorted = TopologicalSort <AssemblyInfo> .Sort(_assemblyInfos, GetReferencedAssemblies).ToArray();

            foreach (var assemblyInfo in sorted)
            {
                var needsRewrite =
                    !MsilUtilities.IsSigned(assemblyInfo.Assembly) ||
                    assemblyInfo.References.Any(r => r.Invalid) ||
                    assemblyInfo.References.Any(r => r.Target.Rewritten);

                if (!needsRewrite)
                {
                    continue;
                }

                if (!assemblyInfo.CanBeSigned)
                {
                    Log.Warn(
                        "Assembly '{0}' or one of its dependencies is unmanaged or thus it cannot be signed.",
                        assemblyInfo.FileName);

                    assemblyInfo.ReferencedBy
                    .Select(r => r.Source).ToList()
                    .ForEach(a => a.CanBeSigned = false);
                }

                MsilUtilities.SaveAssembly(assemblyInfo.Assembly, assemblyInfo.FileName, keyPair);
                assemblyInfo.Assembly = MsilUtilities.LoadAssembly(assemblyInfo.FileName);
                assemblyInfo.ReferencedBy.ForEach(r => r.Invalid = true);
                assemblyInfo.Rewritten = true;

                FixupReferencesTo(assemblyInfo);
            }
        }
Пример #4
0
        /// <summary>Executes the task.</summary>
        /// <param name="mainFileName">Name of the main file.</param>
        /// <param name="includePatterns">The include patterns.</param>
        /// <param name="excludePatterns">The exclude patterns.</param>
        /// <param name="keyFileName">Name of the key file.</param>
        /// <param name="keyFilePassword">The key file password.</param>
        /// <param name="overwrite">
        ///     if set to <c>true</c> overwrites .dll already embedded.
        /// </param>
        /// <param name="move">
        ///     if set to <c>true</c> moves assembly (deletes source files).
        /// </param>
        public virtual void Execute(
            string mainFileName,
            string[] includePatterns, string[] excludePatterns,
            string keyFileName, string keyFilePassword,
            bool overwrite, bool move)
        {
            if (!File.Exists(mainFileName))
            {
                throw FileNotFound(mainFileName);
            }

            var keyPair  = MsilUtilities.LoadKeyPair(keyFileName, keyFilePassword);
            var assembly = MsilUtilities.LoadAssembly(mainFileName);

            ValidateAsmZInstrumentation(assembly);

            var injectedFileNames = new List <string>();

            foreach (var fileName in FindFiles(includePatterns, excludePatterns))
            {
                var sourceAssembly = MsilUtilities.LoadAssembly(fileName);
                if (sourceAssembly == null)
                {
                    Log.Error("Assembly '{0}' could not be loaded", fileName);
                    continue;
                }

                Log.Info("Injecting '{0}' into '{1}'", fileName, mainFileName);
                if (!InjectDll(assembly, sourceAssembly, File.ReadAllBytes(fileName), overwrite))
                {
                    continue;
                }

                injectedFileNames.Add(fileName);
            }

            if (injectedFileNames.Count <= 0)
            {
                Log.Warn("No files injected: {0}", string.Join(", ", includePatterns));
            }
            else
            {
                Log.Info("Instrumenting assembly with initialization code");
                InstrumentAsmZ(assembly);

                MsilUtilities.SaveAssembly(assembly, mainFileName, keyPair);

                if (move)
                {
                    foreach (var fn in injectedFileNames)
                    {
                        DeleteFile(fn);
                    }
                }
            }
        }
Пример #5
0
        /// <summary>Executes the task.</summary>
        /// <param name="mainFileName">Name of the main file.</param>
        /// <param name="libzFileNames">The libz file names.</param>
        /// <param name="keyFileName">Name of the key file.</param>
        /// <param name="keyFilePassword">The key file password.</param>
        /// <param name="move">
        ///     if set to <c>true</c> moves injected file (deletes the source file).
        /// </param>
        public virtual void Execute(
            string mainFileName, string[] libzFileNames,
            string keyFileName, string keyFilePassword,
            bool move)
        {
            var keyPair           = MsilUtilities.LoadKeyPair(keyFileName, keyFilePassword);
            var assembly          = MsilUtilities.LoadAssembly(mainFileName);
            var injectedFileNames = new List <string>();

            // TODO:MAK exclude?
            foreach (var libzFileName in FindFiles(libzFileNames))
            {
                if (libzFileName == null)
                {
                    throw ArgumentNull("libzFileName");
                }
                if (!File.Exists(libzFileName))
                {
                    throw FileNotFound(libzFileName);
                }
                if (!File.Exists(mainFileName))
                {
                    throw FileNotFound(mainFileName);
                }

                var fileName = Path.GetFileName(libzFileName);                 // TODO:MAK relative path?

                var resourceName = "libz://" + HashString(fileName);
                var resource     = new EmbeddedResource(
                    resourceName,
                    ManifestResourceAttributes.Public,
                    File.ReadAllBytes(libzFileName));
                assembly.MainModule.Resources.Add(resource);
                Log.Info("Injecting '{0}' into '{1}'", libzFileName, mainFileName);
                injectedFileNames.Add(libzFileName);
            }

            if (injectedFileNames.Count <= 0)
            {
                Log.Warn("No files injected: {0}", string.Join(", ", libzFileNames));
            }
            else
            {
                MsilUtilities.SaveAssembly(assembly, mainFileName, keyPair);
                if (move)
                {
                    foreach (var fn in injectedFileNames)
                    {
                        DeleteFile(fn);
                    }
                }
            }
        }
Пример #6
0
        /// <summary>Validates if LibZResolver can be injected.</summary>
        /// <param name="assembly">The target assembly.</param>
        /// <exception cref="System.ArgumentException">If assembly is targeting unsupported version.</exception>
        protected static void ValidateLibZInstrumentation(AssemblyDefinition assembly)
        {
            var version = MsilUtilities.GetFrameworkVersion(assembly);

            if (version >= new Version("4.0.0.0"))
            {
                return;
            }
            if (version < new Version("2.0.0.0") || version == new Version("2.0.5.0"))
            {
                throw new ArgumentException(
                          string.Format("Cannot inject code into assemblies targeting '{0}'", version));
            }
            if (version < new Version("3.5.0.0"))
            {
                Log.Warn(string.Format("Attempting to inject assemblies into assembly targeting '{0}'.", version));
                Log.Warn("LibZResolver will work only if .NET 3.5 is also installed on target machine");
            }
        }
Пример #7
0
        /// <summary>Validates if AsmZResolver can be injected.</summary>
        /// <param name="assembly">The target assembly.</param>
        /// <exception cref="System.ArgumentException">If assembly is targeting unsupported version.</exception>
        protected static void ValidateAsmZInstrumentation(AssemblyDefinition assembly)
        {
            var version = MsilUtilities.GetFrameworkVersion(assembly);

            if (version >= new Version("4.0.0.0"))
            {
                return;
            }
            if (version < new Version("2.0.0.0") || version == new Version("2.0.5.0"))
            {
                throw new ArgumentException(
                          string.Format("Cannot inject code into assemblies targeting '{0}'", version));
            }
            if (version < new Version("3.5.0.0"))
            {
                Log.Warn(string.Format("Attempting to inject AsmZResolver into assembly targeting framework '{0}'.", version));
                Log.Warn("AsmZResolver should work but is neither designed nor tested with this framework.");
            }
        }
Пример #8
0
        public void Execute(
            string keyFileName, string keyFilePassword,
            string[] includePatterns, string[] excludePatterns)
        {
            var keyPair   = MsilUtilities.LoadKeyPair(keyFileName, keyFilePassword);
            var fileNames = FindFiles(includePatterns, excludePatterns).ToArray();

            foreach (var fileName in fileNames)
            {
                var assembly     = MsilUtilities.LoadAssembly(fileName);
                var assemblyInfo = new AssemblyInfo {
                    FileName    = fileName,
                    Assembly    = assembly,
                    CanBeSigned = MsilUtilities.IsManaged(assembly),
                };
                _assemblyInfos.Add(assemblyInfo);
            }

            ScanDependencies();
            SignAndFixAssemblies(keyPair);
        }
Пример #9
0
        /// <summary>Executes the task.</summary>
        /// <param name="mainFileName">Name of the main file.</param>
        /// <param name="allLibZResources">
        ///     if set to <c>true</c> loads all LibZ files in resources on startup.
        /// </param>
        /// <param name="libzFiles">The LibZ files to be loaded on startup.</param>
        /// <param name="libzPatterns">The libz file patterns to be loaded on startup.</param>
        /// <param name="keyFileName">Name of the key file.</param>
        /// <param name="keyFilePassword">The key file password.</param>
        public virtual void Execute(
            string mainFileName,
            bool allLibZResources,
            string[] libzFiles,
            string[] libzPatterns,
            string keyFileName, string keyFilePassword)
        {
            if (!File.Exists(mainFileName))
            {
                throw FileNotFound(mainFileName);
            }
            if (libzFiles == null)
            {
                libzFiles = new string[0];
            }
            if (libzPatterns == null)
            {
                libzPatterns = new string[0];
            }

            var targetAssembly = MsilUtilities.LoadAssembly(mainFileName);

            ValidateLibZInstrumentation(targetAssembly);

            var keyPair = MsilUtilities.LoadKeyPair(keyFileName, keyFilePassword);
            var requiresAsmZResolver = false;

            var bootstrapAssembly =
                FindBootstrapAssembly(targetAssembly, mainFileName);

            if (bootstrapAssembly == null)
            {
                var version = MsilUtilities.GetFrameworkVersion(targetAssembly);

                var bootstrapAssemblyImage = InstrumentHelper.GetBootstrapAssemblyImage(version);
                bootstrapAssembly = MsilUtilities.LoadAssembly(bootstrapAssemblyImage);

                if (bootstrapAssembly == null)
                {
                    throw new ArgumentException("LibZ.Bootstrap has not been found");
                }

                Log.Info("Using built in LibZResolver");

                InjectDll(
                    targetAssembly,
                    bootstrapAssembly,
                    bootstrapAssemblyImage,
                    true);
                requiresAsmZResolver = true;
            }

            _instrumentHelper = new InstrumentHelper(
                targetAssembly,
                bootstrapAssembly);

            _instrumentHelper.InjectLibZInitializer();
            if (requiresAsmZResolver)
            {
                _instrumentHelper.InjectAsmZResolver();
            }
            _instrumentHelper.InjectLibZStartup(allLibZResources, libzFiles, libzPatterns);

            MsilUtilities.SaveAssembly(targetAssembly, mainFileName, keyPair);
        }
Пример #10
0
        /// <summary>Injects the DLL.</summary>
        /// <param name="targetAssembly">The target assembly.</param>
        /// <param name="sourceAssembly">The source assembly.</param>
        /// <param name="sourceAssemblyBytes">The source assembly bytes.</param>
        /// <param name="overwrite">
        ///     if set to <c>true</c> overwrites existing resource.
        /// </param>
        /// <returns>
        ///     <c>true</c> if assembly has been injected.
        /// </returns>
        protected static bool InjectDll(
            AssemblyDefinition targetAssembly,
            AssemblyDefinition sourceAssembly, byte[] sourceAssemblyBytes,
            bool overwrite)
        {
            var flags = String.Empty;

            if (!MsilUtilities.IsManaged(sourceAssembly))
            {
                flags += "u";
            }
            if (MsilUtilities.IsPortable(sourceAssembly))
            {
                flags += "p";
            }

            var input  = sourceAssemblyBytes;
            var output = DefaultCodecs.DeflateEncoder(input);

            if (output.Length < input.Length)
            {
                flags += "z";
            }
            else
            {
                output = input;
            }

            var architecture       = MsilUtilities.GetArchitecture(sourceAssembly);
            var architecturePrefix =
                architecture == AssemblyArchitecture.X64 ? "x64:" :
                architecture == AssemblyArchitecture.X86 ? "x86:" :
                string.Empty;
            var guid = Hash(architecturePrefix + sourceAssembly.FullName);

            var resourceName = String.Format(
                "asmz://{0:N}/{1}/{2}",
                guid, input.Length, flags);

            var existing = targetAssembly.MainModule.Resources
                           .Where(r => Hash(r) == guid)
                           .ToArray();

            if (existing.Length > 0)
            {
                if (overwrite)
                {
                    Log.Warn("Resource '{0}' already exists and is going to be replaced.", resourceName);
                    foreach (var r in existing)
                    {
                        targetAssembly.MainModule.Resources.Remove(r);
                    }
                }
                else
                {
                    Log.Warn("Resource '{0}' already exists and will be skipped.", resourceName);
                    return(false);
                }
            }

            var resource = new EmbeddedResource(
                resourceName,
                ManifestResourceAttributes.Public,
                output);

            targetAssembly.MainModule.Resources.Add(resource);

            return(true);
        }
Пример #11
0
        /// <summary>Executes the task.</summary>
        /// <param name="libzFileName">Name of the libz file.</param>
        /// <param name="includePatterns">The include patterns.</param>
        /// <param name="excludePatterns">The exclude patterns.</param>
        /// <param name="codecName">Name of the codec.</param>
        /// <param name="safeLoad">if set to <c>true</c> 'safe load' if requested.</param>
        /// <param name="move">if set to <c>true</c> moves files (deletes soure files).</param>
        /// <param name="overwrite">if set to <c>true</c> overwrites existing resources.</param>
        public virtual void Execute(
            string libzFileName,
            string[] includePatterns, string[] excludePatterns,
            string codecName, bool safeLoad, bool move, bool overwrite)
        {
            var injectedFileNames = new List <string>();

            if (string.IsNullOrEmpty(codecName))
            {
                codecName = "deflate";
            }

            using (var container = new LibZContainer(libzFileName, true))
            {
                foreach (var fileName in FindFiles(includePatterns, excludePatterns))
                {
                    var assembly = MsilUtilities.LoadAssembly(fileName);
                    if (assembly == null)
                    {
                        Log.Warn("Assembly from '{0}' could not be loaded", fileName);
                        continue;
                    }
                    var assemblyName = assembly.Name;
                    var managed      = MsilUtilities.IsManaged(assembly);
                    var architecture = MsilUtilities.GetArchitecture(assembly);
                    var portable     = MsilUtilities.IsPortable(assembly);

                    var assemblyInfo = new AssemblyInfo {
                        AssemblyName = new AssemblyName(assemblyName.FullName),
                        AnyCPU       = architecture == AssemblyArchitecture.AnyCPU,
                        X64          = architecture == AssemblyArchitecture.X64,
                        SafeLoad     = safeLoad,
                        Unmanaged    = !managed,
                        Portable     = portable,
                        Bytes        = File.ReadAllBytes(fileName),
                    };

                    Log.Info("Appending '{0}' from '{1}'", assemblyInfo.AssemblyName, fileName);

                    container.Append(
                        assemblyInfo,
                        new AppendOptions {
                        CodecName = codecName, Overwrite = overwrite,
                    });

                    injectedFileNames.Add(fileName);
                }

                if (injectedFileNames.Count <= 0)
                {
                    Log.Warn("No files injected: {0}", string.Join(", ", includePatterns));
                }
                else
                {
                    if (move)
                    {
                        foreach (var fn in injectedFileNames)
                        {
                            DeleteFile(fn);
                        }
                    }
                }
            }
        }
Пример #12
0
        private void ScanDependencies()
        {
            var foundByLongName  = new HashSet <string>();
            var foundByShortName = new HashSet <Tuple <string, string> >();
            var notFound         = new HashSet <string>();

            foreach (var assemblyInfo in _assemblyInfos)
            {
                foreach (var referenceName in assemblyInfo.ReferencedNames)
                {
                    var found = false;

                    foreach (var otherAssemblyInfo in _assemblyInfos)
                    {
                        if (found)
                        {
                            break;
                        }
                        if (!MsilUtilities.EqualAssemblyNames(referenceName.FullName, otherAssemblyInfo.AssemblyName.FullName))
                        {
                            continue;
                        }

                        foundByLongName.Add(referenceName.FullName);

                        var reference = new AssemblyInfoReference {
                            ReferencedAssemblyName = referenceName,
                            Source  = assemblyInfo,
                            Target  = otherAssemblyInfo,
                            Invalid = false,
                        };

                        assemblyInfo.References.Add(reference);
                        otherAssemblyInfo.ReferencedBy.Add(reference);

                        found = true;
                    }

                    foreach (var otherAssemblyInfo in _assemblyInfos)
                    {
                        if (found)
                        {
                            break;
                        }
                        if (!MsilUtilities.EqualAssemblyNames(referenceName.Name, otherAssemblyInfo.AssemblyName.Name))
                        {
                            continue;
                        }

                        foundByShortName.Add(Tuple.Create(referenceName.FullName, otherAssemblyInfo.AssemblyName.FullName));

                        var reference = new AssemblyInfoReference {
                            Source  = assemblyInfo,
                            Target  = otherAssemblyInfo,
                            Invalid = true,
                        };

                        assemblyInfo.References.Add(reference);
                        otherAssemblyInfo.ReferencedBy.Add(reference);

                        found = true;
                    }

                    if (!found)
                    {
                        notFound.Add(referenceName.FullName);
                    }
                }
            }

            foundByLongName.OrderBy(v => v).ToList()
            .ForEach(n => Log.Info("Assembly '{0}' has been successfully resolved", n));
            foundByShortName.OrderBy(v => v.Item1).ToList()
            .ForEach(t => Log.Info("Assembly '{0}' has been resolved to '{1}' using short name", t.Item1, t.Item2));
            notFound.OrderBy(v => v).ToList()
            .ForEach(n => Log.Warn("Assembly '{0}' has not been found", n));
        }