mkaring / ConfuserEx

An open-source, free protector for .NET applications
https://mkaring.github.io/ConfuserEx/
MIT License
2.25k stars 349 forks source link

NullReferenceException for .NET Standard 2.0 dll #311

Open Anthony-GitHub opened 3 years ago

Anthony-GitHub commented 3 years ago

This issue only occurred on a machine that does not install the .NET Standard runtime. My build machine is Windows 7 and the .NET Standard runtime cannot be installed for some reasons. So I use the/probe parameter to provide the dll search path for .NET Standard.

The NullReferenceException will occur when there is a class with the ICloneable interface.

  public class InternalTest : ICloneable {
    public object Clone() {
      return new InternalTest();
    }
  }

confuserex.crproj:

<project outputDir=".\dotfus" baseDir="." xmlns="http://confuser.codeplex.com">
    <rule preset="none" pattern="true" >
        <protection id="anti debug" action="remove" />
        <protection id="anti dump" action="remove" />
        <protection id="anti ildasm" action="remove" />
        <protection id="anti tamper" action="remove" />
        <protection id="constants" action="remove" />
        <protection id="ctrl flow" action="remove" />
        <protection id="invalid metadata" action="remove" />
        <protection id="ref proxy" action="remove" />
        <protection id="rename" action="add">
          <argument name="mode" value="sequential" />
          <argument name="renPublic" value="true" />
          <argument name="flatten" value="false" />
        </protection>
        <protection id="watermark" action="remove" />
        <protection id="resources" action="remove" />
    </rule>
  <module path=".\testNetStandardDll.dll" snKey=".\test.snk">
    <rule preset="none" pattern="namespace('testNetStandardDll.Public')" >
        <protection id="rename" action="remove"/>
    </rule>
  </module>
</project>

command:

Confuser.CLI.exe /probe=\Libs\CoreCLR\SDK\2.0.0\shared\Microsoft.NETCore.App\2.0.0-preview2-25407-01 -o=test .\testNetStandardDll.dll  confuserex.crproj

The output:

C:\testCoreCLR>C:\Libs\ConfuserEx-CLI\Confuser.CLI.exe /probe=\Libs\CoreCLR\SDK\2.0.0\shared\Microsoft.NETCore.App\2.0.0-preview2-25407-01 -o=test .\testNetStandardDll.dll  confuserex.crproj 
 [INFO] Confuser.Core 1.5.0-alpha+e1d32df601 Copyright c 2014 Ki, 2018 - 2021 Martin Karing
 [INFO] Running on Microsoft Windows NT 6.1.7601 Service Pack 1, .NET Framework v4.0.30319.42000, 64 bits
[DEBUG] Discovering plugins...
 [INFO] Discovered 13 protections, 1 packers.
[DEBUG] Resolving component dependency...
 [INFO] Loading input modules...
 [INFO] Loading '.\testNetStandardDll.dll'...
 [INFO] Initializing...
[DEBUG] Building pipeline...
[DEBUG] Executing 'Type scanner' phase...
 [INFO] Resolving dependencies...
[DEBUG] Checking Strong Name...
 [WARN] [testNetStandardDll.dll] SN Key or SN public Key is not provided for a signed module, the output may not be working.
[DEBUG] Creating global .cctors...
[DEBUG] Executing 'Name analysis' phase...
[DEBUG] Building VTables & identifier list...
[ERROR] Failed to resolve a type, check if all dependencies are present in the correct version.
Exception: dnlib.DotNet.TypeResolveException: Could not resolve type: System.ICloneable (netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51)
   at dnlib.DotNet.TypeRef.ResolveThrow(ModuleDef sourceModule)
   at Confuser.Renamer.VTableStorage.GetVTable(ITypeDefOrRef type)
   at Confuser.Renamer.VTable.ConstructVTable(TypeDef typeDef, VTableStorage storage)
   at Confuser.Renamer.VTableStorage.GetOrConstruct(TypeDef type)
   at Confuser.Renamer.AnalyzePhase.Execute(ConfuserContext context, ProtectionParameters parameters)
   at Confuser.Core.ProtectionPipeline.ExecuteStage(PipelineStage stage, Action`1 func, Func`1 targets, ConfuserContext context)
   at Confuser.Core.ConfuserEngine.RunPipeline(ProtectionPipeline pipeline, ConfuserContext context)
   at Confuser.Core.ConfuserEngine.RunInternal(ConfuserParameters parameters, CancellationToken token)
[ERROR] ---BEGIN DEBUG INFO---
[ERROR] Installed Framework Versions:
[ERROR]     v2.0.50727  2.0.50727.5420
[ERROR]     v3.0  3.0.30729.5420
[ERROR]     v3.5  3.5.30729.5420
[ERROR]     v4
[ERROR]     Client  4.6.01055
[ERROR]     Full  4.6.01055
[ERROR]     v4.0
[ERROR]     Client  4.0.0.0
[ERROR]     v4.5 394271
[ERROR] 
[ERROR] Cached assemblies:
[ERROR]     testNetStandardDll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=fdf33a57ec201991 (C:\testCoreCLR\testNetStandardDll.dll)
[ERROR]         netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
[ERROR]     netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51 (C:\Libs\CoreCLR\SDK\2.0.0\shared\Microsoft.NETCore.App\2.0.0-preview2-25407-01\netstandard.dll)
[ERROR]         System.Runtime, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.IO.MemoryMappedFiles, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.IO.Pipes, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Diagnostics.Process, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Security.Cryptography.X509Certificates, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Runtime.Extensions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Diagnostics.Tools, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Collections, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Collections.NonGeneric, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Collections.Concurrent, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.ObjectModel, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Collections.Specialized, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.ComponentModel.TypeConverter, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.ComponentModel.EventBasedAsync, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.ComponentModel.Primitives, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.ComponentModel, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         Microsoft.Win32.Primitives, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Console, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Data.Common, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Runtime.InteropServices, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Diagnostics.TraceSource, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Diagnostics.Contracts, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Diagnostics.Debug, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Diagnostics.TextWriterTraceListener, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Diagnostics.FileVersionInfo, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Diagnostics.StackTrace, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Diagnostics.Tracing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Drawing.Primitives, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Linq.Expressions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.IO.Compression, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.IO.Compression.ZipFile, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.IO.FileSystem, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.IO.FileSystem.DriveInfo, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.IO.FileSystem.Watcher, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.IO.IsolatedStorage, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Linq, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Linq.Queryable, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Linq.Parallel, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Threading.Thread, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.Requests, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.Primitives, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.HttpListener, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
[ERROR]         System.Net.ServicePoint, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
[ERROR]         System.Net.NameResolution, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.WebClient, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
[ERROR]         System.Net.Http, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.WebHeaderCollection, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.WebProxy, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
[ERROR]         System.Net.Mail, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
[ERROR]         System.Net.NetworkInformation, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.Ping, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.Security, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.Sockets, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.WebSockets.Client, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Net.WebSockets, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Runtime.Numerics, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Threading.Tasks, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Reflection.Primitives, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Resources.ResourceManager, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Resources.Writer, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Runtime.CompilerServices.VisualC, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Runtime.InteropServices.RuntimeInformation, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Runtime.Serialization.Primitives, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Runtime.Serialization.Xml, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Runtime.Serialization.Json, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Runtime.Serialization.Formatters, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Security.Claims, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Security.Cryptography.Algorithms, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Security.Cryptography.Csp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Security.Cryptography.Encoding, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Security.Cryptography.Primitives, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Security.Principal, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Text.Encoding.Extensions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Text.RegularExpressions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Threading, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Threading.Overlapped, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Threading.ThreadPool, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Threading.Tasks.Parallel, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Threading.Timer, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Transactions.Local, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
[ERROR]         System.Web.HttpUtility, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
[ERROR]         System.Xml.ReaderWriter, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Xml.XDocument, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Xml.XmlSerializer, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Xml.XPath.XDocument, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Xml.XPath, Version=0.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Failed at 2:33 PM, 0:00 elapsed.

Unhandled Exception: System.AggregateException: One or more errors occurred. ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Confuser.Core.ConfuserEngine.PrintEnvironmentInfo(ConfuserContext context)
   at Confuser.Core.ConfuserEngine.RunInternal(ConfuserParameters parameters, CancellationToken token)
   at System.Threading.Tasks.Task.Execute()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at Confuser.CLI.Program.RunProject(ConfuserParameters parameters)
   at Confuser.CLI.Program.Main(String[] args)

Here is the demo project to reproduce: ConfuserExNullReferenceException.zip

This project does not include the dll for .NETCore due to the upload size limitation. For the full project, please download from: https://drive.google.com/file/d/1zIFdeA2T17597i5BQhWdkKO0JZ8bldPD/view?usp=sharing


I finally make it work by disabling the GAC: https://github.com/Anthony-GitHub/ConfuserEx/commit/7b6cc07bc537d489b861668cc9c0d188d97c3323

Is that possible to add a parameter to disable/enable the GAC? Or do you have any other ideas?

Thanks

mkaring commented 3 years ago

To get .NET Core 1.x and 2.x as well as .NET Standard <= 2.0 working properly, you need to add the dependency explicitly as external module. This way it will resolve the file properly.

So you add

<module path="\Libs\CoreCLR\SDK\2.0.0\shared\Microsoft.NETCore.App\2.0.0-preview2-25407-01\netstandard.dll" external="true" />

to the project. This will force ConfuserEx 1.5 to use the file (1.4.1 will not work).

Anthony-GitHub commented 3 years ago

Thanks. I tried to add the dependency explicitly as an external module but it makes no difference. It still crashes with NullReferenceException. I also tried to add all the .NET Standard dlls as an external module, still not work.

mkaring commented 3 years ago

The NullReferenceException is hiding the real error. Any chance you could attach the debugger to the Confuser while running and tell me, what exactly triggers this exception in this function?

I'm guessing it's triggered here because there is some assembly without managed module.

Anthony-GitHub commented 3 years ago

Yes, the NullReferenceException is triggered here. The variable asm is null.

The first Exception is triggered in VTable.cs:

dnlib.DotNet.TypeResolveException
  HResult=0x80131500
  Message=Could not resolve type: System.ICloneable (netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51)
  Source=dnlib
  StackTrace:
   at dnlib.DotNet.TypeRef.ResolveThrow(ModuleDef sourceModule)
   at Confuser.Renamer.VTableStorage.GetVTable(ITypeDefOrRef type) in C:\test\ConfuserEx-master\Confuser.Renamer\VTable.cs:line 372
mkaring commented 3 years ago

Okay, so I can't reproduce the issue in my system, because it always falls back to the .NET Framework version of the system. And that is the same thing that should happen in your case, unless you don't have the .NET Framework installed.

What exactly is the setup on your system?

Anthony-GitHub commented 3 years ago

I just install a Windows 7 SP1 in VM, and then install .NET Framework 4.6.1, then it can reproduce this issue.

Let me know if you still cannot reproduce this issue. I can share the credential by Email so you can remote login. Or I can upload this VM that may take some time.

mkaring commented 3 years ago

There was actually still an error in ConfuserEx, that caused my suggested fix from before to fail. The fix suggested here should not work with the ConfuserEx 1.5 Release.

Please let me know if that resolves the problem.

Anthony-GitHub commented 3 years ago

The NullReferenceException is still there with the ConfuserEx 1.5 Release.. The error message is the same as before.

Timocop commented 3 years ago

Try uninstalling .NET 4.6.1. For whatever reason .NET 4.6.1 breaks serval obfuscators that have been build with .NET 4.0. Install .NET 4.8 instead. Maybe that helps.