/// <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); } }
/// <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; }
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); } }
/// <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); } } } }
/// <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); } } } }
/// <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"); } }
/// <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."); } }
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); }
/// <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); }
/// <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); }
/// <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); } } } } }
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)); }