internal ITypeReference Map(ITypeReference typeReference) { var result = new MetadataDeepCopier(host).Copy(typeReference); var rewriter = new ActualMutator(host, targetUnit, sourceUnitIdentity); return(rewriter.Rewrite(result)); }
static void Main(string[] argv) { if (argv == null || argv.Length < 1) { Console.WriteLine("Usage: Main <assemblys> [<outputPath>]"); } using (var host = new PeReader.DefaultHost()) { var module = host.LoadUnitFrom(argv[0]) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new Exception(argv[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); } PdbReader pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { Console.WriteLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { var copy = new MetadataDeepCopier(host).Copy(module); var shadowFieldsAddedAssembly = new ShadowFieldRewriter(host).Rewrite(copy); var shadowFieldsAndMethodsAddedAssembly = new ShadowMethodRewriter(host).Rewrite(shadowFieldsAddedAssembly); var rewrittenAssembly = new FinalizeMethodRewriter(host).Rewrite(shadowFieldsAndMethodsAddedAssembly); var main = rewrittenAssembly.EntryPoint.ResolvedMethod; if (main != Dummy.Method) { var body = main.Body as MethodBody; if (body != null) { new AddGCWaitForFinalization(host, body).Rewrite(); } } var validator = new MetadataValidator(host); validator.Validate(rewrittenAssembly as IAssembly); string outputPath = rewrittenAssembly.Location + ".meta"; var outputFileName = Path.GetFileNameWithoutExtension(outputPath); // Need to not pass in a local scope provider until such time as we have one that will use the mutator // to remap things (like the type of a scope constant) from the original assembly to the mutated one. using (var peStream = File.Create(outputPath)) { using (var pdbWriter = new PdbWriter(outputFileName + ".pdb", pdbReader)) { PeWriter.WritePeToStream(rewrittenAssembly, host, peStream, pdbReader, null, pdbWriter); } } } } }
IAssembly VisitAndMutate(MetadataRewriter mutator, IAssembly assembly) { var mutableAssembly = new MetadataDeepCopier(host).Copy(assembly); assembly = mutator.Rewrite(mutableAssembly); Assert.NotNull(assembly); return(assembly); }
static int Main(string[] args) { /* if (args == null || args.Length < 1) { Console.WriteLine("Usage: ILMutator <assembly> [<outputPath>]"); return 1; } */ String inputFile = @"c:\Users\typ\Documents\Visual Studio 2013\Projects\vererbung\vererbung\bin\Debug\vererbung.exe"; using (var host = new PeReader.DefaultHost()) { //IModule/*?*/ module = host.LoadUnitFrom(args[0]) as IModule; IModule/*?*/ module = host.LoadUnitFrom(inputFile) as IModule; if (module == null || module is Dummy) { Console.WriteLine(args[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); return 1; } module = new MetadataDeepCopier(host).Copy(module); PdbReader/*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { Console.WriteLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { var localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader); module = RewriteStoreLocal.RewriteModule(host, localScopeProvider, pdbReader, module); string newName; if (args.Length == 2) { //newName = args[1]; newName = @"e:\mutated.exe"; } else { var loc = module.Location; var path = Path.GetDirectoryName(loc)??""; var fileName = Path.GetFileNameWithoutExtension(loc); var ext = Path.GetExtension(loc); newName = Path.Combine(path, fileName + "1" + ext); newName = @"e:\mutated.exe"; } using (var peStream = File.Create(newName)) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(newName, ".pdb"), pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } return 0; // success } }
static int Main(string[] args) { if (args == null || args.Length < 1) { Console.WriteLine("Usage: ILMutator <assembly> [<outputPath>]"); return(1); } using (var host = new PeReader.DefaultHost()) { IModule /*?*/ module = host.LoadUnitFrom(args[0]) as IModule; if (module == null || module is Dummy) { Console.WriteLine(args[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); return(1); } module = new MetadataDeepCopier(host).Copy(module); PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { Console.WriteLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { var localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader); ILMutator mutator = new ILMutator(host, pdbReader); module = mutator.Rewrite(module); string newName; if (args.Length == 2) { newName = args[1]; } else { var loc = module.Location; var path = Path.GetDirectoryName(loc) ?? ""; var fileName = Path.GetFileNameWithoutExtension(loc); var ext = Path.GetExtension(loc); newName = Path.Combine(path, fileName + "1" + ext); } using (var peStream = File.Create(newName)) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(newName, ".pdb"), pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } return(0); // success } }
internal static IModule GetInstrumented(IMetadataHost host, IModule module, PdbReader/*?*/ pdbReader, INamespaceTypeDefinition logger) { var copier = new MetadataDeepCopier(host); var copy = copier.Copy(module); var loggerCopy = copier.Copy(logger); loggerCopy.ContainingUnitNamespace = copy.UnitNamespaceRoot; var logEdgeCount = TypeHelper.GetMethod(loggerCopy, host.NameTable.GetNameFor("LogEdgeCount"), host.PlatformType.SystemUInt32); new Instrumenter(host, pdbReader, logEdgeCount).Rewrite(copy); copy.AllTypes.Add(loggerCopy); return copy; }
internal static IModule GetInstrumented(IMetadataHost host, IModule module, PdbReader /*?*/ pdbReader, INamespaceTypeDefinition logger) { var copier = new MetadataDeepCopier(host); var copy = copier.Copy(module); var loggerCopy = copier.Copy(logger); loggerCopy.ContainingUnitNamespace = copy.UnitNamespaceRoot; var logEdgeCount = TypeHelper.GetMethod(loggerCopy, host.NameTable.GetNameFor("LogEdgeCount"), host.PlatformType.SystemUInt32); new Instrumenter(host, pdbReader, logEdgeCount).Rewrite(copy); copy.AllTypes.Add(loggerCopy); return(copy); }
static void Main(string[] args) { if (args == null || args.Length == 0) { Console.WriteLine("usage: PeToPe [path]fileName.ext"); return; } using (var host = new PeReader.DefaultHost()) { var module = host.LoadUnitFrom(args[0]) as IModule; if (module == null || module is Dummy) { Console.WriteLine(args[0]+" is not a PE file containing a CLR module or assembly."); return; } PdbReader/*?*/ pdbReader = null; string pdbFile = module.DebugInformationLocation; if (string.IsNullOrEmpty(pdbFile)) pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { Stream pdbStream = File.OpenRead(pdbFile); pdbReader = new PdbReader(pdbStream, host); } using (pdbReader) { //Make a mutable copy of the module. var copier = new MetadataDeepCopier(host); var mutableModule = copier.Copy(module); //Traverse the module. In a real application the MetadataVisitor and/or the MetadataTravers will be subclasses //and the traversal will gather information to use during rewriting. var traverser = new MetadataTraverser() { PreorderVisitor = new MetadataVisitor(), TraverseIntoMethodBodies = true }; traverser.Traverse(mutableModule); //Rewrite the mutable copy. In a real application the rewriter would be a subclass of MetadataRewriter that actually does something. var rewriter = new MetadataRewriter(host); var rewrittenModule = rewriter.Rewrite(mutableModule); //Write out rewritten module. using (var peStream = File.Create(rewrittenModule.Location + ".pe")) { if (pdbReader == null) { PeWriter.WritePeToStream(rewrittenModule, host, peStream); } else { //Note that the default copier and rewriter preserves the locations collections, so the original pdbReader is still a valid ISourceLocationProvider. //However, if IL instructions were rewritten, the pdbReader will no longer be an accurate ILocalScopeProvider using (var pdbWriter = new PdbWriter(pdbFile + ".pdb", pdbReader)) { PeWriter.WritePeToStream(rewrittenModule, host, peStream, pdbReader, pdbReader, pdbWriter); } } } } } }
void RoundTripMutableCopyAndAddGenericParameter2(string assemblyName) { PeVerifyResult expectedResult = PeVerify.VerifyAssembly(assemblyName); IAssembly assembly = LoadAssembly(assemblyName); var copier1 = new MetadataDeepCopier(host); var codeAssembly = copier1.Copy(assembly); for (int i = 0; i < 30; i++) { AddGenericParameters adder = new AddGenericParameters(host, codeAssembly.AllTypes, i); codeAssembly = (Assembly)adder.Rewrite(codeAssembly); } AssertWriteToPeFile(expectedResult, codeAssembly, null); }
/// <summary> /// Returns a mutable Code Model module that is equivalent to the given Metadata Model module, /// except that in the new module method bodies also implement ISourceMethodBody. /// </summary> /// <param name="host">An object representing the application that is hosting this decompiler. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references.</param> /// <param name="module">The root of the Metadata Model to be converted to a Code Model.</param> /// <param name="sourceLocationProvider">An object that can map some kinds of ILocation objects to IPrimarySourceLocation objects. May be null.</param> /// <param name="localScopeProvider">An object that can provide information about the local scopes of a method. May be null.</param> /// <param name="options">Set of options that control decompilation.</param> private static Module GetCodeModelFromMetadataModelHelper(IMetadataHost host, IModule module, ISourceLocationProvider /*?*/ sourceLocationProvider, ILocalScopeProvider /*?*/ localScopeProvider, DecompilerOptions options) { var result = new MetadataDeepCopier(host).Copy(module); var replacer = new ReplaceMetadataMethodBodiesWithDecompiledMethodBodies(host, module, sourceLocationProvider, localScopeProvider, options); replacer.Traverse(result); var finder = new HelperTypeFinder(host, sourceLocationProvider); finder.Traverse(result); var remover = new RemoveUnnecessaryTypes(finder.helperTypes, finder.helperMethods, finder.helperFields); remover.Traverse(result); result.AllTypes.RemoveAll(td => finder.helperTypes.ContainsKey(td.InternedKey)); // depends on RemoveAll preserving order return(result); }
public override void RewriteChildren(NamedTypeDefinition typeDefinition) { if (typeDefinition.Properties == null) { return; } var props = typeDefinition.Properties .Select(x => new { Property = x, Attributes = x.Attributes //.Select(y => (NamespaceTypeDefinition)y.Type) .Select(y => y.Type as NamespaceTypeDefinition) .Where(y => y != null && y.Name.Value == "PropertyChangedAttribute") }) .Where(x => x.Attributes.Any()); if (!props.Any()) { return; } foreach (var p in props.ToArray()) { if (p.Property.Setter == null) { throw new InvalidOperationException(); } var copier = new MetadataDeepCopier(host); var p2 = copier.Copy(p.Property); typeDefinition.Properties.Remove(p.Property); typeDefinition.Properties.Add(p2); var method = copier.Copy(p2.Setter.ResolvedMethod); _rewriter.PropertyName = p2.Name.Value; _rewriter.Type = method.ContainingTypeDefinition; method.Body = _rewriter.Rewrite(method.Body); method.ContainingTypeDefinition = typeDefinition; var m = typeDefinition.Methods.FirstOrDefault(x => x.Name == p2.Setter.ResolvedMethod.Name); typeDefinition.Methods.Remove(m); typeDefinition.Methods.Add(method); } }
private IAssembly LoadAssemblyFrom(string filePath) { IAssembly module = _host.LoadUnitFrom(filePath) as IAssembly; _host.RegisterAsLatest(module); if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new AssemblyReadException(filePath + " is not a PE file containing a CLR module or assembly."); } PdbReader pdbReader; TryGetPdbReader(module, out pdbReader); module = new MetadataDeepCopier(_host).Copy(module); // var decompiled = Decompiler.GetCodeModelFromMetadataModel(_host, module, pdbReader, // DecompilerOptions.None); return(module); // return new CodeDeepCopier(_host, pdbReader).Copy(decompiled); }
public static void Main(string[] args) { if (args.Length != 2) { Console.WriteLine("Usage: PInvokeCompiler Input.dll Output.dll"); return; } var inputFile = args[0]; var outputFile = args[1]; using (var host = new PeReader.DefaultHost()) { var unit = host.LoadUnitFrom(inputFile); var assembly = unit as IAssembly; if (assembly == null) { Console.WriteLine("Error: Input file not loadable as assembly"); return; } Assembly mutable = new MetadataDeepCopier(host).Copy(assembly); var interopHelperReference = new InteropHelperReferences(host, mutable); var pinvokeMethodMetadataTraverser = new PInvokeMethodMetadataTraverser(interopHelperReference.PInvokeHelpers); pinvokeMethodMetadataTraverser.TraverseChildren(mutable); var methodTransformationMetadataRewriter = new MethodTransformationMetadataRewriter(interopHelperReference.LoadLibrary, interopHelperReference.GetProcAddress, interopHelperReference.IsLibraryInitialized, host, pinvokeMethodMetadataTraverser); methodTransformationMetadataRewriter.RewriteChildren(mutable); var pinvokeMethodMetadataRewriter = new PInvokeMethodMetadataRewriter(interopHelperReference, host, methodTransformationMetadataRewriter); pinvokeMethodMetadataRewriter.RewriteChildren(mutable); using (var stream = File.Create(outputFile)) { PeWriter.WritePeToStream(mutable, host, stream); } } }
private static void TransformProgram(WholeProgram wholeProgram, string transformedBinariesPath, string reportsPath, MethodRemoval methodRemoval, TargetProfile profile) { System.IO.Directory.CreateDirectory(transformedBinariesPath); StubMethodBodyEmitter stubEmitter = GetStubMethodBodyEmitterForProfile(profile, wholeProgram); foreach (IAssembly assembly in wholeProgram.AllAssemblies()) { if (AssemblyShouldBeRewritten(assembly)) { if (assembly.PublicKeyToken.Count() > 0) { Console.WriteLine("Warning: rewriting assembly with a public key token. {0}", assembly); } string outputBinary = transformedBinariesPath + @"\" + Path.GetFileName(assembly.Location); var copy = new MetadataDeepCopier(wholeProgram.Host()).Copy(assembly); DocumentationCommentDefinitionIdStringMap idMap = new DocumentationCommentDefinitionIdStringMap(new IAssembly[] { copy }); AssemblyReport assemblyReport = AssemblyReport.CreateAssemblyReportFromPath(copy, reportsPath, idMap); stopwatch.Start(); RewriteBinary(copy, assemblyReport, wholeProgram.Host(), outputBinary, methodRemoval, stubEmitter); stopwatch.Start(); } else { //Console.WriteLine("Skipping rewrite of of assembly {0}", assembly.Name.Value); } } }
private Prune( IMetadataHost host, MetadataDeepCopier copier, HashSet <object> thingsToKeep, HashSet <uint> methodsWhoseBodiesShouldBeKept, IDictionary <IMethodDefinition, MethodHashAttribute> methodHashAttributes ) : base(host) { Contract.Requires(host != null); Contract.Requires(copier != null); Contract.Requires(thingsToKeep != null); Contract.Requires(methodsWhoseBodiesShouldBeKept != null); Contract.Requires(methodHashAttributes != null); this.copier = copier; this.thingsToKeep = thingsToKeep; this.methodDefsToKeep = methodsWhoseBodiesShouldBeKept; this.methodHashAttributes = methodHashAttributes; this.systemInt = host.PlatformType.SystemInt32; this.systemString = host.PlatformType.SystemString; }
private Prune( IMetadataHost host, MetadataDeepCopier copier, HashSet<object> thingsToKeep, HashSet<uint> methodsWhoseBodiesShouldBeKept, IDictionary<IMethodDefinition, MethodHashAttribute> methodHashAttributes ) : base(host) { Contract.Requires(host != null); Contract.Requires(copier != null); Contract.Requires(thingsToKeep != null); Contract.Requires(methodsWhoseBodiesShouldBeKept != null); Contract.Requires(methodHashAttributes != null); this.copier = copier; this.thingsToKeep = thingsToKeep; this.methodDefsToKeep = methodsWhoseBodiesShouldBeKept; this.methodHashAttributes = methodHashAttributes; this.systemInt = host.PlatformType.SystemInt32; this.systemString = host.PlatformType.SystemString; }
public Assembly GenerateFacade(IAssembly contractAssembly, IAssemblyReference seedCoreAssemblyReference, bool ignoreMissingTypes, IAssembly overrideContractAssembly = null) { Assembly assembly; if (overrideContractAssembly != null) { MetadataDeepCopier copier = new MetadataDeepCopier(_seedHost); assembly = copier.Copy(overrideContractAssembly); // Use non-empty partial facade if present } else { MetadataDeepCopier copier = new MetadataDeepCopier(_contractHost); assembly = copier.Copy(contractAssembly); ReferenceAssemblyToFacadeRewriter rewriter = new ReferenceAssemblyToFacadeRewriter(_seedHost, _contractHost, seedCoreAssemblyReference, _assemblyFileVersion != null); rewriter.Rewrite(assembly); } IEnumerable<string> docIds = _docIdTable[contractAssembly.AssemblyIdentity.Name.Value]; // Add all the type forwards bool error = false; HashSet<string> existingDocIds = new HashSet<string>(assembly.AllTypes.Select(typeDef => typeDef.RefDocId())); IEnumerable<string> missingDocIds = docIds.Where(id => !existingDocIds.Contains(id)); foreach (string docId in missingDocIds) { IReadOnlyList<INamedTypeDefinition> seedTypes; if (!_typeTable.TryGetValue(docId, out seedTypes)) { if (!ignoreMissingTypes) { Trace.TraceError("Did not find type '{0}' in any of the seed assemblies.", docId); error = true; } continue; } INamedTypeDefinition seedType = GetSeedType(docId, seedTypes); if (seedType == null) { TraceDuplicateSeedTypeError(docId, seedTypes); error = true; continue; } AddTypeForward(assembly, seedType); } if (error) { return null; } if (_assemblyFileVersion != null) { assembly.AssemblyAttributes.Add(CreateAttribute("System.Reflection.AssemblyFileVersionAttribute", seedCoreAssemblyReference.ResolvedAssembly, _assemblyFileVersion.ToString())); assembly.AssemblyAttributes.Add(CreateAttribute("System.Reflection.AssemblyInformationalVersionAttribute", seedCoreAssemblyReference.ResolvedAssembly, _assemblyFileVersion.ToString())); } if (_buildDesignTimeFacades) { assembly.AssemblyAttributes.Add(CreateAttribute("System.Runtime.CompilerServices.ReferenceAssemblyAttribute", seedCoreAssemblyReference.ResolvedAssembly)); assembly.Flags |= ReferenceAssemblyFlag; } if (_clearBuildAndRevision) { assembly.Version = new Version(assembly.Version.Major, assembly.Version.Minor, 0, 0); } AddWin32VersionResource(contractAssembly.Location, assembly); return assembly; }
public Assembly GenerateFacade(IAssembly contractAssembly, IAssemblyReference seedCoreAssemblyReference, bool ignoreMissingTypes, IAssembly overrideContractAssembly = null, bool buildPartialReferenceFacade = false) { Assembly assembly; if (overrideContractAssembly != null) { MetadataDeepCopier copier = new MetadataDeepCopier(_seedHost); assembly = copier.Copy(overrideContractAssembly); // Use non-empty partial facade if present } else { MetadataDeepCopier copier = new MetadataDeepCopier(_contractHost); assembly = copier.Copy(contractAssembly); // if building a reference facade don't strip the contract if (!buildPartialReferenceFacade) { ReferenceAssemblyToFacadeRewriter rewriter = new ReferenceAssemblyToFacadeRewriter(_seedHost, _contractHost, seedCoreAssemblyReference, _assemblyFileVersion != null); rewriter.Rewrite(assembly); } } string contractAssemblyName = contractAssembly.AssemblyIdentity.Name.Value; IEnumerable <string> docIds = _docIdTable[contractAssemblyName]; // Add all the type forwards bool error = false; Dictionary <string, INamedTypeDefinition> existingDocIds = assembly.AllTypes.ToDictionary(typeDef => typeDef.RefDocId(), typeDef => typeDef); IEnumerable <string> docIdsToForward = buildPartialReferenceFacade ? existingDocIds.Keys : docIds.Where(id => !existingDocIds.ContainsKey(id)); Dictionary <string, INamedTypeReference> forwardedTypes = new Dictionary <string, INamedTypeReference>(); foreach (string docId in docIdsToForward) { IReadOnlyList <INamedTypeDefinition> seedTypes; if (!_typeTable.TryGetValue(docId, out seedTypes)) { if (!ignoreMissingTypes && !buildPartialReferenceFacade) { Trace.TraceError("Did not find type '{0}' in any of the seed assemblies.", docId); error = true; } continue; } INamedTypeDefinition seedType = GetSeedType(docId, seedTypes); if (seedType == null) { TraceDuplicateSeedTypeError(docId, seedTypes); error = true; continue; } if (buildPartialReferenceFacade) { // honor preferSeedType for keeping contract type string preferredSeedAssembly; bool keepType = _seedTypePreferences.TryGetValue(docId, out preferredSeedAssembly) && contractAssemblyName.Equals(preferredSeedAssembly, StringComparison.OrdinalIgnoreCase); if (keepType) { continue; } assembly.AllTypes.Remove(existingDocIds[docId]); forwardedTypes.Add(docId, seedType); } AddTypeForward(assembly, seedType); } if (buildPartialReferenceFacade) { if (forwardedTypes.Count == 0) { Trace.TraceError("Did not find any types in any of the seed assemblies."); return(null); } else { // for any thing that's now a typeforward, make sure typerefs point to that rather than // the type previously inside the assembly. TypeReferenceRewriter typeRefRewriter = new TypeReferenceRewriter(_seedHost, oldType => { INamedTypeReference newType = null; return(forwardedTypes.TryGetValue(oldType.DocId(), out newType) ? newType : oldType); }); typeRefRewriter.Rewrite(assembly); } } if (error) { return(null); } if (_assemblyFileVersion != null) { assembly.AssemblyAttributes.Add(CreateAttribute("System.Reflection.AssemblyFileVersionAttribute", seedCoreAssemblyReference.ResolvedAssembly, _assemblyFileVersion.ToString())); assembly.AssemblyAttributes.Add(CreateAttribute("System.Reflection.AssemblyInformationalVersionAttribute", seedCoreAssemblyReference.ResolvedAssembly, _assemblyFileVersion.ToString())); } if (_buildDesignTimeFacades) { assembly.AssemblyAttributes.Add(CreateAttribute("System.Runtime.CompilerServices.ReferenceAssemblyAttribute", seedCoreAssemblyReference.ResolvedAssembly)); assembly.Flags |= ReferenceAssemblyFlag; } if (_clearBuildAndRevision) { assembly.Version = new Version(assembly.Version.Major, assembly.Version.Minor, 0, 0); } AddWin32VersionResource(contractAssembly.Location, assembly); return(assembly); }
/// <summary> /// Gets a mutable copy of the target assembly. /// </summary> /// <param name="target"> /// The assembly to retrieve the mutable copy for. /// </param> /// <param name="host"> /// The host to use when loading the assembly. /// </param> /// <returns> /// A mutable copy of the target assembly. /// </returns> private static Assembly GetMutableAssembly(IAssemblyTarget target, IMetadataHost host) { var copier = new MetadataDeepCopier(host); return copier.Copy(LoadModule(target, host)); }
private Task LoadManagedData() { return _loadingManagedData ?? (_loadingManagedData = _tasks.Start(() => { if (_loadOptions.HasFlag(BinaryLoadOptions.NoManaged)) { return; } // load managed data from working file if (!IsManaged) { ILOnly.Value = false; return; } // copy this to a temporary file, because it locks the file until we're *really* done. try { var module = _host.LoadUnitFrom(WorkingCopy) as IModule; if (module == null || module is Dummy) { throw new CoAppException("{0} is not a PE file containing a CLR module or assembly.".format(Filename)); } ILOnly.Value = module.ILOnly; //Make a mutable copy of the module. var copier = new MetadataDeepCopier(_host); var mutableModule = copier.Copy(module); //Traverse the module. In a real application the MetadataVisitor and/or the MetadataTravers will be subclasses //and the traversal will gather information to use during rewriting. var traverser = new MetadataTraverser { PreorderVisitor = new MetadataVisitor(), TraverseIntoMethodBodies = true }; traverser.Traverse(mutableModule); //Rewrite the mutable copy. In a real application the rewriter would be a subclass of MetadataRewriter that actually does something. var rewriter = new MetadataRewriter(_host); _mutableAssembly = rewriter.Rewrite(mutableModule) as Assembly; AssemblyCulture.Value = _mutableAssembly.Culture; AssemblyVersion.Value = _mutableAssembly.Version; } finally { // delete it, or at least trash it & queue it up for next reboot. // temporaryCopy.TryHardToDelete(); } try { if (_mutableAssembly != null) { // we should see if we can get assembly attributes, since sometimes they can be set, but not the native ones. foreach (var a in _mutableAssembly.ContainingAssembly.AssemblyAttributes) { var attributeArgument = (a.Arguments.FirstOrDefault() as MetadataConstant); if (attributeArgument != null) { var attributeValue = attributeArgument.Value.ToString(); if (!string.IsNullOrEmpty(attributeValue)) { switch (a.Type.ToString()) { case "System.Reflection.AssemblyTitleAttribute": _fileDescription = _fileDescription ?? attributeValue; break; case "System.Reflection.AssemblyCompanyAttribute": _companyName = _companyName ?? attributeValue; break; case "System.Reflection.AssemblyProductAttribute": _productName = _productName ?? attributeValue; break; // case "System.Reflection.AssemblyVersionAttribute": // _assemblyVersion = _assemblyVersion == 0L ? (FourPartVersion)attributeValue : _assemblyVersion; // break; case "System.Reflection.AssemblyFileVersionAttribute": _fileVersion = _fileVersion == 0L ? (FourPartVersion)attributeValue : _fileVersion; _productVersion = _productVersion == 0L ? (FourPartVersion)attributeValue : _productVersion; break; case "System.Reflection.AssemblyCopyrightAttribute": _legalCopyright = _legalCopyright ?? attributeValue; break; case "System.Reflection.AssemblyTrademarkAttribute": _legalTrademarks = _legalTrademarks ?? attributeValue; break; case "System.Reflection.AssemblyDescriptionAttribute": _comments = _comments ?? attributeValue; break; case "BugTrackerAttribute": _bugTracker = _bugTracker ?? attributeValue; break; } } } } } } catch (Exception e) { Console.WriteLine("{0} -- {1}", e.Message, e.StackTrace); } // if there are dependencies, this will load them. if (_loadOptions.HasFlag(BinaryLoadOptions.UnsignedManagedDependencies)) { LoadUnsignedManagedDependencies(); } })); }
internal static void Amend(params string[] targets) { // Ensure that at least one target assembly was specified if (targets == null || targets.Length == 0) { throw new ArgumentException("At least one target assembly must be specified."); } // Ensure that the target assemblies exist for (int i = 0; i < targets.Length; i++) { var path = targets[i] = Path.GetFullPath(targets[i]); if (!File.Exists(path)) { throw new ArgumentException("The specified target assembly, " + path + ", does not exist."); } } // Determine the set of target directories and backup locations var directories = targets .Select(path => Path.GetDirectoryName(path).ToLower()) .Distinct() .Select(directory => new { SourcePath = directory, BackupPath = Directory.CreateDirectory(Path.Combine(directory, "Backup")).FullName }); // Determine the set of dlls, pdbs, and backup files var assemblies = targets .Select(dllPath => new { DllPath = dllPath, DllBackupPath = Path.Combine(Path.Combine(Path.GetDirectoryName(dllPath), "Backup"), Path.GetFileName(dllPath)), PdbPath = Path.Combine(Path.GetDirectoryName(dllPath), Path.GetFileNameWithoutExtension(dllPath) + ".pdb"), PdbBackupPath = Path.Combine(Path.Combine(Path.GetDirectoryName(dllPath), "Backup"), Path.GetFileNameWithoutExtension(dllPath) + ".pdb") }); // Backup the directories containing the targeted dll and pdb files foreach (var directory in directories) { foreach (var file in Directory.GetFiles(directory.SourcePath)) { if (file.ToLower().EndsWith("exe") || file.ToLower().EndsWith("dll") || file.ToLower().EndsWith("pdb")) { File.Copy(file, Path.Combine(directory.BackupPath, Path.GetFileName(file)), true); } } } // Register an assembly resolver to look in backup folders when resolving assemblies AppDomain.CurrentDomain.AssemblyResolve += (s, e) => { try { return(System.Reflection.Assembly.Load(e.Name)); } catch { foreach (var directory in directories) { var dependency = Path.Combine(directory.BackupPath, e.Name.Substring(0, e.Name.IndexOf(',')) + ".dll"); if (File.Exists(dependency)) { return(System.Reflection.Assembly.LoadFrom(dependency)); } } return(null); } }; // Get the set of amendments to apply from all of the specified assemblies var amendments = AmendmentAttribute.GetAmendments(assemblies.Select(a => System.Reflection.Assembly.LoadFrom(a.DllBackupPath)).ToArray()).ToList(); // Exit immediately if there are no amendments in the target assemblies if (amendments.Count == 0) { return; } // Process each target assembly individually foreach (var assembly in assemblies) { var assemblyAmendments = amendments.Where(a => a.Type.Assembly.Location == assembly.DllBackupPath).ToArray(); if (assemblyAmendments.Length == 0) { continue; } Console.Write("Amending " + Path.GetFileName(assembly.DllPath)); var start = DateTime.Now; using (var host = new PeReader.DefaultHost()) { // Load the target assembly IModule module = host.LoadUnitFrom(assembly.DllBackupPath) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new ArgumentException(assembly.DllBackupPath + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); } // Copy the assembly to enable it to be mutated module = new MetadataDeepCopier(host).Copy(module); // Load the debug file if it exists PdbReader pdbReader = null; if (File.Exists(assembly.PdbBackupPath)) { using (var pdbStream = File.OpenRead(assembly.PdbBackupPath)) { pdbReader = new PdbReader(pdbStream, host); } } // Amend and persist the target assembly using (pdbReader) { // Create and execute a new assembly amender AssemblyAmender amender = new AssemblyAmender(host, pdbReader, assemblyAmendments); amender.TargetRuntimeVersion = module.TargetRuntimeVersion; module = amender.Visit(module); // Save the amended assembly back to the original directory using (var pdbWriter = pdbReader != null ? new PdbWriter(assembly.PdbPath, pdbReader) : null) { using (var dllStream = File.Create(assembly.DllPath)) { PeWriter.WritePeToStream(module, host, dllStream, pdbReader, null, pdbWriter); } } } } Console.WriteLine(" (" + DateTime.Now.Subtract(start).TotalSeconds.ToString("0.000") + " seconds)"); } }
/// <summary> /// Returns a mutable Code Model module that is equivalent to the given Metadata Model module, /// except that in the new module method bodies also implement ISourceMethodBody. /// </summary> /// <param name="host">An object representing the application that is hosting this decompiler. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references.</param> /// <param name="module">The root of the Metadata Model to be converted to a Code Model.</param> /// <param name="sourceLocationProvider">An object that can map some kinds of ILocation objects to IPrimarySourceLocation objects. May be null.</param> /// <param name="localScopeProvider">An object that can provide information about the local scopes of a method. May be null.</param> /// <param name="options">Set of options that control decompilation.</param> private static Module GetCodeModelFromMetadataModelHelper(IMetadataHost host, IModule module, ISourceLocationProvider/*?*/ sourceLocationProvider, ILocalScopeProvider/*?*/ localScopeProvider, DecompilerOptions options) { var result = new MetadataDeepCopier(host).Copy(module); var replacer = new ReplaceMetadataMethodBodiesWithDecompiledMethodBodies(host, module, sourceLocationProvider, localScopeProvider, options); replacer.Traverse(result); var finder = new HelperTypeFinder(host, sourceLocationProvider); finder.Traverse(result); var remover = new RemoveUnnecessaryTypes(finder.helperTypes, finder.helperMethods, finder.helperFields); remover.Traverse(result); result.AllTypes.RemoveAll(td => finder.helperTypes.ContainsKey(td.InternedKey)); // depends on RemoveAll preserving order return result; }
/// <summary> /// Amends the specified target assembly, optionally using assembly amendments defined in the /// specified amendment assemblies. /// </summary> /// <param name="targetAssembly"></param> /// <param name="amendmentAssemblies"></param> internal static void Amend(string targetAssembly, string[] amendmentAssemblies, string[] referenceAssemblies) { // Verify the target assembly exists targetAssembly = Path.GetFullPath(targetAssembly); if (!File.Exists(targetAssembly)) throw new ArgumentException("The specified target assembly, " + targetAssembly + ", does not exist."); // Verify the amendment assemblies exist if (amendmentAssemblies == null) amendmentAssemblies = new string[0]; for (int i = 0; i < amendmentAssemblies.Length; i++) { var path = amendmentAssemblies[i] = Path.GetFullPath(amendmentAssemblies[i]); if (!File.Exists(path)) throw new ArgumentException("The specified amendment assembly, " + path + ", does not exist."); } // Verify that the target has not already been amended var afterthoughtTracker = targetAssembly + ".afterthought"; if (File.Exists(afterthoughtTracker) && File.GetLastWriteTime(targetAssembly) == File.GetLastWriteTime(afterthoughtTracker)) return; // Determine the set of target directories and backup locations var targetWriteTime = File.GetLastWriteTime(targetAssembly); var backupTargetAssembly = targetAssembly + ".backup"; var targetDirectory = Path.GetDirectoryName(targetAssembly); File.Delete(backupTargetAssembly); File.Move(targetAssembly, backupTargetAssembly); // Build up a set of paths with resolving assemblies var referencePaths = new Dictionary<string, string>(); foreach (string path in amendmentAssemblies .Union(referenceAssemblies) .Union(Directory.GetFiles(targetDirectory).Where(p => p.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) && p != targetAssembly))) referencePaths[Path.GetFileName(path)] = path; // Register an assembly resolver to look in assembly directories when resolving assemblies AppDomain.CurrentDomain.AssemblyResolve += (s, e) => { var assemblyName = new System.Reflection.AssemblyName(e.Name).Name + ".dll"; string referencePath; if (referencePaths.TryGetValue(assemblyName, out referencePath)) return System.Reflection.Assembly.LoadFrom(referencePath); return null; }; // Get the set of amendments to apply from all of the specified assemblies var assemblies = new System.Reflection.Assembly[] { System.Reflection.Assembly.LoadFrom(backupTargetAssembly) }.Union(amendmentAssemblies.Select(a => System.Reflection.Assembly.LoadFrom(a))); var amendments = AmendmentAttribute.GetAmendments(assemblies.First(), assemblies.Skip(1).ToArray()).ToList(); // Exit immediately if there are no amendments in the target assemblies if (amendments.Count == 0) return; // Amend the target assembly Console.Write("Amending " + Path.GetFileName(targetAssembly)); var start = DateTime.Now; using (var host = new PeReader.DefaultHost()) { foreach (var referencePath in referencePaths.Select(p => Path.GetDirectoryName(p.Value)).Distinct()) host.AddLibPath(referencePath); // Load the target assembly IModule module = host.LoadUnitFrom(backupTargetAssembly) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) throw new ArgumentException(backupTargetAssembly + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); // Copy the assembly to enable it to be mutated module = new MetadataDeepCopier(host).Copy(module); // Load the debug file if it exists PdbReader pdbReader = null; var pdbFile = Path.Combine(targetDirectory, Path.GetFileNameWithoutExtension(targetAssembly) + ".pdb"); var backupPdbFile = pdbFile + ".backup"; if (File.Exists(pdbFile)) { File.Delete(backupPdbFile); File.Move(pdbFile, backupPdbFile); using (var pdbStream = File.OpenRead(backupPdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } // Amend and persist the target assembly using (pdbReader) { // Create and execute a new assembly amender AssemblyAmender amender = new AssemblyAmender(host, pdbReader, amendments, assemblies); amender.TargetRuntimeVersion = module.TargetRuntimeVersion; module = amender.Visit(module); // Save the amended assembly back to the original directory var localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader); using (var pdbWriter = pdbReader != null ? new PdbWriter(pdbFile, pdbReader) : null) { using (var dllStream = File.Create(targetAssembly)) { PeWriter.WritePeToStream(module, host, dllStream, pdbReader, localScopeProvider, pdbWriter); } } } File.SetLastWriteTime(targetAssembly, targetWriteTime); if (pdbReader != null) File.SetLastWriteTime(pdbFile, targetWriteTime); } Console.WriteLine(" (" + DateTime.Now.Subtract(start).TotalSeconds.ToString("0.000") + " seconds)"); // Set the last write time of the afterthought tracker to match the amended assembly to prevent accidental reamending File.WriteAllText(afterthoughtTracker, ""); File.SetLastWriteTime(afterthoughtTracker, File.GetLastWriteTime(targetAssembly)); }
static void Main(string[] args) { if (args == null || args.Length == 0) { Console.WriteLine("usage: PeToPe [path]fileName.ext [decompile] [noStack]"); return; } bool decompile = args.Length >= 2; bool noStack = args.Length >= 3; using (var host = new HostEnvironment()) { //Read the Metadata Model from the PE file var module = host.LoadUnitFrom(args[0]) as IModule; if (module == null || module is Dummy) { Console.WriteLine(args[0] + " is not a PE file containing a CLR module or assembly."); return; } //Get a PDB reader if there is a PDB file. PdbReader /*?*/ pdbReader = null; string pdbFile = module.DebugInformationLocation; if (string.IsNullOrEmpty(pdbFile) || !File.Exists(pdbFile)) { pdbFile = Path.ChangeExtension(module.Location, "pdb"); } if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } using (pdbReader) { ISourceLocationProvider sourceLocationProvider = pdbReader; ILocalScopeProvider localScopeProvider = pdbReader; if (decompile) { //Construct a Code Model from the Metadata model via decompilation var options = DecompilerOptions.AnonymousDelegates | DecompilerOptions.Iterators | DecompilerOptions.Loops; if (noStack) { options |= DecompilerOptions.Unstack; } module = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader, options); if (pdbReader != null) { localScopeProvider = new Decompiler.LocalScopeProvider(pdbReader); } } MetadataRewriter rewriter; MetadataDeepCopier copier; if (decompile) { copier = new CodeDeepCopier(host, pdbReader, pdbReader); rewriter = new CodeRewriter(host); } else { copier = new MetadataDeepCopier(host); rewriter = new MetadataRewriter(host); } var mutableModule = copier.Copy(module); module = rewriter.Rewrite(mutableModule); //var validator = new MetadataValidator(host); //List<Microsoft.Cci.ErrorEventArgs> errorEvents = new List<Microsoft.Cci.ErrorEventArgs>(); //host.Errors += (object sender, Microsoft.Cci.ErrorEventArgs e) => errorEvents.Add(e); //var assem = module as IAssembly; //validator.Validate(assem); //if (errorEvents.Count != 0) //{ // foreach (var e in errorEvents) // { // foreach (var err in e.Errors) // { // Console.WriteLine(err.Message); // } // } //} #if DEBUG var newRoot = Path.GetFileNameWithoutExtension(module.Location) + "1"; var newName = newRoot + Path.GetExtension(module.Location); using (Stream peStream = File.Create(newName)) { if (pdbReader == null) { PeWriter.WritePeToStream(module, host, peStream); } else { using (var pdbWriter = new PdbWriter(newRoot + ".pdb", pdbReader, emitTokenSourceInfo: true)) { PeWriter.WritePeToStream(module, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter); } } } #else using (Stream peStream = File.Create(module.Location)) { if (pdbReader == null) { PeWriter.WritePeToStream(module, host, peStream); } else { using (var pdbWriter = new PdbWriter(pdbFile, pdbReader, emitTokenSourceInfo: true)) { PeWriter.WritePeToStream(module, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter); } } } #endif } } }
public ITypeReference Map(ITypeReference typeReference) { var result = new MetadataDeepCopier(host).Copy(typeReference); var rewriter = new ActualMutator(host, targetUnit, sourceUnitIdentity); return rewriter.Rewrite(result); }
public static Assembly PruneAssembly(HostEnvironment host, ISlice <MethodReferenceAdaptor, FieldReferenceAdaptor, TypeReferenceAdaptor, IAssemblyReference> slice) { Contract.Requires(host != null); Contract.Requires(slice != null); var newAssemblyName = slice.Name; var originalAssembly = slice.ContainingAssembly.ResolvedAssembly; Contract.Assume(!(originalAssembly is Dummy)); var methodDefsToKeep = new HashSet <uint>(); foreach (var m in slice.Methods) { methodDefsToKeep.Add(m.reference.InternedKey); } var copier = new MetadataDeepCopier(host); var thingsToKeep = new HashSet <object>(); var methodHashAttributes = new Dictionary <IMethodDefinition, MethodHashAttribute>(); var me = new Prune(host, copier, thingsToKeep, methodDefsToKeep, methodHashAttributes); // 1. everything that is specified in the slice should definitely be kept. foreach (var c in slice.Chains) { me.VisitChain(c); } // 2. everything reachable from the initial set of things to keep should be kept Dictionary <IMethodDefinition, uint> contractOffsets; FindReachable.Reachable(host, slice, thingsToKeep, methodDefsToKeep, out contractOffsets); me.contractOffsets = contractOffsets; // 3. copy the original assembly --- entirely! var a_prime = copier.Copy(originalAssembly); var nameTable = host.NameTable; a_prime.ModuleName = nameTable.GetNameFor(newAssemblyName + ".dll"); a_prime.Name = nameTable.GetNameFor(newAssemblyName); var mutableRoot = (RootUnitNamespace)(a_prime.UnitNamespaceRoot); var methodHashAttributeType = DefineMethodHashAttributeType(host, mutableRoot); me.methodHashAttributeCtor = new Microsoft.Cci.MethodReference( host, methodHashAttributeType, CallingConvention.HasThis, host.PlatformType.SystemVoid, host.NameTable.Ctor, 0, me.systemString, me.systemInt); // 4. delete all unwanted things from the mutable copy me.RewriteChildren(a_prime); var remainingTypes = new List <INamedTypeDefinition>(a_prime.AllTypes.Count); // will only shrink remainingTypes.Add(a_prime.AllTypes[0]); // <Module> class is always kept for (int i = 1, n = a_prime.AllTypes.Count; i < n; i++) { var t = a_prime.AllTypes[i]; Contract.Assume(t != null); Contract.Assume(copier.OriginalFor.ContainsKey(t)); var orig = copier.OriginalFor[t]; if (thingsToKeep.Contains(orig)) { remainingTypes.Add(t); } } a_prime.AllTypes = remainingTypes; // do this afterwards so it doesn't get visited. mutableRoot.Members.Add(methodHashAttributeType); a_prime.AllTypes.Add(methodHashAttributeType); return(a_prime); }
public static void RunBclRewriter(string[] args) { #region Parse the command-line arguments. if (!Parser.ParseArgumentsWithUsage(args, typeof(Program))) { throw new UsageException(); } #endregion #region Figure out paths s_assemblyName = Path.GetFullPath(s_assemblyName); // this has to be specified string outputBaseName = null; if (!String.IsNullOrEmpty(s_output)) { s_output = Path.GetFullPath(s_output); outputBaseName = Path.GetFileNameWithoutExtension(s_output); } else { s_output = Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileNameWithoutExtension(s_assemblyName) + ".small" + Path.GetExtension(s_assemblyName)); outputBaseName = s_assemblyName; } string pdbSourceFile = Path.ChangeExtension(s_assemblyName, "pdb"); string outputPdb = Path.ChangeExtension(s_output, "pdb"); string outputFolder = Path.GetDirectoryName(s_output); // if the user wants to do an in-place rewrite, we copy the file to a temp file if (s_output == s_assemblyName) { String tempPath = s_assemblyName + TempExtension; String tempPdbPath = pdbSourceFile + TempExtension; File.Copy(s_assemblyName, tempPath, true); s_assemblyName = tempPath; if (File.Exists(pdbSourceFile)) { File.Copy(pdbSourceFile, tempPdbPath, true); pdbSourceFile = tempPdbPath; } } if (!Directory.Exists(outputFolder)) { Directory.CreateDirectory(outputFolder); } #endregion #region Load input files HostEnvironment host = new HostEnvironment(new NameTable(), s_assemblyDependencyPaths, s_referencedAssemblies); IAssembly /*?*/ assembly = host.LoadUnitFrom(s_assemblyName) as IAssembly; // TODO: Handle multimodule assemblies if (assembly == null || assembly == Dummy.Assembly) { throw new UsageException(args[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); } if (!File.Exists(s_includeListFile)) { throw new UsageException(String.Format("ERROR: Can't find code model file '{0}'", s_includeListFile)); } ThinModel model = new ThinModel(new ThinnerOptions(host, new AssemblyIdentity[] { assembly.AssemblyIdentity })); model.LoadModel(s_includeListFile, new ModelReaderOptions(s_platform, s_architecture, s_flavor, s_treatFxInternalAsPublic, s_defines)); #endregion #region Calculate api closure. ConsoleTimer.StartTimer("Calculating api closure"); model.LoadMetadataFrom(assembly); ThinModel apiClosure = model.CalculateApiClosure(); if (s_keepTempFiles) { apiClosure.SaveModel(Path.ChangeExtension(s_output, ".apiClosure.xml")); } ConsoleTimer.EndTimer("Calculating api closure"); #endregion #region Calculate impl closure. ConsoleTimer.StartTimer("Calculating implementation closure"); apiClosure.LoadMetadataFrom(assembly); ThinModel implClosure = apiClosure.CalculateImplementationClosure(true, FieldOptions.KeepAll); if (s_keepTempFiles) { implClosure.SaveModel(Path.ChangeExtension(s_output, ".implClosure.xml")); } ConsoleTimer.EndTimer("Calculating implementation closure"); #endregion #region Trim. ConsoleTimer.StartTimer("Trimming assembly"); IncludeSet includeSet = new IncludeSet(); includeSet.LoadFrom(implClosure); var copier = new MetadataDeepCopier(host); Assembly copiedAssembly = copier.Copy(assembly); Trimmer trimmer = new Trimmer(includeSet, true, false, true, host, s_removeSerializable); trimmer.RewriteChildren(copiedAssembly); Assembly mutableAssembly = copiedAssembly; assembly = mutableAssembly; ConsoleTimer.EndTimer("Trimming assembly"); #endregion #region Update assembly name. ConsoleTimer.StartTimer("Updating assembly name"); // If the output assembly name is different, update the internal assembly name to match. AssemblyIdentity originalAssemblyIdentity = mutableAssembly.AssemblyIdentity; if (!outputBaseName.Equals(originalAssemblyIdentity.Name.ToString(), StringComparison.OrdinalIgnoreCase)) { mutableAssembly.Name = host.NameTable.GetNameFor(outputBaseName); mutableAssembly.ModuleName = mutableAssembly.Name; } // If we changed the assembly identity, update references to it. if (!mutableAssembly.AssemblyIdentity.Equals(originalAssemblyIdentity)) { trimmer.UpdateAssemblyReferences(originalAssemblyIdentity, mutableAssembly.AssemblyIdentity); } ConsoleTimer.EndTimer("Updating assembly name"); #endregion #region Write out the assembly ConsoleTimer.StartTimer("Writing assembly"); PdbReader pdbReader = null; PdbWriter pdbWriter = null; if (File.Exists(pdbSourceFile)) { Stream pdbStream = File.OpenRead(pdbSourceFile); pdbReader = new PdbReader(pdbStream, host); pdbWriter = new PdbWriter(outputPdb, pdbReader); Console.WriteLine("Writing pdb: {0}", outputPdb); } Console.WriteLine("Writing assembly: {0}", s_output); FileStream file = File.Create(s_output); try { PeWriter.WritePeToStream(assembly, host, file, pdbReader, pdbReader, pdbWriter); } finally { if (file != null) { file.Dispose(); } if (pdbWriter != null) { pdbWriter.Dispose(); } } ConsoleTimer.EndTimer("Writing assembly"); #endregion }
internal static void Amend(params string[] targets) { // Ensure that at least one target assembly was specified if (targets == null || targets.Length == 0) throw new ArgumentException("At least one target assembly must be specified."); // Ensure that the target assemblies exist for (int i = 0; i < targets.Length; i++) { var path = targets[i] = Path.GetFullPath(targets[i]); if (!File.Exists(path)) throw new ArgumentException("The specified target assembly, " + path + ", does not exist."); } // Determine the set of target directories and backup locations var directories = targets .Select(path => Path.GetDirectoryName(path).ToLower()) .Distinct() .Select(directory => new { SourcePath = directory, BackupPath = Directory.CreateDirectory(Path.Combine(directory, "Backup")).FullName }); // Determine the set of dlls, pdbs, and backup files var assemblies = targets .Select(dllPath => new { DllPath = dllPath, DllBackupPath = Path.Combine(Path.Combine(Path.GetDirectoryName(dllPath), "Backup"), Path.GetFileName(dllPath)), PdbPath = Path.Combine(Path.GetDirectoryName(dllPath), Path.GetFileNameWithoutExtension(dllPath) + ".pdb"), PdbBackupPath = Path.Combine(Path.Combine(Path.GetDirectoryName(dllPath), "Backup"), Path.GetFileNameWithoutExtension(dllPath) + ".pdb") }); // Backup the directories containing the targeted dll and pdb files foreach (var directory in directories) { foreach (var file in Directory.GetFiles(directory.SourcePath)) { if (file.ToLower().EndsWith("exe") || file.ToLower().EndsWith("dll") || file.ToLower().EndsWith("pdb")) { var backupPath = Path.Combine(directory.BackupPath, Path.GetFileName(file)); if (File.Exists(backupPath)) File.SetAttributes(backupPath, File.GetAttributes(backupPath) & ~FileAttributes.ReadOnly); File.Copy(file, backupPath, true); } } } // Register an assembly resolver to look in backup folders when resolving assemblies AppDomain.CurrentDomain.AssemblyResolve += (s, e) => { var assemblyName = new AssemblyName(e.Name).Name + ".dll"; // First see if the assembly is located in one of the target backup directories foreach (var directory in directories) { var dependency = Path.Combine(directory.BackupPath, assemblyName); if (File.Exists(dependency)) return System.Reflection.Assembly.LoadFrom(dependency); } return null; }; // Get the set of amendments to apply from all of the specified assemblies var amendments = AmendmentAttribute.GetAmendments(assemblies.Select(a => System.Reflection.Assembly.LoadFrom(a.DllBackupPath)).ToArray()).ToList(); // Exit immediately if there are no amendments in the target assemblies if (amendments.Count == 0) return; // Process each target assembly individually foreach (var assembly in assemblies) { var assemblyAmendments = amendments.Where(a => a.Type.Assembly.Location == assembly.DllBackupPath).ToArray(); if (assemblyAmendments.Length == 0) continue; Console.Write("Amending " + Path.GetFileName(assembly.DllPath)); var start = DateTime.Now; using (var host = new PeReader.DefaultHost()) { // Load the target assembly IModule module = host.LoadUnitFrom(assembly.DllBackupPath) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) throw new ArgumentException(assembly.DllBackupPath + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); // Copy the assembly to enable it to be mutated module = new MetadataDeepCopier(host).Copy(module); // Load the debug file if it exists PdbReader pdbReader = null; if (File.Exists(assembly.PdbBackupPath)) { using (var pdbStream = File.OpenRead(assembly.PdbBackupPath)) { pdbReader = new PdbReader(pdbStream, host); } } // Amend and persist the target assembly using (pdbReader) { // Create and execute a new assembly amender AssemblyAmender amender = new AssemblyAmender(host, pdbReader, assemblyAmendments); amender.TargetRuntimeVersion = module.TargetRuntimeVersion; module = amender.Visit(module); // Save the amended assembly back to the original directory using (var pdbWriter = pdbReader != null ? new PdbWriter(assembly.PdbPath, pdbReader) : null) { using (var dllStream = File.Create(assembly.DllPath)) { PeWriter.WritePeToStream(module, host, dllStream, pdbReader, null, pdbWriter); } } } } Console.WriteLine(" (" + DateTime.Now.Subtract(start).TotalSeconds.ToString("0.000") + " seconds)"); } }
public static bool Execute( string seeds, string contracts, string facadePath, Version assemblyFileVersion = null, bool clearBuildAndRevision = false, bool ignoreMissingTypes = false, bool ignoreBuildAndRevisionMismatch = false, bool buildDesignTimeFacades = false, string inclusionContracts = null, ErrorTreatment seedLoadErrorTreatment = ErrorTreatment.Default, ErrorTreatment contractLoadErrorTreatment = ErrorTreatment.Default, string[] seedTypePreferencesUnsplit = null, bool forceZeroVersionSeeds = false, bool producePdb = true, string partialFacadeAssemblyPath = null) { if (!Directory.Exists(facadePath)) { Directory.CreateDirectory(facadePath); } var nameTable = new NameTable(); var internFactory = new InternFactory(); try { Dictionary <string, string> seedTypePreferences = ParseSeedTypePreferences(seedTypePreferencesUnsplit); using (var contractHost = new HostEnvironment(nameTable, internFactory)) using (var seedHost = new HostEnvironment(nameTable, internFactory)) { contractHost.LoadErrorTreatment = contractLoadErrorTreatment; seedHost.LoadErrorTreatment = seedLoadErrorTreatment; var contractAssemblies = LoadAssemblies(contractHost, contracts); IReadOnlyDictionary <string, IEnumerable <string> > docIdTable = GenerateDocIdTable(contractAssemblies, inclusionContracts); IAssembly[] seedAssemblies = LoadAssemblies(seedHost, seeds).ToArray(); IAssemblyReference seedCoreAssemblyRef = ((Microsoft.Cci.Immutable.PlatformType)seedHost.PlatformType).CoreAssemblyRef; if (forceZeroVersionSeeds) { // Create a deep copier, copy the seed assemblies, and zero out their versions. var copier = new MetadataDeepCopier(seedHost); for (int i = 0; i < seedAssemblies.Length; i++) { var mutableSeed = copier.Copy(seedAssemblies[i]); mutableSeed.Version = new Version(0, 0, 0, 0); // Copy the modified seed assembly back. seedAssemblies[i] = mutableSeed; if (mutableSeed.Name.UniqueKey == seedCoreAssemblyRef.Name.UniqueKey) { seedCoreAssemblyRef = mutableSeed; } } } var typeTable = GenerateTypeTable(seedAssemblies); var facadeGenerator = new FacadeGenerator(seedHost, contractHost, docIdTable, typeTable, seedTypePreferences, clearBuildAndRevision, buildDesignTimeFacades, assemblyFileVersion); if (partialFacadeAssemblyPath != null) { if (contractAssemblies.Count() != 1) { throw new FacadeGenerationException( "When partialFacadeAssemblyPath is specified, only exactly one corresponding contract assembly can be specified."); } IAssembly contractAssembly = contractAssemblies.First(); IAssembly partialFacadeAssembly = seedHost.LoadAssembly(partialFacadeAssemblyPath); if (contractAssembly.Name != partialFacadeAssembly.Name || contractAssembly.Version.Major != partialFacadeAssembly.Version.Major || contractAssembly.Version.Minor != partialFacadeAssembly.Version.Minor || (!ignoreBuildAndRevisionMismatch && contractAssembly.Version.Build != partialFacadeAssembly.Version.Build) || (!ignoreBuildAndRevisionMismatch && contractAssembly.Version.Revision != partialFacadeAssembly.Version.Revision) || contractAssembly.GetPublicKeyToken() != partialFacadeAssembly.GetPublicKeyToken()) { throw new FacadeGenerationException( string.Format("The partial facade assembly's name, version, and public key token must exactly match the contract to be filled. Contract: {0}, Facade: {1}", contractAssembly.AssemblyIdentity, partialFacadeAssembly.AssemblyIdentity)); } Assembly filledPartialFacade = facadeGenerator.GenerateFacade(contractAssembly, seedCoreAssemblyRef, ignoreMissingTypes, overrideContractAssembly: partialFacadeAssembly); if (filledPartialFacade == null) { Trace.TraceError("Errors were encountered while generating the facade."); return(false); } string pdbLocation = null; if (producePdb) { string pdbFolder = Path.GetDirectoryName(partialFacadeAssemblyPath); pdbLocation = Path.Combine(pdbFolder, contractAssembly.Name + ".pdb"); if (producePdb && !File.Exists(pdbLocation)) { pdbLocation = null; Trace.TraceWarning("No PDB file present for un-transformed partial facade. No PDB will be generated."); } } OutputFacadeToFile(facadePath, seedHost, filledPartialFacade, contractAssembly, pdbLocation); } else { foreach (var contract in contractAssemblies) { Assembly facade = facadeGenerator.GenerateFacade(contract, seedCoreAssemblyRef, ignoreMissingTypes); if (facade == null) { #if !COREFX Debug.Assert(Environment.ExitCode != 0); #endif return(false); } OutputFacadeToFile(facadePath, seedHost, facade, contract); } } } return(true); } catch (FacadeGenerationException ex) { Trace.TraceError(ex.Message); #if !COREFX Debug.Assert(Environment.ExitCode != 0); #endif return(false); } }
static void Main(string[] args) { String inputFile; String targetFile; String targetNamespace; String targetClass; String targetMethod; int depth; int dimension; int numberValidPaths; int duplicateBasicBlockWeight; int duplicateBasicBlockCorrectionValue; int stateChangeWeight; int stateChangeCorrectionValue; int insertOpaquePredicateWeight; int seed; // Add debugging code into the obfuscated method (dump obfuscation graphs and so on) bool graphTransformerDebug = false; // Should the obfuscated code contain information to trace the control flow? bool basicBlockTrace = false; // When debugging is active, should the whole obfuscation graph be dumped or only the vpaths in it? bool graphOnlyDumpVPaths = true; // The number of random interfaces that are added to the program int numberRandomInterfaces = 100; if (args.Length != 14) { System.Console.WriteLine("Needed parameters: <inputBinary> <outputBinary> <namespace> <class> <method> <depth> <dimension> <numberValidPaths> <duplicateBasicBlockWeight> <duplicateBasicBlockCorrectionValue> <stateChangeWeight> <stateChangeCorrectionValue> <insertOpaquePredicateWeight> <seed>"); return; } else { inputFile = args[0]; targetFile = args[1]; targetNamespace = args[2]; targetClass = args[3]; targetMethod = args[4]; depth = Convert.ToInt32(args[5]); dimension = Convert.ToInt32(args[6]); numberValidPaths = Convert.ToInt32(args[7]); duplicateBasicBlockWeight = Convert.ToInt32(args[8]); duplicateBasicBlockCorrectionValue = Convert.ToInt32(args[9]); stateChangeWeight = Convert.ToInt32(args[10]); stateChangeCorrectionValue = Convert.ToInt32(args[11]); insertOpaquePredicateWeight = Convert.ToInt32(args[12]); seed = Convert.ToInt32(args[13]); } String logDir = Path.GetDirectoryName(targetFile); Log.Log logger = new Log.Log(logDir, "probfuscation_logfile.txt"); System.Console.WriteLine("Obfuscating: " + inputFile); logger.writeLine("Obfuscating: " + inputFile); System.Console.WriteLine("Output file: " + targetFile); logger.writeLine("Output file: " + targetFile); System.Console.WriteLine("Target namespace: " + targetNamespace); logger.writeLine("Target namespace: " + targetNamespace); System.Console.WriteLine("Target class: " + targetClass); logger.writeLine("Target class: " + targetClass); System.Console.WriteLine("Target method: " + targetMethod); logger.writeLine("Target method: " + targetMethod); System.Console.WriteLine("Depth: " + depth); logger.writeLine("Depth: " + depth); System.Console.WriteLine("Dimension: " + dimension); logger.writeLine("Dimension: " + dimension); System.Console.WriteLine("Number of vpaths: " + numberValidPaths); logger.writeLine("Number of vpaths: " + numberValidPaths); System.Console.WriteLine("Basic Block duplication weight: " + duplicateBasicBlockWeight); logger.writeLine("Basic Block duplication weight: " + duplicateBasicBlockWeight); System.Console.WriteLine("Basic Block duplication correction value: " + duplicateBasicBlockCorrectionValue); logger.writeLine("Basic Block duplication correction value: " + duplicateBasicBlockCorrectionValue); System.Console.WriteLine("State change weight: " + stateChangeWeight); logger.writeLine("State change weight: " + stateChangeWeight); System.Console.WriteLine("State change correction value: " + stateChangeCorrectionValue); logger.writeLine("State change correction value: " + stateChangeCorrectionValue); System.Console.WriteLine("Opaque predicate weight: " + insertOpaquePredicateWeight); logger.writeLine("Opaque predicate weight: " + insertOpaquePredicateWeight); System.Console.WriteLine("Seed: " + seed); logger.writeLine("Seed: " + seed); // Seed PRNG for interfaces PRNGRandomInterfaces = new Random(seed); using (var host = new PeReader.DefaultHost()) { IModule/*?*/ module = host.LoadUnitFrom(inputFile) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { Console.WriteLine(inputFile + " is not a PE file containing a CLR module or assembly."); return; } module = new MetadataDeepCopier(host).Copy(module); if (module as Assembly == null) { logger.writeLine("File does not have CIL assembly"); return; } // create analyzer object object CfgBuilder analyze = new Cfg.CfgBuilder(module, host, logger); PdbReader/*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { logger.writeLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { Microsoft.Cci.ILGenerator.LocalScopeProvider localScopeProvider = null; if (pdbReader != null) { localScopeProvider = new ILGenerator.LocalScopeProvider(pdbReader); } // search the namespace the interface should be added to IUnitNamespace foundNamespace = null; foreach (var tempMember in module.UnitNamespaceRoot.Members) { if ((tempMember as IUnitNamespace) == null) { continue; } IUnitNamespace tempNamespace = (tempMember as IUnitNamespace); if (tempNamespace.ToString() == targetNamespace) { foundNamespace = tempNamespace; break; } } if (foundNamespace == null) { throw new ArgumentException("Not able to find target namespace."); } // add created interface (and implemented methods) to all classes bool classFound = false; foreach (var tempClass in module.GetAllTypes()) { if ((tempClass as NamespaceTypeDefinition) == null || tempClass.IsAbstract) { continue; } NamespaceTypeDefinition foundClass = (tempClass as NamespaceTypeDefinition); if (foundClass.ContainingUnitNamespace.ToString() == "") { continue; } if (foundClass.ToString() != targetNamespace + "." + targetClass) { continue; } classFound = true; Random prng = new Random(); GraphTransformer graphTransformer = new GraphTransformer(module, host, logger, prng, foundNamespace, foundClass, depth, dimension, graphTransformerDebug); graphTransformer.duplicateBasicBlockWeight = duplicateBasicBlockWeight; graphTransformer.duplicateBasicBlockCorrectionValue = duplicateBasicBlockCorrectionValue; graphTransformer.stateChangeWeight = stateChangeWeight; graphTransformer.stateChangeCorrectionValue = stateChangeCorrectionValue; graphTransformer.insertOpaquePredicateWeight = insertOpaquePredicateWeight; graphTransformer.trace = basicBlockTrace; graphTransformer.graphOnlyDumpVPaths = graphOnlyDumpVPaths; graphTransformer.debuggingDumpLocation = logDir; // Add 100 random interfaces to the namespace Helper testHelper = new Helper(module, host, logger); List<NamespaceTypeDefinition> randomInterfaces = new List<NamespaceTypeDefinition>(); for (int i = 0; i < numberRandomInterfaces; i++) { String randName = randomString(20); NamespaceTypeDefinition temp = testHelper.createNewInterface(randName, foundNamespace); randomInterfaces.Add(temp); } InterfaceTransformer interfaceTransformer = new InterfaceTransformer(module, host, logger); foreach (var classToAdd in module.GetAllTypes()) { if ((classToAdd as NamespaceTypeDefinition) == null || classToAdd.IsAbstract || classToAdd.IsInterface || classToAdd.IsEnum || classToAdd.IsDelegate || classToAdd.IsGeneric || classToAdd.IsStruct) { continue; } if (((NamespaceTypeDefinition)classToAdd).ContainingUnitNamespace.ToString() == "") { continue; } /* // Use this code if you want to add standard interfaces to the target class interfaceTransformer.addStdInterfacesGivenByFile(@"e:\code\dotnet_standard_interfaces.txt"); // add std interfaces to class if (foundClass != (classToAdd as NamespaceTypeDefinition)) { foreach (ITypeDefinition temp in interfaceTransformer.getInterfacesList()) { interfaceTransformer.addInterface((classToAdd as NamespaceTypeDefinition), temp); } } */ // Add random interfaces to the classes List<NamespaceTypeDefinition> alreadyAdded = new List<NamespaceTypeDefinition>(); int max = PRNGRandomInterfaces.Next(numberRandomInterfaces); NamespaceTypeDefinition interfaceClass = (classToAdd as NamespaceTypeDefinition); logger.writeLine("Adding " + max + " random interfaces to class \"" + interfaceClass.ToString() + "\""); for (int i = 0; i < max; i++) { NamespaceTypeDefinition randInterface = randomInterfaces.ElementAt(PRNGRandomInterfaces.Next(randomInterfaces.Count)); if (alreadyAdded.Contains(randInterface)) { continue; } alreadyAdded.Add(randInterface); logger.writeLine("Adding interface: \"" + randInterface.ToString() + "\""); // add nodes interface to class if (interfaceClass.Interfaces != null) { interfaceClass.Interfaces.Add(randInterface); } else { interfaceClass.Interfaces = new List<ITypeReference>(); interfaceClass.Interfaces.Add(randInterface); } } logger.writeLine(""); // Add special interface for the obfuscation scheme to the class // (makes sure that all needed attributes and methods are implemented) graphTransformer.addNodeInterfaceToTargetClass((classToAdd as NamespaceTypeDefinition)); } // Prepare obfuscation graph graphTransformer.generateGraph(numberValidPaths); graphTransformer.createGraphMethods(); // Search method to obfuscate MethodDefinition methodToObfu = null; foreach (MethodDefinition tempMethod in foundClass.Methods) { if (tempMethod.Name.ToString() == targetMethod) { methodToObfu = tempMethod; break; } } if (methodToObfu == null) { throw new ArgumentException("Not able to find target method."); } // Obfuscate target method MethodCfg cfg = analyze.buildCfgForMethod(methodToObfu); logger.dumpMethodCfg(cfg, "before"); graphTransformer.addObfuscationToMethod(cfg); analyze.createMethodFromCfg(cfg); logger.dumpMethodCfg(cfg, "after"); break; } if (!classFound) { throw new ArgumentException("Not able to find target class."); } /* * This code can be used if not only one specific method should be obfuscated, * but the whole class. List<ClassCfg> classCfgList = new List<ClassCfg>(); foreach (var tempClass in module.GetAllTypes()) { if ((tempClass as NamespaceTypeDefinition) == null || tempClass.IsAbstract) { continue; } // create basic blocks NamespaceTypeDefinition foundClass = (tempClass as NamespaceTypeDefinition); logger.writeLine("Create CFG for class \"" + foundClass.Name.ToString() + "\""); ClassCfg temp = analyze.buildCfgForClass(foundClass); classCfgList.Add(temp); logger.writeLine("\n---------------------------------\n"); } // transform each function NopTransformer transformator = new NopTransformer(module, host, logger); foreach (ClassCfg tempClassCfg in classCfgList) { foreach (MethodCfg tempMethodCfg in tempClassCfg.methodCfgs) { logger.writeLine("Transform method CFG of \"" + tempMethodCfg.method.ToString() + "\""); transformator.addNopsToCfg(tempMethodCfg); logger.writeLine("\n---------------------------------\n"); } } foreach (ClassCfg tempClassCfg in classCfgList) { logger.writeLine("Create class from CFG for \"" + tempClassCfg.classObj.Name.ToString() + "\""); analyze.createClassFromCfg(tempClassCfg); logger.writeLine("\n---------------------------------\n"); } */ using (var peStream = File.Create(targetFile)) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(targetFile, ".pdb"), pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } } }
public static Assembly PruneAssembly(HostEnvironment host, ISlice<MethodReferenceAdaptor, FieldReferenceAdaptor, TypeReferenceAdaptor, IAssemblyReference> slice) { Contract.Requires(host != null); Contract.Requires(slice != null); var newAssemblyName = slice.Name; var originalAssembly = slice.ContainingAssembly.ResolvedAssembly; Contract.Assume(!(originalAssembly is Dummy)); var methodDefsToKeep = new HashSet<uint>(); foreach (var m in slice.Methods) { methodDefsToKeep.Add(m.reference.InternedKey); } var copier = new MetadataDeepCopier(host); var thingsToKeep = new HashSet<object>(); var methodHashAttributes = new Dictionary<IMethodDefinition, MethodHashAttribute>(); var me = new Prune(host, copier, thingsToKeep, methodDefsToKeep, methodHashAttributes); // 1. everything that is specified in the slice should definitely be kept. foreach (var c in slice.Chains) { me.VisitChain(c); } // 2. everything reachable from the initial set of things to keep should be kept Dictionary<IMethodDefinition, uint> contractOffsets; FindReachable.Reachable(host, slice, thingsToKeep, methodDefsToKeep, out contractOffsets); me.contractOffsets = contractOffsets; // 3. copy the original assembly --- entirely! var a_prime = copier.Copy(originalAssembly); var nameTable = host.NameTable; a_prime.ModuleName = nameTable.GetNameFor(newAssemblyName + ".dll"); a_prime.Name = nameTable.GetNameFor(newAssemblyName); var mutableRoot = (RootUnitNamespace)(a_prime.UnitNamespaceRoot); var methodHashAttributeType = DefineMethodHashAttributeType(host, mutableRoot); me.methodHashAttributeCtor = new Microsoft.Cci.MethodReference( host, methodHashAttributeType, CallingConvention.HasThis, host.PlatformType.SystemVoid, host.NameTable.Ctor, 0, me.systemString, me.systemInt); // 4. delete all unwanted things from the mutable copy me.RewriteChildren(a_prime); var remainingTypes = new List<INamedTypeDefinition>(a_prime.AllTypes.Count); // will only shrink remainingTypes.Add(a_prime.AllTypes[0]); // <Module> class is always kept for (int i = 1, n = a_prime.AllTypes.Count; i < n; i++) { var t = a_prime.AllTypes[i]; Contract.Assume(t!= null); Contract.Assume(copier.OriginalFor.ContainsKey(t)); var orig = copier.OriginalFor[t]; if (thingsToKeep.Contains(orig)) remainingTypes.Add(t); } a_prime.AllTypes = remainingTypes; // do this afterwards so it doesn't get visited. mutableRoot.Members.Add(methodHashAttributeType); a_prime.AllTypes.Add(methodHashAttributeType); return a_prime; }
public Assembly GenerateFacade(IAssembly contractAssembly, IAssemblyReference seedCoreAssemblyReference, bool ignoreMissingTypes, IAssembly overrideContractAssembly = null) { Assembly assembly; if (overrideContractAssembly != null) { MetadataDeepCopier copier = new MetadataDeepCopier(_seedHost); assembly = copier.Copy(overrideContractAssembly); // Use non-empty partial facade if present } else { MetadataDeepCopier copier = new MetadataDeepCopier(_contractHost); assembly = copier.Copy(contractAssembly); ReferenceAssemblyToFacadeRewriter rewriter = new ReferenceAssemblyToFacadeRewriter(_seedHost, _contractHost, seedCoreAssemblyReference, _assemblyFileVersion != null); rewriter.Rewrite(assembly); } IEnumerable <string> docIds = _docIdTable[contractAssembly.AssemblyIdentity.Name.Value]; // Add all the type forwards bool error = false; HashSet <string> existingDocIds = new HashSet <string>(assembly.AllTypes.Select(typeDef => typeDef.RefDocId())); IEnumerable <string> missingDocIds = docIds.Where(id => !existingDocIds.Contains(id)); foreach (string docId in missingDocIds) { IReadOnlyList <INamedTypeDefinition> seedTypes; if (!_typeTable.TryGetValue(docId, out seedTypes)) { if (!ignoreMissingTypes) { Trace.TraceError("Did not find type '{0}' in any of the seed assemblies.", docId); error = true; } continue; } INamedTypeDefinition seedType = GetSeedType(docId, seedTypes); if (seedType == null) { TraceDuplicateSeedTypeError(docId, seedTypes); error = true; continue; } AddTypeForward(assembly, seedType); } if (error) { return(null); } if (_assemblyFileVersion != null) { assembly.AssemblyAttributes.Add(CreateAttribute("System.Reflection.AssemblyFileVersionAttribute", seedCoreAssemblyReference.ResolvedAssembly, _assemblyFileVersion.ToString())); assembly.AssemblyAttributes.Add(CreateAttribute("System.Reflection.AssemblyInformationalVersionAttribute", seedCoreAssemblyReference.ResolvedAssembly, _assemblyFileVersion.ToString())); } if (_buildDesignTimeFacades) { assembly.AssemblyAttributes.Add(CreateAttribute("System.Runtime.CompilerServices.ReferenceAssemblyAttribute", seedCoreAssemblyReference.ResolvedAssembly)); assembly.Flags |= ReferenceAssemblyFlag; } if (_clearBuildAndRevision) { assembly.Version = new Version(assembly.Version.Major, assembly.Version.Minor, 0, 0); } AddWin32VersionResource(contractAssembly.Location, assembly); return(assembly); }
static void Main(string[] args) { if (args == null || args.Length == 0) { Console.WriteLine("usage: PeToPe [path]fileName.ext"); return; } using (var host = new PeReader.DefaultHost()) { var module = host.LoadUnitFrom(args[0]) as IModule; if (module == null || module is Dummy) { Console.WriteLine(args[0] + " is not a PE file containing a CLR module or assembly."); return; } PdbReader /*?*/ pdbReader = null; string pdbFile = module.DebugInformationLocation; if (string.IsNullOrEmpty(pdbFile)) { pdbFile = Path.ChangeExtension(module.Location, "pdb"); } if (File.Exists(pdbFile)) { Stream pdbStream = File.OpenRead(pdbFile); pdbReader = new PdbReader(pdbStream, host); } using (pdbReader) { //Make a mutable copy of the module. var copier = new MetadataDeepCopier(host); var mutableModule = copier.Copy(module); //Traverse the module. In a real application the MetadataVisitor and/or the MetadataTravers will be subclasses //and the traversal will gather information to use during rewriting. var traverser = new MetadataTraverser() { PreorderVisitor = new MetadataVisitor(), TraverseIntoMethodBodies = true }; traverser.Traverse(mutableModule); //Rewrite the mutable copy. In a real application the rewriter would be a subclass of MetadataRewriter that actually does something. var rewriter = new MetadataRewriter(host); var rewrittenModule = rewriter.Rewrite(mutableModule); //Write out rewritten module. using (var peStream = File.Create(rewrittenModule.Location + ".pe")) { if (pdbReader == null) { PeWriter.WritePeToStream(rewrittenModule, host, peStream); } else { //Note that the default copier and rewriter preserves the locations collections, so the original pdbReader is still a valid ISourceLocationProvider. //However, if IL instructions were rewritten, the pdbReader will no longer be an accurate ILocalScopeProvider using (var pdbWriter = new PdbWriter(pdbFile + ".pdb", pdbReader)) { PeWriter.WritePeToStream(rewrittenModule, host, peStream, pdbReader, pdbReader, pdbWriter); } } } } } }
IAssembly VisitAndMutate(MetadataRewriter mutator, IAssembly assembly) { var mutableAssembly = new MetadataDeepCopier(host).Copy(assembly); assembly = mutator.Rewrite(mutableAssembly); Assert.NotNull(assembly); return assembly; }
private IAssembly LoadAssemblyFrom(string filePath) { IAssembly module = _host.LoadUnitFrom(filePath) as IAssembly; _host.RegisterAsLatest(module); if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new AssemblyReadException(filePath + " is not a PE file containing a CLR module or assembly."); } PdbReader pdbReader; TryGetPdbReader(module, out pdbReader); module = new MetadataDeepCopier(_host).Copy(module); // var decompiled = Decompiler.GetCodeModelFromMetadataModel(_host, module, pdbReader, // DecompilerOptions.None); return module; // return new CodeDeepCopier(_host, pdbReader).Copy(decompiled); }
static void Main(string[] args) { String inputFile; String targetFile; String targetNamespace; String targetClass; String targetMethod; int depth; int dimension; int numberValidPaths; int duplicateBasicBlockWeight; int duplicateBasicBlockCorrectionValue; int stateChangeWeight; int stateChangeCorrectionValue; int insertOpaquePredicateWeight; int seed; // Add debugging code into the obfuscated method (dump obfuscation graphs and so on) bool graphTransformerDebug = false; // Should the obfuscated code contain information to trace the control flow? bool basicBlockTrace = false; // When debugging is active, should the whole obfuscation graph be dumped or only the vpaths in it? bool graphOnlyDumpVPaths = true; // The number of random interfaces that are added to the program int numberRandomInterfaces = 100; if (args.Length != 14) { System.Console.WriteLine("Needed parameters: <inputBinary> <outputBinary> <namespace> <class> <method> <depth> <dimension> <numberValidPaths> <duplicateBasicBlockWeight> <duplicateBasicBlockCorrectionValue> <stateChangeWeight> <stateChangeCorrectionValue> <insertOpaquePredicateWeight> <seed>"); return; } else { inputFile = args[0]; targetFile = args[1]; targetNamespace = args[2]; targetClass = args[3]; targetMethod = args[4]; depth = Convert.ToInt32(args[5]); dimension = Convert.ToInt32(args[6]); numberValidPaths = Convert.ToInt32(args[7]); duplicateBasicBlockWeight = Convert.ToInt32(args[8]); duplicateBasicBlockCorrectionValue = Convert.ToInt32(args[9]); stateChangeWeight = Convert.ToInt32(args[10]); stateChangeCorrectionValue = Convert.ToInt32(args[11]); insertOpaquePredicateWeight = Convert.ToInt32(args[12]); seed = Convert.ToInt32(args[13]); } String logDir = Path.GetDirectoryName(targetFile); Log.Log logger = new Log.Log(logDir, "probfuscation_logfile.txt"); System.Console.WriteLine("Obfuscating: " + inputFile); logger.writeLine("Obfuscating: " + inputFile); System.Console.WriteLine("Output file: " + targetFile); logger.writeLine("Output file: " + targetFile); System.Console.WriteLine("Target namespace: " + targetNamespace); logger.writeLine("Target namespace: " + targetNamespace); System.Console.WriteLine("Target class: " + targetClass); logger.writeLine("Target class: " + targetClass); System.Console.WriteLine("Target method: " + targetMethod); logger.writeLine("Target method: " + targetMethod); System.Console.WriteLine("Depth: " + depth); logger.writeLine("Depth: " + depth); System.Console.WriteLine("Dimension: " + dimension); logger.writeLine("Dimension: " + dimension); System.Console.WriteLine("Number of vpaths: " + numberValidPaths); logger.writeLine("Number of vpaths: " + numberValidPaths); System.Console.WriteLine("Basic Block duplication weight: " + duplicateBasicBlockWeight); logger.writeLine("Basic Block duplication weight: " + duplicateBasicBlockWeight); System.Console.WriteLine("Basic Block duplication correction value: " + duplicateBasicBlockCorrectionValue); logger.writeLine("Basic Block duplication correction value: " + duplicateBasicBlockCorrectionValue); System.Console.WriteLine("State change weight: " + stateChangeWeight); logger.writeLine("State change weight: " + stateChangeWeight); System.Console.WriteLine("State change correction value: " + stateChangeCorrectionValue); logger.writeLine("State change correction value: " + stateChangeCorrectionValue); System.Console.WriteLine("Opaque predicate weight: " + insertOpaquePredicateWeight); logger.writeLine("Opaque predicate weight: " + insertOpaquePredicateWeight); System.Console.WriteLine("Seed: " + seed); logger.writeLine("Seed: " + seed); // Seed PRNG for interfaces PRNGRandomInterfaces = new Random(seed); using (var host = new PeReader.DefaultHost()) { IModule /*?*/ module = host.LoadUnitFrom(inputFile) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { Console.WriteLine(inputFile + " is not a PE file containing a CLR module or assembly."); return; } module = new MetadataDeepCopier(host).Copy(module); if (module as Assembly == null) { logger.writeLine("File does not have CIL assembly"); return; } // create analyzer object object CfgBuilder analyze = new Cfg.CfgBuilder(module, host, logger); PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { logger.writeLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { Microsoft.Cci.ILGenerator.LocalScopeProvider localScopeProvider = null; if (pdbReader != null) { localScopeProvider = new ILGenerator.LocalScopeProvider(pdbReader); } // search the namespace the interface should be added to IUnitNamespace foundNamespace = null; foreach (var tempMember in module.UnitNamespaceRoot.Members) { if ((tempMember as IUnitNamespace) == null) { continue; } IUnitNamespace tempNamespace = (tempMember as IUnitNamespace); if (tempNamespace.ToString() == targetNamespace) { foundNamespace = tempNamespace; break; } } if (foundNamespace == null) { throw new ArgumentException("Not able to find target namespace."); } // add created interface (and implemented methods) to all classes bool classFound = false; foreach (var tempClass in module.GetAllTypes()) { if ((tempClass as NamespaceTypeDefinition) == null || tempClass.IsAbstract) { continue; } NamespaceTypeDefinition foundClass = (tempClass as NamespaceTypeDefinition); if (foundClass.ContainingUnitNamespace.ToString() == "") { continue; } if (foundClass.ToString() != targetNamespace + "." + targetClass) { continue; } classFound = true; Random prng = new Random(); GraphTransformer graphTransformer = new GraphTransformer(module, host, logger, prng, foundNamespace, foundClass, depth, dimension, graphTransformerDebug); graphTransformer.duplicateBasicBlockWeight = duplicateBasicBlockWeight; graphTransformer.duplicateBasicBlockCorrectionValue = duplicateBasicBlockCorrectionValue; graphTransformer.stateChangeWeight = stateChangeWeight; graphTransformer.stateChangeCorrectionValue = stateChangeCorrectionValue; graphTransformer.insertOpaquePredicateWeight = insertOpaquePredicateWeight; graphTransformer.trace = basicBlockTrace; graphTransformer.graphOnlyDumpVPaths = graphOnlyDumpVPaths; graphTransformer.debuggingDumpLocation = logDir; // Add 100 random interfaces to the namespace Helper testHelper = new Helper(module, host, logger); List <NamespaceTypeDefinition> randomInterfaces = new List <NamespaceTypeDefinition>(); for (int i = 0; i < numberRandomInterfaces; i++) { String randName = randomString(20); NamespaceTypeDefinition temp = testHelper.createNewInterface(randName, foundNamespace); randomInterfaces.Add(temp); } InterfaceTransformer interfaceTransformer = new InterfaceTransformer(module, host, logger); foreach (var classToAdd in module.GetAllTypes()) { if ((classToAdd as NamespaceTypeDefinition) == null || classToAdd.IsAbstract || classToAdd.IsInterface || classToAdd.IsEnum || classToAdd.IsDelegate || classToAdd.IsGeneric || classToAdd.IsStruct) { continue; } if (((NamespaceTypeDefinition)classToAdd).ContainingUnitNamespace.ToString() == "") { continue; } /* * // Use this code if you want to add standard interfaces to the target class * interfaceTransformer.addStdInterfacesGivenByFile(@"e:\code\dotnet_standard_interfaces.txt"); * * // add std interfaces to class * if (foundClass != (classToAdd as NamespaceTypeDefinition)) { * foreach (ITypeDefinition temp in interfaceTransformer.getInterfacesList()) { * interfaceTransformer.addInterface((classToAdd as NamespaceTypeDefinition), temp); * } * } */ // Add random interfaces to the classes List <NamespaceTypeDefinition> alreadyAdded = new List <NamespaceTypeDefinition>(); int max = PRNGRandomInterfaces.Next(numberRandomInterfaces); NamespaceTypeDefinition interfaceClass = (classToAdd as NamespaceTypeDefinition); logger.writeLine("Adding " + max + " random interfaces to class \"" + interfaceClass.ToString() + "\""); for (int i = 0; i < max; i++) { NamespaceTypeDefinition randInterface = randomInterfaces.ElementAt(PRNGRandomInterfaces.Next(randomInterfaces.Count)); if (alreadyAdded.Contains(randInterface)) { continue; } alreadyAdded.Add(randInterface); logger.writeLine("Adding interface: \"" + randInterface.ToString() + "\""); // add nodes interface to class if (interfaceClass.Interfaces != null) { interfaceClass.Interfaces.Add(randInterface); } else { interfaceClass.Interfaces = new List <ITypeReference>(); interfaceClass.Interfaces.Add(randInterface); } } logger.writeLine(""); // Add special interface for the obfuscation scheme to the class // (makes sure that all needed attributes and methods are implemented) graphTransformer.addNodeInterfaceToTargetClass((classToAdd as NamespaceTypeDefinition)); } // Prepare obfuscation graph graphTransformer.generateGraph(numberValidPaths); graphTransformer.createGraphMethods(); // Search method to obfuscate MethodDefinition methodToObfu = null; foreach (MethodDefinition tempMethod in foundClass.Methods) { if (tempMethod.Name.ToString() == targetMethod) { methodToObfu = tempMethod; break; } } if (methodToObfu == null) { throw new ArgumentException("Not able to find target method."); } // Obfuscate target method MethodCfg cfg = analyze.buildCfgForMethod(methodToObfu); logger.dumpMethodCfg(cfg, "before"); graphTransformer.addObfuscationToMethod(cfg); analyze.createMethodFromCfg(cfg); logger.dumpMethodCfg(cfg, "after"); break; } if (!classFound) { throw new ArgumentException("Not able to find target class."); } /* * This code can be used if not only one specific method should be obfuscated, * but the whole class. * List<ClassCfg> classCfgList = new List<ClassCfg>(); * foreach (var tempClass in module.GetAllTypes()) { * if ((tempClass as NamespaceTypeDefinition) == null || tempClass.IsAbstract) { || continue; || } || || // create basic blocks || NamespaceTypeDefinition foundClass = (tempClass as NamespaceTypeDefinition); || || logger.writeLine("Create CFG for class \"" + foundClass.Name.ToString() + "\""); || ClassCfg temp = analyze.buildCfgForClass(foundClass); || classCfgList.Add(temp); || logger.writeLine("\n---------------------------------\n"); ||} || ||// transform each function ||NopTransformer transformator = new NopTransformer(module, host, logger); ||foreach (ClassCfg tempClassCfg in classCfgList) { || foreach (MethodCfg tempMethodCfg in tempClassCfg.methodCfgs) { || logger.writeLine("Transform method CFG of \"" + tempMethodCfg.method.ToString() + "\""); || transformator.addNopsToCfg(tempMethodCfg); || logger.writeLine("\n---------------------------------\n"); || } ||} || ||foreach (ClassCfg tempClassCfg in classCfgList) { || logger.writeLine("Create class from CFG for \"" + tempClassCfg.classObj.Name.ToString() + "\""); || analyze.createClassFromCfg(tempClassCfg); || logger.writeLine("\n---------------------------------\n"); ||} */ using (var peStream = File.Create(targetFile)) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(targetFile, ".pdb"), pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } } }
static int Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage: ILWeave [Assembly]"); return(1); } string tmpDir, newName, newPdb; using (var host = new PeReader.DefaultHost()) { var module = host.LoadUnitFrom(args[0]) as IModule; if (module == null || module is Dummy) { Console.WriteLine("{0} is not a PE file containing a CLR assembly, or an error occurred when loading it.", args[0]); return(1); } module = new MetadataDeepCopier(host).Copy(module); PdbReader pdbReader = null; var pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { Console.WriteLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { var localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader); module = PropertyChangedWeaver.RewriteModule( host, localScopeProvider, pdbReader, module); tmpDir = Directory.CreateDirectory(Path.GetRandomFileName()).FullName; newName = Path.Combine(tmpDir, Path.GetFileName(args[0])); using (var peStream = File.Create(newName)) { newPdb = Path.ChangeExtension(newName, ".pdb"); using (var pdbWriter = new PdbWriter(newPdb, pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } } var dst = Path.GetDirectoryName(args[0]); foreach (var s in Directory.GetFiles(tmpDir)) { File.Copy(s, Path.Combine(dst, Path.GetFileName(s)), true); } Directory.Delete(tmpDir, true); return(0); }
static void Main(string[] argv) { if (argv == null || argv.Length < 1) { Console.WriteLine("Usage: Main <assemblys> [<outputPath>]"); } using (var host = new PeReader.DefaultHost()) { var module = host.LoadUnitFrom(argv[0]) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new Exception(argv[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); } PdbReader pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else Console.WriteLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); using (pdbReader) { var copy = new MetadataDeepCopier(host).Copy(module); var shadowFieldsAddedAssembly = new ShadowFieldRewriter(host).Rewrite(copy); var shadowFieldsAndMethodsAddedAssembly = new ShadowMethodRewriter(host).Rewrite(shadowFieldsAddedAssembly); var rewrittenAssembly = new FinalizeMethodRewriter(host).Rewrite(shadowFieldsAndMethodsAddedAssembly); var main = rewrittenAssembly.EntryPoint.ResolvedMethod; if (main != Dummy.Method) { var body = main.Body as MethodBody; if (body != null) new AddGCWaitForFinalization(host, body).Rewrite(); } var validator = new MetadataValidator(host); validator.Validate(rewrittenAssembly as IAssembly); string outputPath = rewrittenAssembly.Location + ".meta"; var outputFileName = Path.GetFileNameWithoutExtension(outputPath); // Need to not pass in a local scope provider until such time as we have one that will use the mutator // to remap things (like the type of a scope constant) from the original assembly to the mutated one. using (var peStream = File.Create(outputPath)) { using (var pdbWriter = new PdbWriter(outputFileName + ".pdb", pdbReader)) { PeWriter.WritePeToStream(rewrittenAssembly, host, peStream, pdbReader, null, pdbWriter); } } } } }
public static void RunBclRewriter(string[] args) { #region Parse the command-line arguments. if (!Parser.ParseArgumentsWithUsage(args, typeof(Program))) throw new UsageException(); #endregion #region Figure out paths s_assemblyName = Path.GetFullPath(s_assemblyName); // this has to be specified string outputBaseName = null; if (!String.IsNullOrEmpty(s_output)) { s_output = Path.GetFullPath(s_output); outputBaseName = Path.GetFileNameWithoutExtension(s_output); } else { s_output = Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileNameWithoutExtension(s_assemblyName) + ".small" + Path.GetExtension(s_assemblyName)); outputBaseName = s_assemblyName; } string pdbSourceFile = Path.ChangeExtension(s_assemblyName, "pdb"); string outputPdb = Path.ChangeExtension(s_output, "pdb"); string outputFolder = Path.GetDirectoryName(s_output); // if the user wants to do an in-place rewrite, we copy the file to a temp file if (s_output == s_assemblyName) { String tempPath = s_assemblyName + TempExtension; String tempPdbPath = pdbSourceFile + TempExtension; File.Copy(s_assemblyName, tempPath, true); s_assemblyName = tempPath; if (File.Exists(pdbSourceFile)) { File.Copy(pdbSourceFile, tempPdbPath, true); pdbSourceFile = tempPdbPath; } } if (!Directory.Exists(outputFolder)) Directory.CreateDirectory(outputFolder); #endregion #region Load input files HostEnvironment host = new HostEnvironment(new NameTable(), s_assemblyDependencyPaths, s_referencedAssemblies); IAssembly/*?*/ assembly = host.LoadUnitFrom(s_assemblyName) as IAssembly; // TODO: Handle multimodule assemblies if (assembly == null || assembly == Dummy.Assembly) { throw new UsageException(args[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); } if (!File.Exists(s_includeListFile)) { throw new UsageException(String.Format("ERROR: Can't find code model file '{0}'", s_includeListFile)); } ThinModel model = new ThinModel(new ThinnerOptions(host, new AssemblyIdentity[] { assembly.AssemblyIdentity })); model.LoadModel(s_includeListFile, new ModelReaderOptions(s_platform, s_architecture, s_flavor, s_treatFxInternalAsPublic, s_defines)); #endregion #region Calculate api closure. ConsoleTimer.StartTimer("Calculating api closure"); model.LoadMetadataFrom(assembly); ThinModel apiClosure = model.CalculateApiClosure(); if (s_keepTempFiles) apiClosure.SaveModel(Path.ChangeExtension(s_output, ".apiClosure.xml")); ConsoleTimer.EndTimer("Calculating api closure"); #endregion #region Calculate impl closure. ConsoleTimer.StartTimer("Calculating implementation closure"); apiClosure.LoadMetadataFrom(assembly); ThinModel implClosure = apiClosure.CalculateImplementationClosure(true, FieldOptions.KeepAll); if (s_keepTempFiles) implClosure.SaveModel(Path.ChangeExtension(s_output, ".implClosure.xml")); ConsoleTimer.EndTimer("Calculating implementation closure"); #endregion #region Trim. ConsoleTimer.StartTimer("Trimming assembly"); IncludeSet includeSet = new IncludeSet(); includeSet.LoadFrom(implClosure); var copier = new MetadataDeepCopier(host); Assembly copiedAssembly = copier.Copy(assembly); Trimmer trimmer = new Trimmer(includeSet, true, false, true, host, s_removeSerializable); trimmer.RewriteChildren(copiedAssembly); Assembly mutableAssembly = copiedAssembly; assembly = mutableAssembly; ConsoleTimer.EndTimer("Trimming assembly"); #endregion #region Update assembly name. ConsoleTimer.StartTimer("Updating assembly name"); // If the output assembly name is different, update the internal assembly name to match. AssemblyIdentity originalAssemblyIdentity = mutableAssembly.AssemblyIdentity; if (!outputBaseName.Equals(originalAssemblyIdentity.Name.ToString(), StringComparison.OrdinalIgnoreCase)) { mutableAssembly.Name = host.NameTable.GetNameFor(outputBaseName); mutableAssembly.ModuleName = mutableAssembly.Name; } // If we changed the assembly identity, update references to it. if (!mutableAssembly.AssemblyIdentity.Equals(originalAssemblyIdentity)) { trimmer.UpdateAssemblyReferences(originalAssemblyIdentity, mutableAssembly.AssemblyIdentity); } ConsoleTimer.EndTimer("Updating assembly name"); #endregion #region Write out the assembly ConsoleTimer.StartTimer("Writing assembly"); PdbReader pdbReader = null; PdbWriter pdbWriter = null; if (File.Exists(pdbSourceFile)) { Stream pdbStream = File.OpenRead(pdbSourceFile); pdbReader = new PdbReader(pdbStream, host); pdbWriter = new PdbWriter(outputPdb, pdbReader); Console.WriteLine("Writing pdb: {0}", outputPdb); } Console.WriteLine("Writing assembly: {0}", s_output); FileStream file = File.Create(s_output); try { PeWriter.WritePeToStream(assembly, host, file, pdbReader, pdbReader, pdbWriter); } finally { if (file != null) { file.Dispose(); } if (pdbWriter != null) { pdbWriter.Dispose(); } } ConsoleTimer.EndTimer("Writing assembly"); #endregion }
/// <summary> /// A rewriter for CodeModel method bodies, which changes any anynomous delegate expressions found in the body into delegates over /// methods of either the containing type of the method, or of a nested type of that type. /// </summary> /// <param name="host">An object representing the application that is hosting the converter. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references.</param> /// <param name="sourceLocationProvider">An object that can map the ILocation objects found in a block of statements to IPrimarySourceLocation objects. May be null.</param> public AnonymousDelegateRemover(IMetadataHost host, ISourceLocationProvider/*?*/ sourceLocationProvider) : base(host) { this.copier = new MetadataDeepCopier(host); this.sourceLocationProvider = sourceLocationProvider; var compilerGeneratedCtor = this.GetReferenceToDefaultConstructor(host.PlatformType.SystemRuntimeCompilerServicesCompilerGeneratedAttribute); this.compilerGenerated = new CustomAttribute() { Constructor = compilerGeneratedCtor }; this.objectCtor = this.GetReferenceToDefaultConstructor(this.host.PlatformType.SystemObject); }
public static void Main(string[] args) { string seeds = null; string contracts = null; string facadePath = null; Version assemblyFileVersion = null; bool clearBuildAndRevision = false; bool ignoreMissingTypes = false; bool buildDesignTimeFacades = false; string inclusionContracts = null; ErrorTreatment seedLoadErrorTreatment = ErrorTreatment.Default; ErrorTreatment contractLoadErrorTreatment = ErrorTreatment.Default; string[] seedTypePreferencesUnsplit = null; bool forceZeroVersionSeeds = false; bool producePdb = true; string partialFacadeAssemblyPath = null; bool parsingSucceeded = CommandLineParser.ParseForConsoleApplication((parser) => { parser.DefineQualifier("facadePath", ref facadePath, "Path to output the facades."); parser.DefineQualifier("seeds", ref seeds, "Path to the seed assemblies. Can contain multiple assemblies or directories delimited by ',' or ';'."); parser.DefineQualifier("contracts", ref contracts, "Path to the contract assemblies. Can contain multiple assemblies or directories delimited by ',' or ';'."); parser.DefineOptionalQualifier("assemblyFileVersion", ref assemblyFileVersion, "Override the AssemblyFileVersion attribute from the contract with the given version for the generated facade."); parser.DefineOptionalQualifier("clearBuildAndRevision", ref clearBuildAndRevision, "Generate facade assembly version x.y.0.0 for contract version x.y.z.w"); parser.DefineOptionalQualifier("ignoreMissingTypes", ref ignoreMissingTypes, "Ignore types that cannot be found in the seed assemblies. This is not recommended but is sometimes helpful while hacking around or trying to produce partial facades."); parser.DefineOptionalQualifier("designTime", ref buildDesignTimeFacades, "Enable design-time facade generation (marks facades with reference assembly flag and attribute)."); parser.DefineOptionalQualifier("include", ref inclusionContracts, "Add types from these contracts to the facades. Can contain multiple assemblies or directories delimited by ',' or ';'."); parser.DefineOptionalQualifier("seedError", ref seedLoadErrorTreatment, "Error handling for seed assembly load failure."); parser.DefineOptionalQualifier("contractError", ref seedLoadErrorTreatment, "Error handling for contract assembly load failure."); parser.DefineOptionalQualifier("preferSeedType", ref seedTypePreferencesUnsplit, "Set which seed assembly to choose for a given type when it is defined in more than one assembly. Format: FullTypeName=PreferredSeedAssemblyName"); parser.DefineOptionalQualifier("forceZeroVersionSeeds", ref forceZeroVersionSeeds, "Forces all seed assembly versions to 0.0.0.0, regardless of their true version."); parser.DefineOptionalQualifier("partialFacadeAssemblyPath", ref partialFacadeAssemblyPath, "Specifies the path to a single partial facade assembly, into which appropriate type forwards will be added to satisfy the given contract. If this option is specified, only a single partial assembly and a single contract may be given."); parser.DefineOptionalQualifier("producePdb", ref producePdb, "Specifices if a PDB file should be produced for the resulting partial facade."); }, args); if (!parsingSucceeded) { return; } CommandLineTraceHandler.Enable(); if (!Directory.Exists(facadePath)) Directory.CreateDirectory(facadePath); var nameTable = new NameTable(); var internFactory = new InternFactory(); try { Dictionary<string, string> seedTypePreferences = ParseSeedTypePreferences(seedTypePreferencesUnsplit); using (var contractHost = new HostEnvironment(nameTable, internFactory)) using (var seedHost = new HostEnvironment(nameTable, internFactory)) { contractHost.LoadErrorTreatment = contractLoadErrorTreatment; seedHost.LoadErrorTreatment = seedLoadErrorTreatment; var contractAssemblies = LoadAssemblies(contractHost, contracts); IReadOnlyDictionary<string, IEnumerable<string>> docIdTable = GenerateDocIdTable(contractAssemblies, inclusionContracts); IAssembly[] seedAssemblies = LoadAssemblies(seedHost, seeds).ToArray(); IAssemblyReference seedCoreAssemblyRef = ((Microsoft.Cci.Immutable.PlatformType)seedHost.PlatformType).CoreAssemblyRef; if (forceZeroVersionSeeds) { // Create a deep copier, copy the seed assemblies, and zero out their versions. var copier = new MetadataDeepCopier(seedHost); for (int i = 0; i < seedAssemblies.Length; i++) { var mutableSeed = copier.Copy(seedAssemblies[i]); mutableSeed.Version = new Version(0, 0, 0, 0); // Copy the modified seed assembly back. seedAssemblies[i] = mutableSeed; if (mutableSeed.Name.UniqueKey == seedCoreAssemblyRef.Name.UniqueKey) { seedCoreAssemblyRef = mutableSeed; } } } var typeTable = GenerateTypeTable(seedAssemblies); var facadeGenerator = new FacadeGenerator(seedHost, contractHost, docIdTable, typeTable, seedTypePreferences, clearBuildAndRevision, buildDesignTimeFacades, assemblyFileVersion); if (partialFacadeAssemblyPath != null) { if (contractAssemblies.Count() != 1) { throw new FacadeGenerationException( "When partialFacadeAssemblyPath is specified, only exactly one corresponding contract assembly can be specified."); } IAssembly contractAssembly = contractAssemblies.First(); IAssembly partialFacadeAssembly = seedHost.LoadAssembly(partialFacadeAssemblyPath); if (contractAssembly.Name != partialFacadeAssembly.Name || contractAssembly.Version != partialFacadeAssembly.Version || contractAssembly.GetPublicKeyToken() != partialFacadeAssembly.GetPublicKeyToken()) { throw new FacadeGenerationException( string.Format("The partial facade assembly's name, version, and public key token must exactly match the contract to be filled. Contract: {0}, Facade: {1}", contractAssembly.AssemblyIdentity, partialFacadeAssembly.AssemblyIdentity)); } Assembly filledPartialFacade = facadeGenerator.GenerateFacade(contractAssembly, seedCoreAssemblyRef, ignoreMissingTypes, overrideContractAssembly: partialFacadeAssembly); string pdbLocation = null; if (producePdb) { string pdbFolder = Path.GetDirectoryName(partialFacadeAssemblyPath); pdbLocation = Path.Combine(pdbFolder, contractAssembly.Name + ".pdb"); if (producePdb && !File.Exists(pdbLocation)) { pdbLocation = null; Trace.TraceWarning("No PDB file present for un-transformed partial facade. No PDB will be generated."); } } OutputFacadeToFile(facadePath, seedHost, filledPartialFacade, contractAssembly, pdbLocation); } else { foreach (var contract in contractAssemblies) { Assembly facade = facadeGenerator.GenerateFacade(contract, seedCoreAssemblyRef, ignoreMissingTypes); if (facade == null) { #if !COREFX Debug.Assert(Environment.ExitCode != 0); #endif continue; } OutputFacadeToFile(facadePath, seedHost, facade, contract); } } } } catch (FacadeGenerationException ex) { Trace.TraceError(ex.Message); #if !COREFX Debug.Assert(Environment.ExitCode != 0); #endif } }
/// <summary> /// Amends the specified target assembly, optionally using assembly amendments defined in the /// specified amendment assemblies. /// </summary> /// <param name="targetAssembly"></param> /// <param name="amendmentAssemblies"></param> internal static void Amend(string targetAssembly, string[] amendmentAssemblies, string[] referenceAssemblies) { // Verify the target assembly exists targetAssembly = Path.GetFullPath(targetAssembly); if (!File.Exists(targetAssembly)) { throw new ArgumentException("The specified target assembly, " + targetAssembly + ", does not exist."); } // Verify the amendment assemblies exist if (amendmentAssemblies == null) { amendmentAssemblies = new string[0]; } for (int i = 0; i < amendmentAssemblies.Length; i++) { var path = amendmentAssemblies[i] = Path.GetFullPath(amendmentAssemblies[i]); if (!File.Exists(path)) { throw new ArgumentException("The specified amendment assembly, " + path + ", does not exist."); } } // Verify that the target has not already been amended var afterthoughtTracker = targetAssembly + ".afterthought"; if (File.Exists(afterthoughtTracker) && File.GetLastWriteTime(targetAssembly) == File.GetLastWriteTime(afterthoughtTracker)) { return; } // Determine the set of target directories and backup locations var targetWriteTime = File.GetLastWriteTime(targetAssembly); var backupTargetAssembly = targetAssembly + ".backup"; var targetDirectory = Path.GetDirectoryName(targetAssembly); File.Delete(backupTargetAssembly); File.Move(targetAssembly, backupTargetAssembly); // Build up a set of paths with resolving assemblies var referencePaths = new Dictionary <string, string>(); foreach (string path in amendmentAssemblies .Union(referenceAssemblies) .Union(Directory.GetFiles(targetDirectory).Where(p => p.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) && p != targetAssembly))) { referencePaths[Path.GetFileName(path)] = path; } // Register an assembly resolver to look in assembly directories when resolving assemblies AppDomain.CurrentDomain.AssemblyResolve += (s, e) => { var assemblyName = new System.Reflection.AssemblyName(e.Name).Name + ".dll"; string referencePath; if (referencePaths.TryGetValue(assemblyName, out referencePath)) { return(System.Reflection.Assembly.LoadFrom(referencePath)); } return(null); }; // Get the set of amendments to apply from all of the specified assemblies var assemblies = new System.Reflection.Assembly[] { System.Reflection.Assembly.LoadFrom(backupTargetAssembly) }.Union(amendmentAssemblies.Select(a => System.Reflection.Assembly.LoadFrom(a))); var amendments = AmendmentAttribute.GetAmendments(assemblies.First(), assemblies.Skip(1).ToArray()).ToList(); // Exit immediately if there are no amendments in the target assemblies //if (amendments.Count == 0) // return; // Amend the target assembly Console.Write("Amending " + Path.GetFileName(targetAssembly)); var start = DateTime.Now; using (var host = new PeReader.DefaultHost()) { // Load the target assembly IModule module = host.LoadUnitFrom(backupTargetAssembly) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new ArgumentException(backupTargetAssembly + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); } // Copy the assembly to enable it to be mutated module = new MetadataDeepCopier(host).Copy(module); // Load the debug file if it exists PdbReader pdbReader = null; var pdbFile = Path.Combine(targetDirectory, Path.GetFileNameWithoutExtension(targetAssembly) + ".pdb"); var backupPdbFile = pdbFile + ".backup"; if (File.Exists(pdbFile)) { File.Delete(backupPdbFile); File.Move(pdbFile, backupPdbFile); using (var pdbStream = File.OpenRead(backupPdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } // Amend and persist the target assembly using (pdbReader) { // Create and execute a new assembly amender AssemblyAmender amender = new AssemblyAmender(host, pdbReader, amendments, assemblies); amender.TargetRuntimeVersion = module.TargetRuntimeVersion; module = amender.Visit(module); // Save the amended assembly back to the original directory var localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader); using (var pdbWriter = pdbReader != null ? new PdbWriter(pdbFile, pdbReader) : null) { using (var dllStream = File.Create(targetAssembly)) { PeWriter.WritePeToStream(module, host, dllStream, pdbReader, localScopeProvider, pdbWriter); } } } File.SetLastWriteTime(targetAssembly, targetWriteTime); if (pdbReader != null) { File.SetLastWriteTime(pdbFile, targetWriteTime); } } Console.WriteLine(" (" + DateTime.Now.Subtract(start).TotalSeconds.ToString("0.000") + " seconds)"); // Set the last write time of the afterthought tracker to match the amended assembly to prevent accidental reamending File.WriteAllText(afterthoughtTracker, ""); File.SetLastWriteTime(afterthoughtTracker, File.GetLastWriteTime(targetAssembly)); }
static void Main(string[] args) { //String inputFile = @"c:\Users\typ\Documents\Visual Studio 2013\Projects\vererbung\vererbung\bin\Debug\vererbung.exe"; String inputFile = @"e:\dile_v0_2_12_x86\Dile.exe"; globalLog = new Log(@"e:\merge_logfile.txt"); System.Console.WriteLine(inputFile); /* if (args == null || args.Length == 0) { Console.WriteLine("Usage: ILMutator <assembly> [<outputPath>]"); return; } */ using (var host = new PeReader.DefaultHost()) { //IModule/*?*/ module = host.LoadUnitFrom(args[0]) as IModule; IModule/*?*/ module = host.LoadUnitFrom(inputFile) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { //Console.WriteLine(args[0] + " is not a PE file containing a CLR module or assembly."); Console.WriteLine(inputFile + " is not a PE file containing a CLR module or assembly."); return; } module = new MetadataDeepCopier(host).Copy(module); if (module as Assembly == null) { globalLog.writeLine("File does not have CIL assembly"); return; } PdbReader/*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { globalLog.writeLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { Microsoft.Cci.ILGenerator.LocalScopeProvider localScopeProvider = null; if (pdbReader != null) { localScopeProvider = new ILGenerator.LocalScopeProvider(pdbReader); } // AB HIER DER INTERESSANTE PART ZUM MERGEN, DAVOR NUR INIT CRAP // search for class in namespace NamespaceTypeDefinition foundClass = null; foreach (var asdf in module.GetAllTypes()) { //if (asdf.ToString() == "vererbung.Erber") { if (asdf.ToString() == "Dile.Disassemble.Assembly") { foundClass = (asdf as NamespaceTypeDefinition); break; } } if (foundClass == null) { globalLog.writeLine("Class not found!"); return; } // merge class globalLog.writeLine("Merge class \"" + foundClass.ToString() + "\" with all ancestors"); mergeClassWithAllAncestors(foundClass, host); string newName; if (args.Length == 2) { newName = args[1]; //newName = @"e:\dile_v0_2_12_x86\dile_classes.exe"; newName = @"e:\test.exe"; } else { var loc = module.Location; var path = Path.GetDirectoryName(loc) ?? ""; var fileName = Path.GetFileNameWithoutExtension(loc); var ext = Path.GetExtension(loc); newName = Path.Combine(path, fileName + "1" + ext); //newName = @"e:\dile_v0_2_12_x86\dile_classes.exe"; newName = @"e:\test.exe"; } using (var peStream = File.Create(newName)) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(newName, ".pdb"), pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } } }
internal int Run() { SecurityKeepOptions securityKeepOptions = options.onlySecurityTransparent ? SecurityKeepOptions.OnlyNonCritical : SecurityKeepOptions.All; if (options.doBreak) { System.Diagnostics.Debugger.Launch(); } string assemblyName = null; if (options.GeneralArguments.Count == 1) { assemblyName = options.GeneralArguments[0]; } if (assemblyName == null) { errorLogger("Must specify an input file."); return(1); } using (var host = new AsmMetaHostEnvironment(options.libPaths.ToArray(), options.searchGAC)) { foreach (var p in options.resolvedPaths) { host.AddResolvedPath(p); } IAssembly /*?*/ assembly = host.LoadUnitFrom(assemblyName) as IAssembly; if (assembly == null || assembly is Dummy) { errorLogger(assemblyName + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); return(1); } var rewrittenAttribute = CreateTypeReference(host, assembly, "System.Diagnostics.Contracts.RuntimeContractsAttribute"); if (AttributeHelper.Contains(assembly.Attributes, rewrittenAttribute)) { errorLogger(assemblyName + " is already rewritten, cannot generate a reference assembly from it."); return(1); } if (options.backwardCompatibility) { // redundant because RemoveMethodBodies.ctor also does this when the flag is set options.whatToEmit = KeepOptions.ExtVis; options.emitAttributes = false; } PdbReader /*?*/ pdbReader = null; if (options.includeSourceTextInContract) { // No point getting the PDB file unless we want to use it for source text string pdbFile = Path.ChangeExtension(assembly.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { errorLogger("Could not load the PDB file for the assembly '" + assembly.Name.Value + "' . Source text will not be preserved in the reference assembly. Proceeding anyway."); } } using (pdbReader) { // We might be working on the assembly that defines the contract class and/or the type System.Void. // (Or any other platform type!) // But the host.PlatformType object has not been duplicated, so its properties will continue to be references to the immutable ones. // This is OK, except if the assembly is being renamed. this.compilerGeneratedAttributeType = host.PlatformType.SystemRuntimeCompilerServicesCompilerGeneratedAttribute; this.contractClassType = host.PlatformType.SystemDiagnosticsContractsContract; this.systemAttributeType = host.PlatformType.SystemAttribute; this.systemBooleanType = host.PlatformType.SystemBoolean; this.systemStringType = host.PlatformType.SystemString; this.systemObjectType = host.PlatformType.SystemObject; this.systemVoidType = host.PlatformType.SystemVoid; //new FindPlatformTypes(this).Traverse(assembly); //update the above fields if any of those types are defined in mutable Assembly mutable = new MetadataDeepCopier(host).Copy(assembly); #region Rename the assembly in a separate pass because things done in later passes depend on interned keys that are computed based (in part) on the assembly identity if (options.rename) { if (options.output != null) { mutable.Name = host.NameTable.GetNameFor(Path.GetFileNameWithoutExtension(options.output)); } else { mutable.Name = host.NameTable.GetNameFor(assembly.Name.Value + ".Contracts"); } mutable.ModuleName = mutable.Name; mutable.Kind = ModuleKind.DynamicallyLinkedLibrary; mutable = (Assembly)RenameAssembly.ReparentAssemblyIdentity(host, assembly.AssemblyIdentity, mutable.AssemblyIdentity, mutable); } #endregion Rename the assembly in a separate pass because things done in later passes depend on interned keys that are computed based (in part) on the assembly identity if (!options.renameOnly) { if (options.contracts) { if (options.rename) { // We might be working on the assembly that defines the contract class and/or the type System.Void. // (Or any other platform type!) // But the host.PlatformType object has not been duplicated, so its properties will continue to be references to the immutable ones. // This is OK, except if the assembly is being renamed. var systemNamespace = GetFirstMatchingNamespace(host, mutable.UnitNamespaceRoot, "System"); if (systemNamespace != null) { var typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Attribute"); if (typeDefinition != null) { this.systemAttributeType = typeDefinition; } typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Boolean"); if (typeDefinition != null) { this.systemBooleanType = typeDefinition; } typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Object"); if (typeDefinition != null) { this.systemObjectType = typeDefinition; } typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "String"); if (typeDefinition != null) { this.systemStringType = typeDefinition; } typeDefinition = GetFirstMatchingTypeDefinition(host, systemNamespace, "Void"); if (typeDefinition != null) { this.systemVoidType = typeDefinition; } var systemRuntimeNamespace = GetFirstMatchingNamespace(host, systemNamespace, "Runtime"); if (systemRuntimeNamespace != null) { var systemRuntimeCompilerServicesNamespace = GetFirstMatchingNamespace(host, systemRuntimeNamespace, "CompilerServices"); if (systemRuntimeCompilerServicesNamespace != null) { typeDefinition = GetFirstMatchingTypeDefinition(host, systemRuntimeCompilerServicesNamespace, "CompilerGeneratedAttribute"); if (typeDefinition != null) { this.compilerGeneratedAttributeType = typeDefinition; } } } var systemDiagnosticsNamespace = GetFirstMatchingNamespace(host, systemNamespace, "Diagnostics"); if (systemDiagnosticsNamespace != null) { var systemDiagnosticsContractsNamespace = GetFirstMatchingNamespace(host, systemDiagnosticsNamespace, "Contracts"); if (systemDiagnosticsContractsNamespace != null) { typeDefinition = GetFirstMatchingTypeDefinition(host, systemDiagnosticsContractsNamespace, "Contract"); if (typeDefinition != null) { this.contractClassType = typeDefinition; } } } } } mutable = AsmMetaRewriter.RewriteModule(host, pdbReader, mutable, contractClassType, compilerGeneratedAttributeType, systemAttributeType, systemBooleanType, systemObjectType, systemStringType, systemVoidType ) as Assembly; } #region Delete things that are not to be kept if (options.backwardCompatibility || options.whatToEmit != KeepOptions.All || !options.emitAttributes || (options.attrs != null && 0 < options.attrs.Count)) { DeleteThings thinner = new DeleteThings(host, options.whatToEmit, securityKeepOptions, options.emitAttributes, options.attrs.ToArray(), options.backwardCompatibility); if (securityKeepOptions == SecurityKeepOptions.OnlyNonCritical && host.platformType.SystemSecuritySecurityCriticalAttribute.ResolvedType is Dummy) { errorLogger("You asked to remove security critical methods, but the version of mscorlib doesn't support the SecurityCriticalAttribute."); return(1); } thinner.RewriteChildren(mutable); #region Fix up dangling references to things that were deleted FixUpReferences patcher = new FixUpReferences(host, thinner.WhackedMethods, thinner.WhackedTypes); patcher.RewriteChildren(mutable); #endregion Fix up dangling references to things that were deleted } #endregion Delete things that are not to be kept #region Output is always a dll, so mark the assembly as that mutable.EntryPoint = Dummy.MethodReference; mutable.Kind = ModuleKind.DynamicallyLinkedLibrary; #endregion Output is always a dll, so mark the assembly as that } assembly = mutable; string outputPath; if (options.output != null) // user specified, they'd better make sure it doesn't conflict with anything { outputPath = options.output; } else if (options.rename) // A.dll ==> A.Contracts.dll (Always! Even if the input is an exe!) { outputPath = assembly.Name.Value + ".dll"; } else // A.dll ==> A.dll.meta { outputPath = assembly.Name.Value + Path.GetExtension(assemblyName) + ".meta"; } // NB: Do *not* pass a pdbWriter to WritePeToStream. No need to create a PDB file and if // it is provided, then it might find things (like constants in a scope) that don't get // visited and so don't have any type references modified as they should be. using (var outputFile = File.Create(outputPath)) { if (pdbReader != null && options.writePDB) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(outputPath, "pdb"), pdbReader)) { // Need to not pass in a local scope provider until such time as we have one that will use the mutator // to remap things (like the type of a scope constant) from the original assembly to the mutated one. PeWriter.WritePeToStream(assembly, host, outputFile, pdbReader, null /*pdbReader*/, pdbWriter); } } else { PeWriter.WritePeToStream(assembly, host, outputFile); } } } } return(0); // success }
public static void Main(string[] args) { string seeds = null; string contracts = null; string facadePath = null; Version assemblyFileVersion = null; bool clearBuildAndRevision = false; bool ignoreMissingTypes = false; bool ignoreBuildAndRevisionMismatch = false; bool buildDesignTimeFacades = false; string inclusionContracts = null; ErrorTreatment seedLoadErrorTreatment = ErrorTreatment.Default; ErrorTreatment contractLoadErrorTreatment = ErrorTreatment.Default; string[] seedTypePreferencesUnsplit = null; bool forceZeroVersionSeeds = false; bool producePdb = true; string partialFacadeAssemblyPath = null; bool parsingSucceeded = CommandLineParser.ParseForConsoleApplication((parser) => { parser.DefineQualifier("facadePath", ref facadePath, "Path to output the facades."); parser.DefineQualifier("seeds", ref seeds, "Path to the seed assemblies. Can contain multiple assemblies or directories delimited by ',' or ';'."); parser.DefineQualifier("contracts", ref contracts, "Path to the contract assemblies. Can contain multiple assemblies or directories delimited by ',' or ';'."); parser.DefineOptionalQualifier("assemblyFileVersion", ref assemblyFileVersion, "Override the AssemblyFileVersion attribute from the contract with the given version for the generated facade."); parser.DefineOptionalQualifier("clearBuildAndRevision", ref clearBuildAndRevision, "Generate facade assembly version x.y.0.0 for contract version x.y.z.w"); parser.DefineOptionalQualifier("ignoreBuildAndRevisionMismatch", ref ignoreBuildAndRevisionMismatch, "Ignore a mismatch in revision and build for partial facade."); parser.DefineOptionalQualifier("ignoreMissingTypes", ref ignoreMissingTypes, "Ignore types that cannot be found in the seed assemblies. This is not recommended but is sometimes helpful while hacking around or trying to produce partial facades."); parser.DefineOptionalQualifier("designTime", ref buildDesignTimeFacades, "Enable design-time facade generation (marks facades with reference assembly flag and attribute)."); parser.DefineOptionalQualifier("include", ref inclusionContracts, "Add types from these contracts to the facades. Can contain multiple assemblies or directories delimited by ',' or ';'."); parser.DefineOptionalQualifier("seedError", ref seedLoadErrorTreatment, "Error handling for seed assembly load failure."); parser.DefineOptionalQualifier("contractError", ref seedLoadErrorTreatment, "Error handling for contract assembly load failure."); parser.DefineOptionalQualifier("preferSeedType", ref seedTypePreferencesUnsplit, "Set which seed assembly to choose for a given type when it is defined in more than one assembly. Format: FullTypeName=PreferredSeedAssemblyName"); parser.DefineOptionalQualifier("forceZeroVersionSeeds", ref forceZeroVersionSeeds, "Forces all seed assembly versions to 0.0.0.0, regardless of their true version."); parser.DefineOptionalQualifier("partialFacadeAssemblyPath", ref partialFacadeAssemblyPath, "Specifies the path to a single partial facade assembly, into which appropriate type forwards will be added to satisfy the given contract. If this option is specified, only a single partial assembly and a single contract may be given."); parser.DefineOptionalQualifier("producePdb", ref producePdb, "Specifices if a PDB file should be produced for the resulting partial facade."); }, args); if (!parsingSucceeded) { return; } CommandLineTraceHandler.Enable(); if (!Directory.Exists(facadePath)) { Directory.CreateDirectory(facadePath); } var nameTable = new NameTable(); var internFactory = new InternFactory(); try { Dictionary <string, string> seedTypePreferences = ParseSeedTypePreferences(seedTypePreferencesUnsplit); using (var contractHost = new HostEnvironment(nameTable, internFactory)) using (var seedHost = new HostEnvironment(nameTable, internFactory)) { contractHost.LoadErrorTreatment = contractLoadErrorTreatment; seedHost.LoadErrorTreatment = seedLoadErrorTreatment; var contractAssemblies = LoadAssemblies(contractHost, contracts); IReadOnlyDictionary <string, IEnumerable <string> > docIdTable = GenerateDocIdTable(contractAssemblies, inclusionContracts); IAssembly[] seedAssemblies = LoadAssemblies(seedHost, seeds).ToArray(); IAssemblyReference seedCoreAssemblyRef = ((Microsoft.Cci.Immutable.PlatformType)seedHost.PlatformType).CoreAssemblyRef; if (forceZeroVersionSeeds) { // Create a deep copier, copy the seed assemblies, and zero out their versions. var copier = new MetadataDeepCopier(seedHost); for (int i = 0; i < seedAssemblies.Length; i++) { var mutableSeed = copier.Copy(seedAssemblies[i]); mutableSeed.Version = new Version(0, 0, 0, 0); // Copy the modified seed assembly back. seedAssemblies[i] = mutableSeed; if (mutableSeed.Name.UniqueKey == seedCoreAssemblyRef.Name.UniqueKey) { seedCoreAssemblyRef = mutableSeed; } } } var typeTable = GenerateTypeTable(seedAssemblies); var facadeGenerator = new FacadeGenerator(seedHost, contractHost, docIdTable, typeTable, seedTypePreferences, clearBuildAndRevision, buildDesignTimeFacades, assemblyFileVersion); if (partialFacadeAssemblyPath != null) { if (contractAssemblies.Count() != 1) { throw new FacadeGenerationException( "When partialFacadeAssemblyPath is specified, only exactly one corresponding contract assembly can be specified."); } IAssembly contractAssembly = contractAssemblies.First(); IAssembly partialFacadeAssembly = seedHost.LoadAssembly(partialFacadeAssemblyPath); if (contractAssembly.Name != partialFacadeAssembly.Name || contractAssembly.Version.Major != partialFacadeAssembly.Version.Major || contractAssembly.Version.Minor != partialFacadeAssembly.Version.Minor || (!ignoreBuildAndRevisionMismatch && contractAssembly.Version.Build != partialFacadeAssembly.Version.Build) || (!ignoreBuildAndRevisionMismatch && contractAssembly.Version.Revision != partialFacadeAssembly.Version.Revision) || contractAssembly.GetPublicKeyToken() != partialFacadeAssembly.GetPublicKeyToken()) { throw new FacadeGenerationException( string.Format("The partial facade assembly's name, version, and public key token must exactly match the contract to be filled. Contract: {0}, Facade: {1}", contractAssembly.AssemblyIdentity, partialFacadeAssembly.AssemblyIdentity)); } Assembly filledPartialFacade = facadeGenerator.GenerateFacade(contractAssembly, seedCoreAssemblyRef, ignoreMissingTypes, overrideContractAssembly: partialFacadeAssembly); string pdbLocation = null; if (producePdb) { string pdbFolder = Path.GetDirectoryName(partialFacadeAssemblyPath); pdbLocation = Path.Combine(pdbFolder, contractAssembly.Name + ".pdb"); if (producePdb && !File.Exists(pdbLocation)) { pdbLocation = null; Trace.TraceWarning("No PDB file present for un-transformed partial facade. No PDB will be generated."); } } OutputFacadeToFile(facadePath, seedHost, filledPartialFacade, contractAssembly, pdbLocation); } else { foreach (var contract in contractAssemblies) { Assembly facade = facadeGenerator.GenerateFacade(contract, seedCoreAssemblyRef, ignoreMissingTypes); if (facade == null) { #if !COREFX Debug.Assert(Environment.ExitCode != 0); #endif continue; } OutputFacadeToFile(facadePath, seedHost, facade, contract); } } } } catch (FacadeGenerationException ex) { Trace.TraceError(ex.Message); #if !COREFX Debug.Assert(Environment.ExitCode != 0); #endif } }
static int RealMain(string[] args) { int errorReturnValue = -1; #region Check options ILMerge.options = new ILMergeOptions(); options.Parse(args); if (options.HelpRequested) { options.PrintOptions(""); return(errorReturnValue); } if (options.HasErrors) { options.PrintErrorsAndExit(Console.Out); } if (options.breakIntoDebugger) { System.Diagnostics.Debugger.Break(); } #endregion Version version = null; if (options.version != null) { TryGetVersionNumber(options.version, out version); } using (var host = new ILMergeHost(options.libpaths)) { if (options.libpaths != null) { foreach (var libpath in options.libpaths) { host.AddLibPath(libpath); } } Assembly /*?*/ primaryAssembly = null; var modules = new List <Module>(); var unit2SourceLocationProviderMap = new Dictionary <IUnit, ISourceLocationProvider>(); var unit2LocalScopeProviderMap = new Dictionary <IUnit, ILocalScopeProvider>(); try { for (int i = 0; i < options.GeneralArguments.Count; i++) { var unitName = options.GeneralArguments[i]; var u = host.LoadUnitFrom(unitName) as IModule; if (i == 0) { IAssembly /*?*/ assembly = u as IAssembly; if (assembly == null || assembly is Dummy) { Console.WriteLine(unitName + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); return(errorReturnValue); } // Use (the copy of) the first input assembly as the merged assembly! primaryAssembly = new MetadataDeepCopier(host).Copy(assembly); } else { var copier = new MetadataDeepCopier(host, primaryAssembly); var mutableModule = copier.Copy(u); modules.Add(mutableModule); } PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(u.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } unit2SourceLocationProviderMap.Add(u, pdbReader); unit2LocalScopeProviderMap.Add(u, pdbReader); } else { Console.WriteLine("Could not load the PDB file for the unit '" + u.Name.Value + "' . Proceeding anyway."); unit2SourceLocationProviderMap.Add(u, null); } } //PdbWriter/*?*/ pdbWriter = null; RewriteUnitReferences renamer = new RewriteUnitReferences(host, modules, options); renamer.targetAssembly = primaryAssembly; renamer.originalAssemblyIdentity = primaryAssembly.AssemblyIdentity; int totalNumberOfTypes = primaryAssembly.AllTypes.Count; #region Pass 1: Mutate each input module (including the primary assembly) so everything is re-parented to the merged assembly renamer.RewriteChildren(primaryAssembly); for (int i = 0, n = modules.Count; i < n; i++) { var mutableModule = modules[i]; // call Rewrite and not RewriteChildren so dynamic dispatch can call the right rewriter method // otherwise, it just rewrites it as a module, not whatever subtype it is. renamer.Rewrite(mutableModule); // However, the rewriter does *not* rewrite parents. So need to re-parent the root unit namespace // of the mutable assembly so it points to the merged assembly. Otherwise, interning (among other // things) will not work correctly. var rootUnitNs = (RootUnitNamespace)mutableModule.UnitNamespaceRoot; rootUnitNs.Unit = primaryAssembly; totalNumberOfTypes += mutableModule.AllTypes.Count; } #endregion #region Pass 2: Collect all of the types into the merged assembly var mergedTypes = new List <INamedTypeDefinition>(totalNumberOfTypes); #region Merge together all of the <Module> classes from the input assemblies // TODO: Merge all of the <Module> classes, i.e., type 0 from each of the input assemblies mergedTypes.Add(primaryAssembly.AllTypes[0]); #endregion var internedKeys = new HashSet <string>(); // keep track of all namespace type definitions #region Types from the primary assembly for (int i = 1, n = primaryAssembly.AllTypes.Count; i < n; i++) { var t = primaryAssembly.AllTypes[i]; mergedTypes.Add(t); if (t is INamespaceTypeDefinition) // don't care about nested types { var key = TypeHelper.GetTypeName(t, NameFormattingOptions.None); internedKeys.Add(key); } } #endregion #region Types from the other input assemblies, taking care of duplicates for (int i = 0, n = modules.Count; i < n; i++) { var module = modules[i]; var unitName = module.Name.Value; for (int j = 1, m = module.AllTypes.Count; j < m; j++) { var t = module.AllTypes[j]; var namespaceTypeDefinition = t as NamespaceTypeDefinition; // duplicates can be only at the top-level: namespace type definitions // if a namespace type definition is unique, then so are all of its nested types if (namespaceTypeDefinition != null) { var typeName = TypeHelper.GetTypeName(namespaceTypeDefinition, NameFormattingOptions.UseGenericTypeNameSuffix); if (internedKeys.Contains(typeName)) // error: duplicate! { if (!namespaceTypeDefinition.IsPublic || options.allowDup) { var newName = String.Format("{0}_from_{1}", namespaceTypeDefinition.Name.Value, unitName); namespaceTypeDefinition.Name = host.NameTable.GetNameFor(newName); var newTypeName = TypeHelper.GetTypeName(namespaceTypeDefinition, NameFormattingOptions.UseGenericTypeNameSuffix); Console.WriteLine("Adding '{0}' as '{1}'", typeName, newTypeName); internedKeys.Add(typeName); t = namespaceTypeDefinition; } else { Console.WriteLine("Error: Duplicate type '{0}'", typeName); continue; //TODO: set a flag somewhere to force a failure. } } else { //Console.WriteLine("Adding '{0}'", typeName); internedKeys.Add(typeName); } } mergedTypes.Add(t); } } #endregion primaryAssembly.AllTypes = mergedTypes; #endregion CopyResourcesToPrimaryAssembly(primaryAssembly, modules); if (version != null) { primaryAssembly.Version = version; } string outputPath; if (options.output != null) { outputPath = options.output; } else { outputPath = primaryAssembly.Name.Value + Path.GetExtension(options.GeneralArguments[0]) + ".meta"; } using (var aggregateSourceLocationProvider = new AggregatingSourceLocationProvider(unit2SourceLocationProviderMap)) { using (var aggregateLocalScopeProvider = new AggregatingLocalScopeProvider(unit2LocalScopeProviderMap)) { using (var peStream = File.Create(outputPath)) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(outputPath, "pdb"), aggregateSourceLocationProvider)) { PeWriter.WritePeToStream(primaryAssembly, host, peStream, aggregateSourceLocationProvider, aggregateLocalScopeProvider, pdbWriter); } } } } } finally { } return(0); // success } }
static int Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage: ILWeave [Assembly]"); return 1; } string tmpDir, newName, newPdb; using (var host = new PeReader.DefaultHost()) { var module = host.LoadUnitFrom(args[0]) as IModule; if (module == null || module is Dummy) { Console.WriteLine("{0} is not a PE file containing a CLR assembly, or an error occurred when loading it.", args[0]); return 1; } module = new MetadataDeepCopier(host).Copy(module); PdbReader pdbReader = null; var pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { Console.WriteLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { var localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader); try { module = PropertyChangedWeaver.RewriteModule( host, localScopeProvider, pdbReader, module); } catch (InvalidOperationException e) { Console.WriteLine("Error: {0}", e); Environment.Exit(5); } tmpDir = Directory.CreateDirectory(Path.GetRandomFileName()).FullName; newName = Path.Combine(tmpDir, Path.GetFileName(args[0])); using (var peStream = File.Create(newName)) { newPdb = Path.ChangeExtension(newName, ".pdb"); using (var pdbWriter = new PdbWriter(newPdb, pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } } var dst = Path.GetDirectoryName(args[0]); foreach (var s in Directory.GetFiles(tmpDir)) { File.Copy(s, Path.Combine(dst, Path.GetFileName(s)), true); } Directory.Delete(tmpDir, true); return 0; }
static void Main(string[] args) { //String inputFile = @"c:\Users\typ\Documents\Visual Studio 2013\Projects\vererbung\vererbung\bin\Debug\vererbung.exe"; String inputFile = @"e:\dile_v0_2_12_x86\Dile.exe"; globalLog = new Log(@"e:\merge_logfile.txt"); System.Console.WriteLine(inputFile); /* * if (args == null || args.Length == 0) * { * Console.WriteLine("Usage: ILMutator <assembly> [<outputPath>]"); * return; * } */ using (var host = new PeReader.DefaultHost()) { //IModule/*?*/ module = host.LoadUnitFrom(args[0]) as IModule; IModule /*?*/ module = host.LoadUnitFrom(inputFile) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { //Console.WriteLine(args[0] + " is not a PE file containing a CLR module or assembly."); Console.WriteLine(inputFile + " is not a PE file containing a CLR module or assembly."); return; } module = new MetadataDeepCopier(host).Copy(module); if (module as Assembly == null) { globalLog.writeLine("File does not have CIL assembly"); return; } PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { globalLog.writeLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { Microsoft.Cci.ILGenerator.LocalScopeProvider localScopeProvider = null; if (pdbReader != null) { localScopeProvider = new ILGenerator.LocalScopeProvider(pdbReader); } // AB HIER DER INTERESSANTE PART ZUM MERGEN, DAVOR NUR INIT CRAP // search for class in namespace NamespaceTypeDefinition foundClass = null; foreach (var asdf in module.GetAllTypes()) { //if (asdf.ToString() == "vererbung.Erber") { if (asdf.ToString() == "Dile.Disassemble.Assembly") { foundClass = (asdf as NamespaceTypeDefinition); break; } } if (foundClass == null) { globalLog.writeLine("Class not found!"); return; } // merge class globalLog.writeLine("Merge class \"" + foundClass.ToString() + "\" with all ancestors"); mergeClassWithAllAncestors(foundClass, host); string newName; if (args.Length == 2) { newName = args[1]; //newName = @"e:\dile_v0_2_12_x86\dile_classes.exe"; newName = @"e:\test.exe"; } else { var loc = module.Location; var path = Path.GetDirectoryName(loc) ?? ""; var fileName = Path.GetFileNameWithoutExtension(loc); var ext = Path.GetExtension(loc); newName = Path.Combine(path, fileName + "1" + ext); //newName = @"e:\dile_v0_2_12_x86\dile_classes.exe"; newName = @"e:\test.exe"; } using (var peStream = File.Create(newName)) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(newName, ".pdb"), pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } } }