Beispiel #1
0
        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);
                }
            }
        }
Beispiel #3
0
        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));
        }
Beispiel #5
0
        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);
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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));
            }
        }
Beispiel #8
0
        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);
            }
        }
Beispiel #9
0
        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);
                }
            }
        }
Beispiel #10
0
		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!");
		}