From 5535e24193082da3e05a99f0f7bbb5a8489c6322 Mon Sep 17 00:00:00 2001 From: Michael Wagner <43564011+horschmwagner@users.noreply.github.com> Date: Thu, 2 Mar 2023 15:47:31 +0100 Subject: [PATCH] Update ConfuserEngine.cs Confuser does write debug files (.pdb) even if debug=false in project file. --- Confuser.Core/ConfuserEngine.cs | 1074 ++++++++++++++++--------------- 1 file changed, 538 insertions(+), 536 deletions(-) diff --git a/Confuser.Core/ConfuserEngine.cs b/Confuser.Core/ConfuserEngine.cs index 519f8585..26df8a4c 100644 --- a/Confuser.Core/ConfuserEngine.cs +++ b/Confuser.Core/ConfuserEngine.cs @@ -1,551 +1,553 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using Confuser.Core.Project; -using Confuser.Core.Services; -using dnlib.DotNet; -using dnlib.DotNet.Emit; -using dnlib.DotNet.Writer; -using Microsoft.Win32; -using InformationalAttribute = System.Reflection.AssemblyInformationalVersionAttribute; -using ProductAttribute = System.Reflection.AssemblyProductAttribute; -using CopyrightAttribute = System.Reflection.AssemblyCopyrightAttribute; -using MethodAttributes = dnlib.DotNet.MethodAttributes; -using MethodImplAttributes = dnlib.DotNet.MethodImplAttributes; -using TypeAttributes = dnlib.DotNet.TypeAttributes; - -namespace Confuser.Core { - /// - /// The processing engine of ConfuserEx. - /// - public static class ConfuserEngine { - /// - /// The version of ConfuserEx. - /// - public static readonly string Version; - - static readonly string Copyright; - - static ConfuserEngine() { - Assembly assembly = typeof(ConfuserEngine).Assembly; - var nameAttr = (ProductAttribute)assembly.GetCustomAttributes(typeof(ProductAttribute), false)[0]; - var verAttr = (InformationalAttribute)assembly.GetCustomAttributes(typeof(InformationalAttribute), false)[0]; - var cpAttr = (CopyrightAttribute)assembly.GetCustomAttributes(typeof(CopyrightAttribute), false)[0]; - Version = string.Format("{0} {1}", nameAttr.Product, verAttr.InformationalVersion); - Copyright = cpAttr.Copyright; - - AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => { - try { - var asmName = new AssemblyName(e.Name); - foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) - if (asm.GetName().Name == asmName.Name) - return asm; - return null; - } - catch { - return null; - } - }; - } - - /// - /// Runs the engine with the specified parameters. - /// - /// The parameters. - /// The token used for cancellation. - /// Task to run the engine. - /// - /// .Project is null. - /// - public static Task Run(ConfuserParameters parameters, CancellationToken? token = null) { - if (parameters.Project == null) - throw new ArgumentNullException("parameters"); - if (token == null) - token = new CancellationTokenSource().Token; - return Task.Factory.StartNew(() => RunInternal(parameters, token.Value), token.Value); - } - - /// - /// Runs the engine. - /// - /// The parameters. - /// The cancellation token. - static void RunInternal(ConfuserParameters parameters, CancellationToken token) { - // 1. Setup context - var context = new ConfuserContext(); - context.Logger = parameters.GetLogger(); - context.Project = parameters.Project.Clone(); - context.PackerInitiated = parameters.PackerInitiated; - context.token = token; - - PrintInfo(context); - - bool ok = false; - try { - // Enable watermarking by default - context.Project.Rules.Insert(0, new Rule { - new SettingItem(WatermarkingProtection._Id) - }); - - var asmResolver = new ConfuserAssemblyResolver {EnableTypeDefCache = true}; - asmResolver.DefaultModuleContext = new ModuleContext(asmResolver); - context.InternalResolver = asmResolver; - context.BaseDirectory = Path.Combine(Environment.CurrentDirectory, context.Project.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar); - context.OutputDirectory = Path.Combine(context.Project.BaseDirectory, context.Project.OutputDirectory.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar); - foreach (string probePath in context.Project.ProbePaths) - asmResolver.PostSearchPaths.Insert(0, Path.Combine(context.BaseDirectory, probePath)); - - context.CheckCancellation(); - - Marker marker = parameters.GetMarker(); - - // 2. Discover plugins - context.Logger.Debug("Discovering plugins..."); - - IList prots; - IList packers; - IList components; - parameters.GetPluginDiscovery().GetPlugins(context, out prots, out packers, out components); - - context.Logger.InfoFormat("Discovered {0} protections, {1} packers.", prots.Count, packers.Count); - - context.CheckCancellation(); - - // 3. Resolve dependency - context.Logger.Debug("Resolving component dependency..."); - try { - var resolver = new DependencyResolver(prots); - prots = resolver.SortDependency(); - } - catch (CircularDependencyException ex) { - context.Logger.ErrorException("", ex); - throw new ConfuserException(ex); - } - - components.Insert(0, new CoreComponent(context, marker)); - foreach (Protection prot in prots) - components.Add(prot); - foreach (Packer packer in packers) - components.Add(packer); - - context.CheckCancellation(); - - // 4. Load modules - context.Logger.Info("Loading input modules..."); - marker.Initalize(prots, packers); - MarkerResult markings = marker.MarkProject(context.Project, context); - context.Modules = new ModuleSorter(markings.Modules).Sort().ToList().AsReadOnly(); - foreach (var module in context.Modules) - module.EnableTypeDefFindCache = false; - context.OutputModules = Enumerable.Repeat(null, context.Modules.Count).ToArray(); - context.OutputSymbols = Enumerable.Repeat(null, context.Modules.Count).ToArray(); - context.OutputPaths = Enumerable.Repeat(null, context.Modules.Count).ToArray(); - context.Packer = markings.Packer; - context.ExternalModules = markings.ExternalModules; - - context.CheckCancellation(); - - // 5. Initialize components - context.Logger.Info("Initializing..."); - foreach (ConfuserComponent comp in components) { - try { - comp.Initialize(context); - } - catch (Exception ex) { - context.Logger.ErrorException("Error occured during initialization of '" + comp.Name + "'.", ex); - throw new ConfuserException(ex); - } - context.CheckCancellation(); - } - - context.CheckCancellation(); - - // 6. Build pipeline - context.Logger.Debug("Building pipeline..."); - var pipeline = new ProtectionPipeline(); - context.Pipeline = pipeline; - foreach (ConfuserComponent comp in components) { - comp.PopulatePipeline(pipeline); - } - - context.CheckCancellation(); - - //7. Run pipeline - RunPipeline(pipeline, context); - - ok = true; - } - catch (AssemblyResolveException ex) { - context.Logger.ErrorException("Failed to resolve an assembly, check if all dependencies are present in the correct version.", ex); - PrintEnvironmentInfo(context); - } - catch (TypeResolveException ex) { - context.Logger.ErrorException("Failed to resolve a type, check if all dependencies are present in the correct version.", ex); - PrintEnvironmentInfo(context); - } - catch (MemberRefResolveException ex) { - context.Logger.ErrorException("Failed to resolve a member, check if all dependencies are present in the correct version.", ex); - PrintEnvironmentInfo(context); - } - catch (IOException ex) { - context.Logger.ErrorException("An IO error occurred, check if all input/output locations are readable/writable.", ex); - } - catch (OperationCanceledException) { - context.Logger.Error("Operation cancelled."); - } - catch (ConfuserException) { - // Exception is already handled/logged, so just ignore and report failure - } - catch (Exception ex) { - context.Logger.ErrorException("Unknown error occurred.", ex); - } - finally { - if (context.Resolver != null) - context.InternalResolver.Clear(); - context.Logger.Finish(ok); - } - } - - /// - /// Runs the protection pipeline. - /// - /// The protection pipeline. - /// The context. - static void RunPipeline(ProtectionPipeline pipeline, ConfuserContext context) { - Func> getAllDefs = () => context.Modules.SelectMany(module => module.FindDefinitions()).ToList(); - Func> getModuleDefs = module => module.FindDefinitions().ToList(); - - context.CurrentModuleIndex = -1; - - pipeline.ExecuteStage(PipelineStage.Inspection, Inspection, () => getAllDefs(), context); - - var options = new ModuleWriterOptionsBase[context.Modules.Count]; - for (int i = 0; i < context.Modules.Count; i++) { - context.CurrentModuleIndex = i; - context.CurrentModuleWriterOptions = null; - - pipeline.ExecuteStage(PipelineStage.BeginModule, BeginModule, () => getModuleDefs(context.CurrentModule), context); - pipeline.ExecuteStage(PipelineStage.ProcessModule, ProcessModule, () => getModuleDefs(context.CurrentModule), context); - pipeline.ExecuteStage(PipelineStage.OptimizeMethods, OptimizeMethods, () => getModuleDefs(context.CurrentModule), context); - pipeline.ExecuteStage(PipelineStage.EndModule, EndModule, () => getModuleDefs(context.CurrentModule), context); - - options[i] = context.CurrentModuleWriterOptions; - } - - for (int i = 0; i < context.Modules.Count; i++) { - context.CurrentModuleIndex = i; - context.CurrentModuleWriterOptions = options[i]; - - pipeline.ExecuteStage(PipelineStage.WriteModule, WriteModule, () => getModuleDefs(context.CurrentModule), context); - - context.OutputModules[i] = context.CurrentModuleOutput; - context.OutputSymbols[i] = context.CurrentModuleSymbol; - context.CurrentModuleWriterOptions = null; - context.CurrentModuleOutput = null; - context.CurrentModuleSymbol = null; - } - - context.CurrentModuleIndex = -1; - - pipeline.ExecuteStage(PipelineStage.Debug, Debug, () => getAllDefs(), context); - pipeline.ExecuteStage(PipelineStage.Pack, Pack, () => getAllDefs(), context); - pipeline.ExecuteStage(PipelineStage.SaveModules, SaveModules, () => getAllDefs(), context); - - if (!context.PackerInitiated) - context.Logger.Info("Done."); - } - - static void Inspection(ConfuserContext context) { - context.Logger.Info("Resolving dependencies..."); - foreach (var dependency in context.Modules - .SelectMany(module => module.GetAssemblyRefs().Select(asmRef => Tuple.Create(asmRef, module)))) { - try { - context.Resolver.ResolveThrow(dependency.Item1, dependency.Item2); - } - catch (AssemblyResolveException ex) { - context.Logger.ErrorException("Failed to resolve dependency of '" + dependency.Item2.Name + "'.", ex); - throw new ConfuserException(ex); - } - } - - context.Logger.Debug("Checking Strong Name..."); - foreach (var module in context.Modules) { - CheckStrongName(context, module); - } - - var marker = context.Registry.GetService(); - - context.Logger.Debug("Creating global .cctors..."); - foreach (ModuleDefMD module in context.Modules) { - TypeDef modType = module.GlobalType; - if (modType == null) { - modType = new TypeDefUser("", "", null); - modType.Attributes = TypeAttributes.AnsiClass; - module.Types.Add(modType); - marker.Mark(modType, null); - } - MethodDef cctor = modType.FindOrCreateStaticConstructor(); - if (!marker.IsMarked(cctor)) - marker.Mark(cctor, null); - } - } - - static void CheckStrongName(ConfuserContext context, ModuleDef module) { - var snKey = context.Annotations.Get(module, Marker.SNKey); - var snPubKeyBytes = context.Annotations.Get(module, Marker.SNPubKey)?.CreatePublicKey(); - var snDelaySign = context.Annotations.Get(module, Marker.SNDelaySig); - - if (snPubKeyBytes == null && snKey != null) - snPubKeyBytes = snKey.PublicKey; - - bool moduleIsSignedOrDelayedSigned = module.IsStrongNameSigned || !module.Assembly.PublicKey.IsNullOrEmpty; - - bool isKeyProvided = snKey != null || (snDelaySign && snPubKeyBytes != null); - - if (!isKeyProvided && moduleIsSignedOrDelayedSigned) - context.Logger.WarnFormat("[{0}] SN Key or SN public Key is not provided for a signed module, the output may not be working.", module.Name); - else if (isKeyProvided && !moduleIsSignedOrDelayedSigned) - context.Logger.WarnFormat("[{0}] SN Key or SN public Key is provided for an unsigned module, the output may not be working.", module.Name); - else if (snPubKeyBytes != null && moduleIsSignedOrDelayedSigned && - !module.Assembly.PublicKey.Data.SequenceEqual(snPubKeyBytes)) - context.Logger.WarnFormat("[{0}] Provided SN public Key and signed module's public key do not match, the output may not be working.", - module.Name); - } - - static void CopyPEHeaders(PEHeadersOptions writerOptions, ModuleDefMD module) { - var image = module.Metadata.PEImage; - writerOptions.MajorImageVersion = image.ImageNTHeaders.OptionalHeader.MajorImageVersion; - writerOptions.MajorLinkerVersion = image.ImageNTHeaders.OptionalHeader.MajorLinkerVersion; - writerOptions.MajorOperatingSystemVersion = image.ImageNTHeaders.OptionalHeader.MajorOperatingSystemVersion; - writerOptions.MajorSubsystemVersion = image.ImageNTHeaders.OptionalHeader.MajorSubsystemVersion; - writerOptions.MinorImageVersion = image.ImageNTHeaders.OptionalHeader.MinorImageVersion; - writerOptions.MinorLinkerVersion = image.ImageNTHeaders.OptionalHeader.MinorLinkerVersion; - writerOptions.MinorOperatingSystemVersion = image.ImageNTHeaders.OptionalHeader.MinorOperatingSystemVersion; - writerOptions.MinorSubsystemVersion = image.ImageNTHeaders.OptionalHeader.MinorSubsystemVersion; - } - - static void BeginModule(ConfuserContext context) { - context.Logger.InfoFormat("Processing module '{0}'...", context.CurrentModule.Name); - - context.CurrentModuleWriterOptions = new ModuleWriterOptions(context.CurrentModule); - CopyPEHeaders(context.CurrentModuleWriterOptions.PEHeadersOptions, context.CurrentModule); - - if (!context.CurrentModule.IsILOnly || context.CurrentModule.VTableFixups != null) - context.RequestNative(true); - +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Confuser.Core.Project; +using Confuser.Core.Services; +using dnlib.DotNet; +using dnlib.DotNet.Emit; +using dnlib.DotNet.Writer; +using Microsoft.Win32; +using InformationalAttribute = System.Reflection.AssemblyInformationalVersionAttribute; +using ProductAttribute = System.Reflection.AssemblyProductAttribute; +using CopyrightAttribute = System.Reflection.AssemblyCopyrightAttribute; +using MethodAttributes = dnlib.DotNet.MethodAttributes; +using MethodImplAttributes = dnlib.DotNet.MethodImplAttributes; +using TypeAttributes = dnlib.DotNet.TypeAttributes; + +namespace Confuser.Core { + /// + /// The processing engine of ConfuserEx. + /// + public static class ConfuserEngine { + /// + /// The version of ConfuserEx. + /// + public static readonly string Version; + + static readonly string Copyright; + + static ConfuserEngine() { + Assembly assembly = typeof(ConfuserEngine).Assembly; + var nameAttr = (ProductAttribute)assembly.GetCustomAttributes(typeof(ProductAttribute), false)[0]; + var verAttr = (InformationalAttribute)assembly.GetCustomAttributes(typeof(InformationalAttribute), false)[0]; + var cpAttr = (CopyrightAttribute)assembly.GetCustomAttributes(typeof(CopyrightAttribute), false)[0]; + Version = string.Format("{0} {1}", nameAttr.Product, verAttr.InformationalVersion); + Copyright = cpAttr.Copyright; + + AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => { + try { + var asmName = new AssemblyName(e.Name); + foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) + if (asm.GetName().Name == asmName.Name) + return asm; + return null; + } + catch { + return null; + } + }; + } + + /// + /// Runs the engine with the specified parameters. + /// + /// The parameters. + /// The token used for cancellation. + /// Task to run the engine. + /// + /// .Project is null. + /// + public static Task Run(ConfuserParameters parameters, CancellationToken? token = null) { + if (parameters.Project == null) + throw new ArgumentNullException("parameters"); + if (token == null) + token = new CancellationTokenSource().Token; + return Task.Factory.StartNew(() => RunInternal(parameters, token.Value), token.Value); + } + + /// + /// Runs the engine. + /// + /// The parameters. + /// The cancellation token. + static void RunInternal(ConfuserParameters parameters, CancellationToken token) { + // 1. Setup context + var context = new ConfuserContext(); + context.Logger = parameters.GetLogger(); + context.Project = parameters.Project.Clone(); + context.PackerInitiated = parameters.PackerInitiated; + context.token = token; + + PrintInfo(context); + + bool ok = false; + try { + // Enable watermarking by default + context.Project.Rules.Insert(0, new Rule { + new SettingItem(WatermarkingProtection._Id) + }); + + var asmResolver = new ConfuserAssemblyResolver {EnableTypeDefCache = true}; + asmResolver.DefaultModuleContext = new ModuleContext(asmResolver); + context.InternalResolver = asmResolver; + context.BaseDirectory = Path.Combine(Environment.CurrentDirectory, context.Project.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar); + context.OutputDirectory = Path.Combine(context.Project.BaseDirectory, context.Project.OutputDirectory.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar); + foreach (string probePath in context.Project.ProbePaths) + asmResolver.PostSearchPaths.Insert(0, Path.Combine(context.BaseDirectory, probePath)); + + context.CheckCancellation(); + + Marker marker = parameters.GetMarker(); + + // 2. Discover plugins + context.Logger.Debug("Discovering plugins..."); + + IList prots; + IList packers; + IList components; + parameters.GetPluginDiscovery().GetPlugins(context, out prots, out packers, out components); + + context.Logger.InfoFormat("Discovered {0} protections, {1} packers.", prots.Count, packers.Count); + + context.CheckCancellation(); + + // 3. Resolve dependency + context.Logger.Debug("Resolving component dependency..."); + try { + var resolver = new DependencyResolver(prots); + prots = resolver.SortDependency(); + } + catch (CircularDependencyException ex) { + context.Logger.ErrorException("", ex); + throw new ConfuserException(ex); + } + + components.Insert(0, new CoreComponent(context, marker)); + foreach (Protection prot in prots) + components.Add(prot); + foreach (Packer packer in packers) + components.Add(packer); + + context.CheckCancellation(); + + // 4. Load modules + context.Logger.Info("Loading input modules..."); + marker.Initalize(prots, packers); + MarkerResult markings = marker.MarkProject(context.Project, context); + context.Modules = new ModuleSorter(markings.Modules).Sort().ToList().AsReadOnly(); + foreach (var module in context.Modules) + module.EnableTypeDefFindCache = false; + context.OutputModules = Enumerable.Repeat(null, context.Modules.Count).ToArray(); + context.OutputSymbols = Enumerable.Repeat(null, context.Modules.Count).ToArray(); + context.OutputPaths = Enumerable.Repeat(null, context.Modules.Count).ToArray(); + context.Packer = markings.Packer; + context.ExternalModules = markings.ExternalModules; + + context.CheckCancellation(); + + // 5. Initialize components + context.Logger.Info("Initializing..."); + foreach (ConfuserComponent comp in components) { + try { + comp.Initialize(context); + } + catch (Exception ex) { + context.Logger.ErrorException("Error occured during initialization of '" + comp.Name + "'.", ex); + throw new ConfuserException(ex); + } + context.CheckCancellation(); + } + + context.CheckCancellation(); + + // 6. Build pipeline + context.Logger.Debug("Building pipeline..."); + var pipeline = new ProtectionPipeline(); + context.Pipeline = pipeline; + foreach (ConfuserComponent comp in components) { + comp.PopulatePipeline(pipeline); + } + + context.CheckCancellation(); + + //7. Run pipeline + RunPipeline(pipeline, context); + + ok = true; + } + catch (AssemblyResolveException ex) { + context.Logger.ErrorException("Failed to resolve an assembly, check if all dependencies are present in the correct version.", ex); + PrintEnvironmentInfo(context); + } + catch (TypeResolveException ex) { + context.Logger.ErrorException("Failed to resolve a type, check if all dependencies are present in the correct version.", ex); + PrintEnvironmentInfo(context); + } + catch (MemberRefResolveException ex) { + context.Logger.ErrorException("Failed to resolve a member, check if all dependencies are present in the correct version.", ex); + PrintEnvironmentInfo(context); + } + catch (IOException ex) { + context.Logger.ErrorException("An IO error occurred, check if all input/output locations are readable/writable.", ex); + } + catch (OperationCanceledException) { + context.Logger.Error("Operation cancelled."); + } + catch (ConfuserException) { + // Exception is already handled/logged, so just ignore and report failure + } + catch (Exception ex) { + context.Logger.ErrorException("Unknown error occurred.", ex); + } + finally { + if (context.Resolver != null) + context.InternalResolver.Clear(); + context.Logger.Finish(ok); + } + } + + /// + /// Runs the protection pipeline. + /// + /// The protection pipeline. + /// The context. + static void RunPipeline(ProtectionPipeline pipeline, ConfuserContext context) { + Func> getAllDefs = () => context.Modules.SelectMany(module => module.FindDefinitions()).ToList(); + Func> getModuleDefs = module => module.FindDefinitions().ToList(); + + context.CurrentModuleIndex = -1; + + pipeline.ExecuteStage(PipelineStage.Inspection, Inspection, () => getAllDefs(), context); + + var options = new ModuleWriterOptionsBase[context.Modules.Count]; + for (int i = 0; i < context.Modules.Count; i++) { + context.CurrentModuleIndex = i; + context.CurrentModuleWriterOptions = null; + + pipeline.ExecuteStage(PipelineStage.BeginModule, BeginModule, () => getModuleDefs(context.CurrentModule), context); + pipeline.ExecuteStage(PipelineStage.ProcessModule, ProcessModule, () => getModuleDefs(context.CurrentModule), context); + pipeline.ExecuteStage(PipelineStage.OptimizeMethods, OptimizeMethods, () => getModuleDefs(context.CurrentModule), context); + pipeline.ExecuteStage(PipelineStage.EndModule, EndModule, () => getModuleDefs(context.CurrentModule), context); + + options[i] = context.CurrentModuleWriterOptions; + } + + for (int i = 0; i < context.Modules.Count; i++) { + context.CurrentModuleIndex = i; + context.CurrentModuleWriterOptions = options[i]; + + pipeline.ExecuteStage(PipelineStage.WriteModule, WriteModule, () => getModuleDefs(context.CurrentModule), context); + + context.OutputModules[i] = context.CurrentModuleOutput; + context.OutputSymbols[i] = context.CurrentModuleSymbol; + context.CurrentModuleWriterOptions = null; + context.CurrentModuleOutput = null; + context.CurrentModuleSymbol = null; + } + + context.CurrentModuleIndex = -1; + + pipeline.ExecuteStage(PipelineStage.Debug, Debug, () => getAllDefs(), context); + pipeline.ExecuteStage(PipelineStage.Pack, Pack, () => getAllDefs(), context); + pipeline.ExecuteStage(PipelineStage.SaveModules, SaveModules, () => getAllDefs(), context); + + if (!context.PackerInitiated) + context.Logger.Info("Done."); + } + + static void Inspection(ConfuserContext context) { + context.Logger.Info("Resolving dependencies..."); + foreach (var dependency in context.Modules + .SelectMany(module => module.GetAssemblyRefs().Select(asmRef => Tuple.Create(asmRef, module)))) { + try { + context.Resolver.ResolveThrow(dependency.Item1, dependency.Item2); + } + catch (AssemblyResolveException ex) { + context.Logger.ErrorException("Failed to resolve dependency of '" + dependency.Item2.Name + "'.", ex); + throw new ConfuserException(ex); + } + } + + context.Logger.Debug("Checking Strong Name..."); + foreach (var module in context.Modules) { + CheckStrongName(context, module); + } + + var marker = context.Registry.GetService(); + + context.Logger.Debug("Creating global .cctors..."); + foreach (ModuleDefMD module in context.Modules) { + TypeDef modType = module.GlobalType; + if (modType == null) { + modType = new TypeDefUser("", "", null); + modType.Attributes = TypeAttributes.AnsiClass; + module.Types.Add(modType); + marker.Mark(modType, null); + } + MethodDef cctor = modType.FindOrCreateStaticConstructor(); + if (!marker.IsMarked(cctor)) + marker.Mark(cctor, null); + } + } + + static void CheckStrongName(ConfuserContext context, ModuleDef module) { + var snKey = context.Annotations.Get(module, Marker.SNKey); + var snPubKeyBytes = context.Annotations.Get(module, Marker.SNPubKey)?.CreatePublicKey(); + var snDelaySign = context.Annotations.Get(module, Marker.SNDelaySig); + + if (snPubKeyBytes == null && snKey != null) + snPubKeyBytes = snKey.PublicKey; + + bool moduleIsSignedOrDelayedSigned = module.IsStrongNameSigned || !module.Assembly.PublicKey.IsNullOrEmpty; + + bool isKeyProvided = snKey != null || (snDelaySign && snPubKeyBytes != null); + + if (!isKeyProvided && moduleIsSignedOrDelayedSigned) + context.Logger.WarnFormat("[{0}] SN Key or SN public Key is not provided for a signed module, the output may not be working.", module.Name); + else if (isKeyProvided && !moduleIsSignedOrDelayedSigned) + context.Logger.WarnFormat("[{0}] SN Key or SN public Key is provided for an unsigned module, the output may not be working.", module.Name); + else if (snPubKeyBytes != null && moduleIsSignedOrDelayedSigned && + !module.Assembly.PublicKey.Data.SequenceEqual(snPubKeyBytes)) + context.Logger.WarnFormat("[{0}] Provided SN public Key and signed module's public key do not match, the output may not be working.", + module.Name); + } + + static void CopyPEHeaders(PEHeadersOptions writerOptions, ModuleDefMD module) { + var image = module.Metadata.PEImage; + writerOptions.MajorImageVersion = image.ImageNTHeaders.OptionalHeader.MajorImageVersion; + writerOptions.MajorLinkerVersion = image.ImageNTHeaders.OptionalHeader.MajorLinkerVersion; + writerOptions.MajorOperatingSystemVersion = image.ImageNTHeaders.OptionalHeader.MajorOperatingSystemVersion; + writerOptions.MajorSubsystemVersion = image.ImageNTHeaders.OptionalHeader.MajorSubsystemVersion; + writerOptions.MinorImageVersion = image.ImageNTHeaders.OptionalHeader.MinorImageVersion; + writerOptions.MinorLinkerVersion = image.ImageNTHeaders.OptionalHeader.MinorLinkerVersion; + writerOptions.MinorOperatingSystemVersion = image.ImageNTHeaders.OptionalHeader.MinorOperatingSystemVersion; + writerOptions.MinorSubsystemVersion = image.ImageNTHeaders.OptionalHeader.MinorSubsystemVersion; + } + + static void BeginModule(ConfuserContext context) { + context.Logger.InfoFormat("Processing module '{0}'...", context.CurrentModule.Name); + + context.CurrentModuleWriterOptions = new ModuleWriterOptions(context.CurrentModule); + CopyPEHeaders(context.CurrentModuleWriterOptions.PEHeadersOptions, context.CurrentModule); + + if (!context.CurrentModule.IsILOnly || context.CurrentModule.VTableFixups != null) + context.RequestNative(true); + var snKey = context.Annotations.Get(context.CurrentModule, Marker.SNKey); var snPubKey = context.Annotations.Get(context.CurrentModule, Marker.SNPubKey); var snSigKey = context.Annotations.Get(context.CurrentModule, Marker.SNSigKey); - var snSigPubKey = context.Annotations.Get(context.CurrentModule, Marker.SNSigPubKey); - + var snSigPubKey = context.Annotations.Get(context.CurrentModule, Marker.SNSigPubKey); + var snDelaySig = context.Annotations.Get(context.CurrentModule, Marker.SNDelaySig, false); - context.CurrentModuleWriterOptions.DelaySign = snDelaySig; - - if (snKey != null && snPubKey != null && snSigKey != null && snSigPubKey != null) - context.CurrentModuleWriterOptions.InitializeEnhancedStrongNameSigning(context.CurrentModule, snSigKey, snSigPubKey, snKey, snPubKey); + context.CurrentModuleWriterOptions.DelaySign = snDelaySig; + + if (snKey != null && snPubKey != null && snSigKey != null && snSigPubKey != null) + context.CurrentModuleWriterOptions.InitializeEnhancedStrongNameSigning(context.CurrentModule, snSigKey, snSigPubKey, snKey, snPubKey); else if (snSigPubKey != null && snSigKey != null) context.CurrentModuleWriterOptions.InitializeEnhancedStrongNameSigning(context.CurrentModule, snSigKey, snSigPubKey); else - context.CurrentModuleWriterOptions.InitializeStrongNameSigning(context.CurrentModule, snKey); - + context.CurrentModuleWriterOptions.InitializeStrongNameSigning(context.CurrentModule, snKey); + if (snDelaySig) { - context.CurrentModuleWriterOptions.StrongNamePublicKey = snPubKey; - context.CurrentModuleWriterOptions.StrongNameKey = null; - } - - foreach (TypeDef type in context.CurrentModule.GetTypes()) - foreach (MethodDef method in type.Methods) { - if (method.Body != null) { - method.Body.Instructions.SimplifyMacros(method.Body.Variables, method.Parameters); - } - } - } - - static void ProcessModule(ConfuserContext context) => - context.CurrentModuleWriterOptions.WriterEvent += (sender, e) => context.CheckCancellation(); - - static void OptimizeMethods(ConfuserContext context) { - foreach (TypeDef type in context.CurrentModule.GetTypes()) - foreach (MethodDef method in type.Methods) { - if (method.Body != null) - method.Body.Instructions.OptimizeMacros(); - } - } - - static void EndModule(ConfuserContext context) { - string output = context.Modules[context.CurrentModuleIndex].Location; - if (!(output is null)) { - if (!Path.IsPathRooted(output)) - output = Path.Combine(context.BaseDirectory, output); - string relativeOutput = Utils.GetRelativePath(output, context.BaseDirectory); + context.CurrentModuleWriterOptions.StrongNamePublicKey = snPubKey; + context.CurrentModuleWriterOptions.StrongNameKey = null; + } + + foreach (TypeDef type in context.CurrentModule.GetTypes()) + foreach (MethodDef method in type.Methods) { + if (method.Body != null) { + method.Body.Instructions.SimplifyMacros(method.Body.Variables, method.Parameters); + } + } + } + + static void ProcessModule(ConfuserContext context) => + context.CurrentModuleWriterOptions.WriterEvent += (sender, e) => context.CheckCancellation(); + + static void OptimizeMethods(ConfuserContext context) { + foreach (TypeDef type in context.CurrentModule.GetTypes()) + foreach (MethodDef method in type.Methods) { + if (method.Body != null) + method.Body.Instructions.OptimizeMacros(); + } + } + + static void EndModule(ConfuserContext context) { + string output = context.Modules[context.CurrentModuleIndex].Location; + if (!(output is null)) { + if (!Path.IsPathRooted(output)) + output = Path.Combine(context.BaseDirectory, output); + string relativeOutput = Utils.GetRelativePath(output, context.BaseDirectory); if (relativeOutput is null) { context.Logger.WarnFormat("Input file is not inside the base directory. Relative path can't be created. Placing file into output root." + Environment.NewLine + "Responsible file is: {0}", output); output = Path.GetFileName(output); } else { output = relativeOutput; - } - } - else { - output = context.CurrentModule.Name; - } - context.OutputPaths[context.CurrentModuleIndex] = output; - } - - static void WriteModule(ConfuserContext context) { - context.Logger.InfoFormat("Writing module '{0}'...", context.CurrentModule.Name); - - MemoryStream pdb = null, output = new MemoryStream(); - - if (context.CurrentModule.PdbState != null) { - pdb = new MemoryStream(); - context.CurrentModuleWriterOptions.WritePdb = true; - context.CurrentModuleWriterOptions.PdbFileName = Path.ChangeExtension(Path.GetFileName(context.OutputPaths[context.CurrentModuleIndex]), "pdb"); - context.CurrentModuleWriterOptions.PdbStream = pdb; - } - - if (context.CurrentModuleWriterOptions is ModuleWriterOptions) - context.CurrentModule.Write(output, (ModuleWriterOptions)context.CurrentModuleWriterOptions); - else - context.CurrentModule.NativeWrite(output, (NativeModuleWriterOptions)context.CurrentModuleWriterOptions); - - context.CurrentModuleOutput = output.ToArray(); - if (context.CurrentModule.PdbState != null) - context.CurrentModuleSymbol = pdb.ToArray(); - } - - static void Debug(ConfuserContext context) { - context.Logger.Info("Finalizing..."); - for (int i = 0; i < context.OutputModules.Count; i++) { - if (context.OutputSymbols[i] == null) - continue; - string path = Path.GetFullPath(Path.Combine(context.OutputDirectory, context.OutputPaths[i])); - string dir = Path.GetDirectoryName(path); - if (!Directory.Exists(dir)) - Directory.CreateDirectory(dir); - File.WriteAllBytes(Path.ChangeExtension(path, "pdb"), context.OutputSymbols[i]); - } - } - - static void Pack(ConfuserContext context) { - if (context.Packer != null) { - context.Logger.Info("Packing..."); - context.Packer.Pack(context, new ProtectionParameters(context.Packer, context.Modules.OfType().ToList())); - } - } - - static void SaveModules(ConfuserContext context) { - context.InternalResolver.Clear(); - for (int i = 0; i < context.OutputModules.Count; i++) { - string path = Path.GetFullPath(Path.Combine(context.OutputDirectory, context.OutputPaths[i])); - string dir = Path.GetDirectoryName(path); - if (!Directory.Exists(dir)) - Directory.CreateDirectory(dir); - context.Logger.DebugFormat("Saving to '{0}'...", path); - File.WriteAllBytes(path, context.OutputModules[i]); - } - } - - /// - /// Prints the copyright stuff and environment information. - /// - /// The working context. - static void PrintInfo(ConfuserContext context) { - if (context.PackerInitiated) { - context.Logger.Info("Protecting packer stub..."); - } - else { - context.Logger.InfoFormat("{0} {1}", Version, Copyright); - - Type mono = Type.GetType("Mono.Runtime"); - context.Logger.InfoFormat("Running on {0}, {1}, {2} bits", - Environment.OSVersion, - mono == null ? - ".NET Framework v" + Environment.Version : - mono.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null), - IntPtr.Size * 8); - } - } - - static IEnumerable GetFrameworkVersions() { - // http://msdn.microsoft.com/en-us/library/hh925568.aspx - - using (RegistryKey ndpKey = - RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ""). - OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\")) { - foreach (string versionKeyName in ndpKey.GetSubKeyNames()) { - if (!versionKeyName.StartsWith("v")) - continue; - - RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName); - var name = (string)versionKey.GetValue("Version", ""); - string sp = versionKey.GetValue("SP", "").ToString(); - string install = versionKey.GetValue("Install", "").ToString(); - if (install == "" || sp != "" && install == "1") - yield return versionKeyName + " " + name; - - if (name != "") - continue; - - foreach (string subKeyName in versionKey.GetSubKeyNames()) { - RegistryKey subKey = versionKey.OpenSubKey(subKeyName); - name = (string)subKey.GetValue("Version", ""); - if (name != "") - sp = subKey.GetValue("SP", "").ToString(); - install = subKey.GetValue("Install", "").ToString(); - - if (install == "") - yield return versionKeyName + " " + name; - else if (install == "1") - yield return " " + subKeyName + " " + name; - } - } - } - - using (RegistryKey ndpKey = - RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ""). - OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\")) { - if (ndpKey.GetValue("Release") == null) - yield break; - var releaseKey = (int)ndpKey.GetValue("Release"); - yield return "v4.5 " + releaseKey; - } - } - - /// - /// Prints the environment information when error occurred. - /// - /// The working context. - static void PrintEnvironmentInfo(ConfuserContext context) { - if (context.PackerInitiated) - return; - - context.Logger.Error("---BEGIN DEBUG INFO---"); - - context.Logger.Error("Installed Framework Versions:"); - foreach (string ver in GetFrameworkVersions()) { - context.Logger.ErrorFormat(" {0}", ver.Trim()); - } - context.Logger.Error(""); - - if (context.Resolver != null) { - context.Logger.Error("Cached assemblies:"); - foreach (AssemblyDef asm in context.InternalResolver.GetCachedAssemblies()) { - if (string.IsNullOrEmpty(asm.ManifestModule.Location)) - context.Logger.ErrorFormat(" {0}", asm.FullName); - else - context.Logger.ErrorFormat(" {0} ({1})", asm.FullName, asm.ManifestModule.Location); - foreach (var reference in asm.Modules.OfType().SelectMany(m => m.GetAssemblyRefs())) - context.Logger.ErrorFormat(" {0}", reference.FullName); - } - } - - context.Logger.Error("---END DEBUG INFO---"); - } - } -} + } + } + else { + output = context.CurrentModule.Name; + } + context.OutputPaths[context.CurrentModuleIndex] = output; + } + + static void WriteModule(ConfuserContext context) { + context.Logger.InfoFormat("Writing module '{0}'...", context.CurrentModule.Name); + + MemoryStream pdb = null, output = new MemoryStream(); + + if (context.CurrentModule.PdbState != null) { + pdb = new MemoryStream(); + context.CurrentModuleWriterOptions.WritePdb = true; + context.CurrentModuleWriterOptions.PdbFileName = Path.ChangeExtension(Path.GetFileName(context.OutputPaths[context.CurrentModuleIndex]), "pdb"); + context.CurrentModuleWriterOptions.PdbStream = pdb; + } + + if (context.CurrentModuleWriterOptions is ModuleWriterOptions) + context.CurrentModule.Write(output, (ModuleWriterOptions)context.CurrentModuleWriterOptions); + else + context.CurrentModule.NativeWrite(output, (NativeModuleWriterOptions)context.CurrentModuleWriterOptions); + + context.CurrentModuleOutput = output.ToArray(); + if (context.CurrentModule.PdbState != null) + context.CurrentModuleSymbol = pdb.ToArray(); + } + + static void Debug(ConfuserContext context) { + context.Logger.Info("Finalizing..."); + if(!context.Project.Debug) + return; + for (int i = 0; i < context.OutputModules.Count; i++) { + if (context.OutputSymbols[i] == null) + continue; + string path = Path.GetFullPath(Path.Combine(context.OutputDirectory, context.OutputPaths[i])); + string dir = Path.GetDirectoryName(path); + if (!Directory.Exists(dir)) + Directory.CreateDirectory(dir); + File.WriteAllBytes(Path.ChangeExtension(path, "pdb"), context.OutputSymbols[i]); + } + } + + static void Pack(ConfuserContext context) { + if (context.Packer != null) { + context.Logger.Info("Packing..."); + context.Packer.Pack(context, new ProtectionParameters(context.Packer, context.Modules.OfType().ToList())); + } + } + + static void SaveModules(ConfuserContext context) { + context.InternalResolver.Clear(); + for (int i = 0; i < context.OutputModules.Count; i++) { + string path = Path.GetFullPath(Path.Combine(context.OutputDirectory, context.OutputPaths[i])); + string dir = Path.GetDirectoryName(path); + if (!Directory.Exists(dir)) + Directory.CreateDirectory(dir); + context.Logger.DebugFormat("Saving to '{0}'...", path); + File.WriteAllBytes(path, context.OutputModules[i]); + } + } + + /// + /// Prints the copyright stuff and environment information. + /// + /// The working context. + static void PrintInfo(ConfuserContext context) { + if (context.PackerInitiated) { + context.Logger.Info("Protecting packer stub..."); + } + else { + context.Logger.InfoFormat("{0} {1}", Version, Copyright); + + Type mono = Type.GetType("Mono.Runtime"); + context.Logger.InfoFormat("Running on {0}, {1}, {2} bits", + Environment.OSVersion, + mono == null ? + ".NET Framework v" + Environment.Version : + mono.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null), + IntPtr.Size * 8); + } + } + + static IEnumerable GetFrameworkVersions() { + // http://msdn.microsoft.com/en-us/library/hh925568.aspx + + using (RegistryKey ndpKey = + RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ""). + OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\")) { + foreach (string versionKeyName in ndpKey.GetSubKeyNames()) { + if (!versionKeyName.StartsWith("v")) + continue; + + RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName); + var name = (string)versionKey.GetValue("Version", ""); + string sp = versionKey.GetValue("SP", "").ToString(); + string install = versionKey.GetValue("Install", "").ToString(); + if (install == "" || sp != "" && install == "1") + yield return versionKeyName + " " + name; + + if (name != "") + continue; + + foreach (string subKeyName in versionKey.GetSubKeyNames()) { + RegistryKey subKey = versionKey.OpenSubKey(subKeyName); + name = (string)subKey.GetValue("Version", ""); + if (name != "") + sp = subKey.GetValue("SP", "").ToString(); + install = subKey.GetValue("Install", "").ToString(); + + if (install == "") + yield return versionKeyName + " " + name; + else if (install == "1") + yield return " " + subKeyName + " " + name; + } + } + } + + using (RegistryKey ndpKey = + RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ""). + OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\")) { + if (ndpKey.GetValue("Release") == null) + yield break; + var releaseKey = (int)ndpKey.GetValue("Release"); + yield return "v4.5 " + releaseKey; + } + } + + /// + /// Prints the environment information when error occurred. + /// + /// The working context. + static void PrintEnvironmentInfo(ConfuserContext context) { + if (context.PackerInitiated) + return; + + context.Logger.Error("---BEGIN DEBUG INFO---"); + + context.Logger.Error("Installed Framework Versions:"); + foreach (string ver in GetFrameworkVersions()) { + context.Logger.ErrorFormat(" {0}", ver.Trim()); + } + context.Logger.Error(""); + + if (context.Resolver != null) { + context.Logger.Error("Cached assemblies:"); + foreach (AssemblyDef asm in context.InternalResolver.GetCachedAssemblies()) { + if (string.IsNullOrEmpty(asm.ManifestModule.Location)) + context.Logger.ErrorFormat(" {0}", asm.FullName); + else + context.Logger.ErrorFormat(" {0} ({1})", asm.FullName, asm.ManifestModule.Location); + foreach (var reference in asm.Modules.OfType().SelectMany(m => m.GetAssemblyRefs())) + context.Logger.ErrorFormat(" {0}", reference.FullName); + } + } + + context.Logger.Error("---END DEBUG INFO---"); + } + } +}