icsharpcode / ILSpy

.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
20.74k stars 3.29k forks source link

ilspycmd: Add support for Xamarin compressed DLLs #2362

Open Techbrunch opened 3 years ago

Techbrunch commented 3 years ago

Steps to reproduce

ilspycmd -p -o test Test.dll

Error message shown

System.BadImageFormatException: Image is too small.
   at System.Reflection.Throw.ImageTooSmall()
   at System.Reflection.PortableExecutable.SectionHeader..ctor(PEBinaryReader& reader)
   at System.Reflection.PortableExecutable.PEHeaders.ReadSectionHeaders(PEBinaryReader& reader)
   at System.Reflection.PortableExecutable.PEHeaders..ctor(Stream peStream, Int32 size, Boolean isLoadedImage)
   at System.Reflection.PortableExecutable.PEReader.InitializePEHeaders()
   at System.Reflection.PortableExecutable.PEReader.get_HasMetadata()
   at ICSharpCode.Decompiler.Metadata.PEFile..ctor(String fileName, PEReader reader, MetadataReaderOptions metadataOptions)
   at ICSharpCode.Decompiler.Metadata.PEFile..ctor(String fileName, Stream stream, PEStreamOptions streamOptions, MetadataReaderOptions metadataOptions)
   at ICSharpCode.Decompiler.Metadata.UniversalAssemblyResolver.Resolve(IAssemblyReference name)
   at ICSharpCode.Decompiler.TypeSystem.DecompilerTypeSystem..ctor(PEFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions)
   at ICSharpCode.Decompiler.TypeSystem.DecompilerTypeSystem..ctor(PEFile mainModule, IAssemblyResolver assemblyResolver, DecompilerSettings settings)
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.WholeProjectDecompiler.WriteCodeFilesInProject(PEFile module, CancellationToken cancellationToken)
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.WholeProjectDecompiler.DecompileProject(PEFile moduleDefinition, String targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken)
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.WholeProjectDecompiler.DecompileProject(PEFile moduleDefinition, String targetDirectory, CancellationToken cancellationToken)
   at ICSharpCode.Decompiler.Console.ILSpyCmdProgram.DecompileAsProject(String assemblyFileName, String outputDirectory) in D:\GitWorkspace\ILSpy\ICSharpCode.Decompiler.Console\IlspyCmdProgram.cs:line 186
   at ICSharpCode.Decompiler.Console.ILSpyCmdProgram.OnExecute(CommandLineApplication app) in D:\GitWorkspace\ILSpy\ICSharpCode.Decompiler.Console\IlspyCmdProgram.cs:line 83

Details

If you need more info let me know.

christophwille commented 3 years ago

I am pretty sure Siegi can't repro the problem without the assembly, so please send it to him. Just to make sure: ilspycmd on Mac didn't work, ilspycmd on Windows worked? Or is it ILSpy on Windows worked?

Techbrunch commented 3 years ago

Hi @christophwille,

thanks, I'll send the DLL to Siegi. I forgot to specify in my last message that it worked on Windows using dotBeek by JetBrains.

siegfriedpammer commented 3 years ago

Thanks for sending the file! Sorry, currently I don't have time to look at it, but I will try to follow up as soon as possible.

Techbrunch commented 3 years ago

Thanks for taking the time to investigate. I'll answer your email here since it might be helpful to someone else and probably future me :)

The problem is related to a file on your system, which the decompiler is trying to load as a reference. However, it then crashes, because the file it is trying to load is not a valid managed DLL.

Yes now it makes sense, the context is that I was trying to decompile a DLL coming from a Xamarin app but I only decompressed one DLL (cf: #2137, #1637). which is probably referencing other DLL that I did not decompress in the same folder.

Have you tried running the command with the bug.dll being in a separate directory?

Doing this resulted in another error but I'm guessing this is to be expected and my file was correctly decompiled:

System.NotSupportedException: Cannot decompile this assembly to a SDK style project. Use default project format instead.
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.ProjectFileWriterSdkStyle.WriteAssemblyInfo(XmlTextWriter xml, PEFile module, IProjectInfoProvider project, ProjectType projectType)
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.ProjectFileWriterSdkStyle.<>c__DisplayClass10_0.<Write>b__0()
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.ProjectFileWriterSdkStyle.PlaceIntoTag(String tagName, XmlTextWriter xml, Action content)
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.ProjectFileWriterSdkStyle.Write(XmlTextWriter xml, IProjectInfoProvider project, IEnumerable`1 files, PEFile module)
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.ProjectFileWriterSdkStyle.Write(TextWriter target, IProjectInfoProvider project, IEnumerable`1 files, PEFile module)
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.WholeProjectDecompiler.DecompileProject(PEFile moduleDefinition, String targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken)
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.WholeProjectDecompiler.DecompileProject(PEFile moduleDefinition, String targetDirectory, CancellationToken cancellationToken)
   at ICSharpCode.Decompiler.Console.ILSpyCmdProgram.DecompileAsProject(String assemblyFileName, String outputDirectory) in D:\GitWorkspace\ILSpy\ICSharpCode.Decompiler.Console\IlspyCmdProgram.cs:line 193
   at ICSharpCode.Decompiler.Console.ILSpyCmdProgram.OnExecute(CommandLineApplication app) in D:\GitWorkspace\ILSpy\ICSharpCode.Decompiler.Console\IlspyCmdProgram.cs:line 86

Let me know if I need to create an issue for this error.

I have added some fixes/additions to the decompiler to make debugging such problems easier. However, there is currently no precompiled ilspycmd.exe for you to download. Could you try compiling ILSpy on your machine and then using a debug build to investigate the issue further? Thank you!

I'm don't know how to do that. I installed ilspycmdon my mac using:

dotnet tool update ilspycmd -g --version 7.0.0.6372-preview3

Can I get the master nuget package from the CI ? If so I should be able to install it locally.

On #2137 you mentionned you said about decompilling DLL coming from Xamarin apps:

Unless support for these is contributed, it won't happen.

I might give it a try but I have no idea how hard it would be to implement. Could you give me some pointer on how someone would go about adding this feature ? Could this be done with a plugin ? If it's too much work don't worry I'll keep using the python script ;)

gravityFlower commented 2 years ago

Found this issue but no further information, what the content of the python script was. Apparently it is a newly introduced compression using lz4. First 12 bytes are metadata, 8-12 is the uncompressed length, remaining bytes after that are the compressed data: https://www.x41-dsec.de/security/news/working/research/2020/09/22/xamarin-dll-decompression/

siegfriedpammer commented 2 years ago

I think the main issue here was already fixed in #2137. The open request here is adding support for compressed DLLs to ilspycmd as well.

siegfriedpammer commented 2 years ago

I am currently trying to reproduce XALZ DLLs in order to be able to test the feature properly. I am following the steps listed here, but I cannot create XALZ DLLs using VS 2022. The only thing I get is an assemblies.blob file inside the apk, which starts with the sequence "XABA" and probably contains multiple compressed assemblies. @Techbrunch @gravityFlower @jingliancui I would really appreciate your help with this, as I have not much experience with Xamarin.Forms projects. Thank you very much!

developerfromjokela commented 1 year ago

Have a look at this: https://github.com/xamarin/xamarin-android/tree/main/tools/assembly-store-reader

jingliancui commented 1 year ago

Glad that I can help you. Maybe this week later. I try to write some reproduce steps for you.

jingliancui commented 1 year ago

I think the newest version of ilspy from MS Store is perfectly solve this problem. The newest version of xamarin.android use "Embedded assemblies store", refer this link:https://learn.microsoft.com/en-us/xamarin/android/release-notes/12/12.2

So if we want to disable this feature, just add this node to csproj file: <AndroidUseAssemblyStore>false</AndroidUseAssemblyStore>