public static string DecompileCSharp(string assemblyFileName, DecompilerSettings settings = null) { if (settings == null) { settings = new DecompilerSettings(); } using (var file = new FileStream(assemblyFileName, FileMode.Open, FileAccess.Read)) { var module = new PEFile(assemblyFileName, file, PEStreamOptions.PrefetchEntireImage); var resolver = new UniversalAssemblyResolver(assemblyFileName, false, module.Reader.DetectTargetFrameworkId(), PEStreamOptions.PrefetchMetadata); resolver.AddSearchDirectory(Path.GetDirectoryName(typeof(Span <>).Assembly.Location)); var typeSystem = new DecompilerTypeSystem(module, resolver, settings); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, settings); decompiler.AstTransforms.Insert(0, new RemoveEmbeddedAttributes()); decompiler.AstTransforms.Insert(0, new RemoveCompilerAttribute()); decompiler.AstTransforms.Insert(0, new RemoveNamespaceMy()); decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()); var syntaxTree = decompiler.DecompileWholeModuleAsSingleFile(sortTypes: true); StringWriter output = new StringWriter(); var visitor = new CSharpOutputVisitor(output, FormattingOptionsFactory.CreateSharpDevelop()); syntaxTree.AcceptVisitor(visitor); string fileName = Path.GetTempFileName(); File.WriteAllText(fileName, output.ToString()); return(fileName); } }
public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { var module = assembly.GetModuleDefinitionAsync().Result; if (options.FullDecompilation && options.SaveAsProjectDirectory != null) { var decompiler = new ILSpyWholeProjectDecompiler(assembly, options); decompiler.ProjectGuid = App.CommandLineArguments.FixedGuid; decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken); } else { AddReferenceWarningMessage(module.Assembly, output); output.WriteLine(); base.DecompileAssembly(assembly, output, options); ModuleDefinition mainModule = module; if (mainModule.Types.Count > 0) { output.Write("// Global type: "); output.WriteReference(mainModule.Types[0].FullName, mainModule.Types[0]); output.WriteLine(); } if (mainModule.EntryPoint != null) { output.Write("// Entry point: "); output.WriteReference(mainModule.EntryPoint.DeclaringType.FullName + "." + mainModule.EntryPoint.Name, mainModule.EntryPoint); output.WriteLine(); } output.WriteLine("// Architecture: " + GetPlatformDisplayName(mainModule)); if ((mainModule.Attributes & ModuleAttributes.ILOnly) == 0) { output.WriteLine("// This assembly contains unmanaged code."); } string runtimeName = GetRuntimeDisplayName(mainModule); if (runtimeName != null) { output.WriteLine("// Runtime: " + runtimeName); } output.WriteLine(); // don't automatically load additional assemblies when an assembly node is selected in the tree view using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad()) { CSharpDecompiler decompiler = new CSharpDecompiler(module, options.DecompilerSettings); decompiler.CancellationToken = options.CancellationToken; SyntaxTree st; if (options.FullDecompilation) { st = decompiler.DecompileWholeModuleAsSingleFile(); } else { st = decompiler.DecompileModuleAndAssemblyAttributes(); } WriteCode(output, options.DecompilerSettings, st, decompiler.TypeSystem); } } }
public string GenerateCSharp() { string dllPath = $"./fordebug.dll"; var generator = new AssemblyGenerator(); generator.GenerateAssembly(Builder, dllPath); CSharpDecompiler decompiler = new CSharpDecompiler(dllPath, new ICSharpCode.Decompiler.DecompilerSettings()); var syntaxTree = decompiler.DecompileWholeModuleAsSingleFile(); StringWriter output = new StringWriter(); var visitor = new CSharpOutputVisitor(output, FormattingOptionsFactory.CreateSharpDevelop()); syntaxTree.AcceptVisitor(visitor); return(output.ToString()); }
protected static void AssertRoundtripCode(string fileName, bool optimize = false, bool useDebug = false, int compilerVersion = 4) { var code = RemoveIgnorableLines(File.ReadLines(fileName)); AssemblyDefinition assembly = CompileLegacy(code, optimize, useDebug, compilerVersion); CSharpDecompiler decompiler = new CSharpDecompiler(assembly.MainModule, new DecompilerSettings()); decompiler.AstTransforms.Insert(0, new RemoveCompilerAttribute()); var syntaxTree = decompiler.DecompileWholeModuleAsSingleFile(); var options = FormattingOptionsFactory.CreateAllman(); options.IndentSwitchBody = false; CodeAssert.AreEqual(code, syntaxTree.ToString(options)); }
public static string DecompileCSharp(string assemblyFileName) { using (var module = ModuleDefinition.ReadModule(assemblyFileName)) { var typeSystem = new DecompilerTypeSystem(module); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, new DecompilerSettings()); decompiler.AstTransforms.Insert(0, new RemoveCompilerAttribute()); decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()); var syntaxTree = decompiler.DecompileWholeModuleAsSingleFile(); StringWriter output = new StringWriter(); var visitor = new CSharpOutputVisitor(output, FormattingOptionsFactory.CreateSharpDevelop()); syntaxTree.AcceptVisitor(visitor); string fileName = Path.GetTempFileName(); File.WriteAllText(fileName, output.ToString()); return(fileName); } }
static void Decompile(string assemblyFileName, TextWriter output, string typeName = null) { ModuleDefinition module = LoadModule(assemblyFileName); var typeSystem = new DecompilerTypeSystem(module); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, new DecompilerSettings()); decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()); SyntaxTree syntaxTree; if (typeName == null) { syntaxTree = decompiler.DecompileWholeModuleAsSingleFile(); } else { syntaxTree = decompiler.DecompileTypes(module.GetTypes().Where(td => string.Equals(td.FullName, typeName, StringComparison.OrdinalIgnoreCase))); } var visitor = new CSharpOutputVisitor(output, FormattingOptionsFactory.CreateSharpDevelop()); syntaxTree.AcceptVisitor(visitor); }
public static Task <string> DecompileCSharp(string assemblyFileName, DecompilerSettings settings = null) { if (settings == null) { settings = new DecompilerSettings(); } using (var file = new FileStream(assemblyFileName, FileMode.Open, FileAccess.Read)) { var module = new PEFile(assemblyFileName, file, PEStreamOptions.PrefetchEntireImage); string targetFramework = module.Metadata.DetectTargetFrameworkId(); var resolver = new UniversalAssemblyResolver(assemblyFileName, false, targetFramework, null, PEStreamOptions.PrefetchMetadata); resolver.AddSearchDirectory(targetFramework.Contains(".NETFramework") ? RefAsmPath : coreRefAsmPath); var typeSystem = new DecompilerTypeSystem(module, resolver, settings); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, settings); decompiler.AstTransforms.Insert(0, new RemoveEmbeddedAttributes()); decompiler.AstTransforms.Insert(0, new RemoveCompilerAttribute()); decompiler.AstTransforms.Insert(0, new RemoveNamespaceMy()); decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()); var pdbFileName = Path.ChangeExtension(assemblyFileName, ".pdb"); if (File.Exists(pdbFileName)) { decompiler.DebugInfoProvider = DebugInfoUtils.FromFile(module, pdbFileName); } var syntaxTree = decompiler.DecompileWholeModuleAsSingleFile(sortTypes: true); StringWriter output = new StringWriter(); CSharpFormattingOptions formattingPolicy = CreateFormattingPolicyForTests(); var visitor = new CSharpOutputVisitor(output, formattingPolicy); syntaxTree.AcceptVisitor(visitor); string fileName = Path.GetTempFileName(); File.WriteAllText(fileName, output.ToString()); return(Task.FromResult(fileName)); } }
public override ProjectId DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { var module = assembly.GetPEFileOrNull(); if (module == null) { return(null); } if (options.FullDecompilation && options.SaveAsProjectDirectory != null) { if (!WholeProjectDecompiler.CanUseSdkStyleProjectFormat(module)) { options.DecompilerSettings.UseSdkStyleProjectFormat = false; } var decompiler = new ILSpyWholeProjectDecompiler(assembly, options); return(decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken)); } else { AddReferenceAssemblyWarningMessage(module, output); AddReferenceWarningMessage(module, output); output.WriteLine(); base.DecompileAssembly(assembly, output, options); // don't automatically load additional assemblies when an assembly node is selected in the tree view IAssemblyResolver assemblyResolver = assembly.GetAssemblyResolver(loadOnDemand: options.FullDecompilation); var typeSystem = new DecompilerTypeSystem(module, assemblyResolver, options.DecompilerSettings); var globalType = typeSystem.MainModule.TypeDefinitions.FirstOrDefault(); if (globalType != null) { output.Write("// Global type: "); output.WriteReference(globalType, globalType.FullName); output.WriteLine(); } var metadata = module.Metadata; var corHeader = module.Reader.PEHeaders.CorHeader; var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress); if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition) { var entrypoint = typeSystem.MainModule.ResolveMethod(entrypointHandle, new Decompiler.TypeSystem.GenericContext()); if (entrypoint != null) { output.Write("// Entry point: "); output.WriteReference(entrypoint, entrypoint.DeclaringType.FullName + "." + entrypoint.Name); output.WriteLine(); } } output.WriteLine("// Architecture: " + GetPlatformDisplayName(module)); if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0) { output.WriteLine("// This assembly contains unmanaged code."); } string runtimeName = GetRuntimeDisplayName(module); if (runtimeName != null) { output.WriteLine("// Runtime: " + runtimeName); } if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.StrongNameSigned) != 0) { output.WriteLine("// This assembly is signed with a strong name key."); } if (module.Reader.ReadDebugDirectory().Any(d => d.Type == DebugDirectoryEntryType.Reproducible)) { output.WriteLine("// This assembly was compiled using the /deterministic option."); } if (metadata.IsAssembly) { var asm = metadata.GetAssemblyDefinition(); if (asm.HashAlgorithm != AssemblyHashAlgorithm.None) { output.WriteLine("// Hash algorithm: " + asm.HashAlgorithm.ToString().ToUpper()); } if (!asm.PublicKey.IsNil) { output.Write("// Public key: "); var reader = metadata.GetBlobReader(asm.PublicKey); while (reader.RemainingBytes > 0) { output.Write(reader.ReadByte().ToString("x2")); } output.WriteLine(); } } var debugInfo = assembly.GetDebugInfoOrNull(); if (debugInfo != null) { output.WriteLine("// Debug info: " + debugInfo.Description); } output.WriteLine(); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, options.DecompilerSettings); decompiler.CancellationToken = options.CancellationToken; if (options.EscapeInvalidIdentifiers) { decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()); } SyntaxTree st; if (options.FullDecompilation) { st = decompiler.DecompileWholeModuleAsSingleFile(); } else { st = decompiler.DecompileModuleAndAssemblyAttributes(); } WriteCode(output, options.DecompilerSettings, st, decompiler.TypeSystem); return(null); } }
public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options) { var module = assembly.GetPEFileOrNull(); if (options.FullDecompilation && options.SaveAsProjectDirectory != null) { var decompiler = new ILSpyWholeProjectDecompiler(assembly, options); decompiler.DecompileProject(module, options.SaveAsProjectDirectory, new TextOutputWriter(output), options.CancellationToken); } else { AddReferenceAssemblyWarningMessage(module, output); AddReferenceWarningMessage(module, output); output.WriteLine(); base.DecompileAssembly(assembly, output, options); // don't automatically load additional assemblies when an assembly node is selected in the tree view using (options.FullDecompilation ? null : LoadedAssembly.DisableAssemblyLoad()) { IAssemblyResolver assemblyResolver = assembly.GetAssemblyResolver(); var typeSystem = new DecompilerTypeSystem(module, assemblyResolver, options.DecompilerSettings); var globalType = typeSystem.MainModule.TypeDefinitions.FirstOrDefault(); if (globalType != null) { output.Write("// Global type: "); output.WriteReference(globalType, globalType.FullName); output.WriteLine(); } var metadata = module.Metadata; var corHeader = module.Reader.PEHeaders.CorHeader; var entrypointHandle = MetadataTokenHelpers.EntityHandleOrNil(corHeader.EntryPointTokenOrRelativeVirtualAddress); if (!entrypointHandle.IsNil && entrypointHandle.Kind == HandleKind.MethodDefinition) { var entrypoint = typeSystem.MainModule.ResolveMethod(entrypointHandle, new Decompiler.TypeSystem.GenericContext()); if (entrypoint != null) { output.Write("// Entry point: "); output.WriteReference(entrypoint, entrypoint.DeclaringType.FullName + "." + entrypoint.Name); output.WriteLine(); } } output.WriteLine("// Architecture: " + GetPlatformDisplayName(module)); if ((corHeader.Flags & System.Reflection.PortableExecutable.CorFlags.ILOnly) == 0) { output.WriteLine("// This assembly contains unmanaged code."); } string runtimeName = GetRuntimeDisplayName(module); if (runtimeName != null) { output.WriteLine("// Runtime: " + runtimeName); } var debugInfo = assembly.GetDebugInfoOrNull(); if (debugInfo != null) { output.WriteLine("// Debug info: " + debugInfo.Description); } output.WriteLine(); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, options.DecompilerSettings); decompiler.CancellationToken = options.CancellationToken; SyntaxTree st; if (options.FullDecompilation) { st = decompiler.DecompileWholeModuleAsSingleFile(); } else { st = decompiler.DecompileModuleAndAssemblyAttributes(); } WriteCode(output, options.DecompilerSettings, st, decompiler.TypeSystem); } } }
static void Main(string[] args) { // args[0] is the path to Opus Magnum EXE string exe = args[0]; // args[1] is the path to mappings CSV string mappingsLoc = args[1]; // if there's a third string, its the path out.csv if(args.Length > 2) { Console.WriteLine("Reading strings..."); string[] lines = File.ReadAllLines(args[2]); bool hadSplit = true; // multi-line strings int lastIndex = 0; foreach(string line in lines) { string[] split = line.Split("~,~"); if(split.Length > 1) { // if we *can* split on this line, then we're definitely at the first line of a string hadSplit = true; try { lastIndex = int.Parse(split[0]); Strings.Add(lastIndex, split[1]); } catch(ArgumentException) { } } else if(!hadSplit) { // if this line isn't blank (or even if it is), then we're continuing a previous multi-line string, so append Strings[lastIndex] = Strings[lastIndex] + "\n" + line; } } // these are ridden with special characters // we can't just trim normally, see "fmt " breaking WAV loading // so we manually regex replace: [^a-zA-Z0-9_.:\n;'*()+<>\\{}# ,~/$\[\]\-©!"?&’\t=—@%●●●●…—……] is removed // this kills other languages, a better solution is needed in the future foreach(int key in Strings.Keys.ToList()) Strings[key] = Regex.Replace(Strings[key], "[^a-zA-Z0-9_.:\n;'*()+<>\\\\{}# ,~/$\\[\\]\\-©!\" ? &’\t =—@%●●●●…—……]", ""); } Console.WriteLine("Reading mappings..."); // for every line that doesn't start with a "#", split by "," and add to mappings string[] mappingsFile = File.ReadAllLines(mappingsLoc); foreach(var line in mappingsFile){ if(!line.StartsWith("#") && !line.Trim().Equals("")){ string[] split = line.Split(",", 2); mappings.Add(split[0], split[1]); } } var module = new PEFile(exe); var decompiler = new CSharpDecompiler(exe, new UniversalAssemblyResolver(exe, false, module.DetectTargetFrameworkId()), new DecompilerSettings() { NamedArguments = false }); // decompile Console.WriteLine("Decompiling..."); var ast = decompiler.DecompileWholeModuleAsSingleFile(); // we now have a syntax tree // we just need to walk it, modify class and member name references, and then output to files Console.WriteLine("Collecting intermediary names..."); ast.AcceptVisitor(new IdentifierCollectingVisitor()); Console.WriteLine("Remapping..."); ast.AcceptVisitor(new RemappingVisitor()); Console.WriteLine("Cleaning up invalid code..."); ast.AcceptVisitor(new CleanupVisitor()); // some params are in the wrong place... //Console.WriteLine("Adding modded entry point..."); //ast.AcceptVisitor(new EntrypointAddingVisitor()); Console.WriteLine("Writing nonsense -> intermediary..."); using StreamWriter intermediaryFile = new StreamWriter("./intermediary.txt"); foreach(KeyValuePair<string, string> kv in IdentifierCollectingVisitor.intermediary) { intermediaryFile.WriteLine(kv.Key + " -> " + kv.Value); } foreach(KeyValuePair<KeyValuePair<string, string>, string> kv in IdentifierCollectingVisitor.paramIntermediary) { intermediaryFile.WriteLine(kv.Key.Key + ", " + kv.Key.Value + " -> " + kv.Value); } string code = ast.ToString(); // if there's a fourth string, its the path to patch.diff // apply patch and compile if(args.Length > 3) { Console.WriteLine("Applying compilation patch..."); string patchFile = File.ReadAllText(args[3]); var diff = DiffParserHelper.Parse(patchFile); code = PatchHelper.Patch(code, diff.First().Chunks, "\n"); Console.WriteLine("Recompiling..."); SyntaxTree syntax = CSharpSyntaxTree.ParseText(code, new CSharpParseOptions()); var options = new CSharpCompilationOptions( OutputKind.WindowsApplication, optimizationLevel: OptimizationLevel.Release, allowUnsafe: true, warningLevel: 1, platform: Platform.X86 ); // File/Process/Directory doesn't exist var compilation = CSharpCompilation.Create("ModdedLightning", options: options) .AddReferences(new MetadataReference[]{ // add libs MetadataReference.CreateFromFile(typeof(string).Assembly.Location), MetadataReference.CreateFromFile(typeof(HashSet<object>).Assembly.Location), MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location), MetadataReference.CreateFromFile(Assembly.Load("mscorlib").Location), MetadataReference.CreateFromFile(Assembly.Load("System.Runtime").Location), MetadataReference.CreateFromFile(Assembly.Load("System.Runtime.Extensions").Location), MetadataReference.CreateFromFile(Assembly.Load("System.IO").Location), MetadataReference.CreateFromFile(Assembly.Load("System.IO.FileSystem").Location), MetadataReference.CreateFromFile(Assembly.Load("System.IO.FileSystem.Watcher").Location), MetadataReference.CreateFromFile(Assembly.Load("System.Net.Requests").Location), MetadataReference.CreateFromFile(Assembly.Load("System.Diagnostics.Process").Location), MetadataReference.CreateFromFile(Assembly.Load("System.Private.Uri").Location), MetadataReference.CreateFromFile(Assembly.Load("System.ComponentModel.Primitives").Location), MetadataReference.CreateFromFile(Assembly.Load("System.Console").Location), MetadataReference.CreateFromFile(Assembly.Load("netstandard").Location), MetadataReference.CreateFromFile(typeof(Steamworks.CSteamID).Assembly.Location), MetadataReference.CreateFromFile(typeof(Ionic.Zip.ZipEntry).Assembly.Location) }) .AddSyntaxTrees(syntax); using FileStream outputAssembly = new FileStream("./ModdedLightning.exe", FileMode.Create); var res = compilation.Emit(outputAssembly); if(res.Success) { Console.WriteLine("Successfully recompiled!"); Console.WriteLine("(Press any key to continue.)"); Console.ReadKey(); Console.WriteLine("Writing runtime config & running batch..."); string runtimeConfig = @"{ ""runtimeOptions"": { ""tfm"": ""netcoreapp3.1"", ""framework"": { ""name"": ""Microsoft.NETCore.App"", ""version"": ""3.1.0"" }}}"; using StreamWriter configFile = new StreamWriter("./ModdedLightning.runtimeconfig.json"); configFile.WriteLine(runtimeConfig); string runBatch = @"""C:\Program Files (x86)\dotnet\dotnet.exe"" ModdedLightning.exe"; using StreamWriter batchFile = new StreamWriter("./runModded.bat"); batchFile.WriteLine(runBatch); } else { Console.WriteLine("Recompilation failed with " + res.Diagnostics.Length + " errors."); foreach(var error in res.Diagnostics) { Console.WriteLine("Location: " + error.Location.GetLineSpan()); Console.WriteLine(" " + error.GetMessage()); Console.WriteLine("(Press any key to continue.)"); Console.ReadKey(); } } } Console.WriteLine("Writing code output..."); using StreamWriter outputFile = new StreamWriter("./decomp.cs"); outputFile.WriteLine(code); Console.WriteLine("Done!"); }