mkaring / ConfuserEx

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

Exception when obfuscating code that sets Func<> object located in external library with ref proxy mild mode #468

Open hp-psi opened 2 years ago

hp-psi commented 2 years ago

Software version

Problem

ConfuserEx throws an exception when attempting to obfuscate code that sets a Func<> object located in an external library with reference proxy in mild mode.

Exception: Failed to resolve a member, check if all dependencies are present in the correct version. dnlib.DotNet.MemberRefResolveException: Could not resolve method.

Steps to reproduce (with the attached example project)

  1. Download the project (ConfuserEx2IssueTestNETF472.zip).
  2. Edit the Obfuscate.bat to point towards your installed ConfuserEx CLI binary.
  3. Build the project.
  4. Go to the Debug/Release folder.
  5. Run the Obfuscate.bat
  6. The error will appear in the cmd.

The attached zip also includes a .log with the CMD output and the .crproj used.

Details

The reference proxy protection causes the issue, if it is set to strong it works, if it is set to mild it throws an exception. In the project Im obfuscating I can't use the strong mode due to incompatibility and other issues. The ExcelDataReader nuggets are in .NET Framework 4.5.

Files

Code (throws exception when obfuscating, requires ExcelDataReader nuggets):

using (FileStream stream = File.Open("Data.xlsx", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    using (var reader = ExcelReaderFactory.CreateReader(stream))
    {
        DataSet excelData = reader.AsDataSet(new ExcelDataSetConfiguration()
        {
            ConfigureDataTable = (tableReader) => new ExcelDataTableConfiguration()
            {
                UseHeaderRow = true
            }
        });

        foreach (DataRow dr in excelData.Tables["Data"].Rows)
            Console.WriteLine($"{dr["ID"]}\t{dr["Description"]}\t{dr["Value"]}");
    }
}

CRPROJ:

<project baseDir="" outputDir="Obfuscated" xmlns="http://confuser.codeplex.com">
    <rule pattern="true" preset="maximum" inherit="false">
        <protection id="ref proxy">
            <argument name="mode" value="mild" />
        </protection>
    </rule>
    <module path="ConfuserEx2IssueTestNETF472.exe" />
</project>

LOG:

 [INFO] Confuser.Core 1.6.0+447341964f Copyright © 2014 Ki, 2018 - 2022 Martin Karing
 [INFO] Running on Microsoft Windows NT 6.2.9200.0, .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 'ConfuserEx2IssueTestNETF472.exe'...
 [INFO] Initializing...
[DEBUG] Building pipeline...
[DEBUG] Executing 'Type scanner' phase...
 [INFO] Resolving dependencies...
[DEBUG] Checking Strong Name...
[DEBUG] Creating global .cctors...
[DEBUG] Executing 'Name analysis' phase...
[DEBUG] Building VTables & identifier list...
[DEBUG] Analyzing...
 [INFO] Processing module 'ConfuserEx2IssueTestNETF472.exe'...
[DEBUG] Executing 'Invalid metadata addition' phase...
[DEBUG] Executing 'Renaming' phase...
[DEBUG] Renaming...
[DEBUG] Executing 'Anti-tamper module writer preparation' phase...
[DEBUG] Executing 'Anti-debug injection' phase...
[DEBUG] Executing 'Anti-dump injection' phase...
[DEBUG] Executing 'Anti-ILDasm marking' phase...
[DEBUG] Executing 'Encoding reference proxies' phase...
[ERROR] Failed to resolve a member, check if all dependencies are present in the correct version.
Exception: dnlib.DotNet.MemberRefResolveException: Could not resolve method: System.Void ExcelDataReader.ExcelDataSetConfiguration::set_ConfigureDataTable(System.Func`2<ExcelDataReader.IExcelDataReader,ExcelDataReader.ExcelDataTableConfiguration>) (ExcelDataReader.DataSet, Version=3.6.0.0, Culture=neutral, PublicKeyToken=93517dbe6a4012fa)
   em dnlib.DotNet.MemberRef.ResolveMethodThrow()
   em Confuser.Protections.ReferenceProxy.MildMode.ProcessCall(RPContext ctx, Int32 instrIndex)
   em Confuser.Protections.ReferenceProxy.ReferenceProxyPhase.ProcessMethod(RPContext ctx)
   em Confuser.Protections.ReferenceProxy.ReferenceProxyPhase.Execute(ConfuserContext context, ProtectionParameters parameters)
   em Confuser.Core.ProtectionPipeline.ExecuteStage(PipelineStage stage, Action`1 func, Func`1 targets, ConfuserContext context)
   em Confuser.Core.ConfuserEngine.RunPipeline(ProtectionPipeline pipeline, ConfuserContext context)
   em Confuser.Core.ConfuserEngine.RunInternal(ConfuserParameters parameters, CancellationToken token)
[ERROR] ---BEGIN DEBUG INFO---
[ERROR] Installed Framework Versions:
[ERROR]     v2.0.50727  2.0.50727.4927
[ERROR]     v3.0  3.0.30729.4926
[ERROR]     v3.5  3.5.30729.4926
[ERROR]     v4
[ERROR]     Client  4.8.04084
[ERROR]     Full  4.8.04084
[ERROR]     v4.0
[ERROR]     Client  4.0.0.0
[ERROR]     v4.5 528372
[ERROR]
[ERROR] Cached assemblies:
[ERROR]     ConfuserEx2IssueTestNETF472, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null (C:\PSI\Projetos\ConfuserEx2IssueTestNETF472\ConfuserEx2IssueTestNETF472\bin\Debug\ConfuserEx2IssueTestNETF472.exe)
[ERROR]         mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         ExcelDataReader, Version=3.6.0.0, Culture=neutral, PublicKeyToken=93517dbe6a4012fa
[ERROR]         System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         ExcelDataReader.DataSet, Version=3.6.0.0, Culture=neutral, PublicKeyToken=93517dbe6a4012fa
[ERROR]     mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 (C:\WINDOWS\Microsoft.NET\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll)
[ERROR]     ExcelDataReader, Version=3.6.0.0, Culture=neutral, PublicKeyToken=93517dbe6a4012fa (C:\PSI\Projetos\ConfuserEx2IssueTestNETF472\ConfuserEx2IssueTestNETF472\bin\Debug\ExcelDataReader.dll)
[ERROR]         mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.IO.Compression, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]     System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 (C:\WINDOWS\Microsoft.NET\assembly\GAC_32\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll)
[ERROR]         mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.Runtime.Caching, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]     ExcelDataReader.DataSet, Version=3.6.0.0, Culture=neutral, PublicKeyToken=93517dbe6a4012fa (C:\PSI\Projetos\ConfuserEx2IssueTestNETF472\ConfuserEx2IssueTestNETF472\bin\Debug\ExcelDataReader.DataSet.dll)
[ERROR]         mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         ExcelDataReader, Version=3.6.0.0, Culture=neutral, PublicKeyToken=93517dbe6a4012fa
[ERROR]     System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 (C:\WINDOWS\assembly\GAC_MSIL\System.Core\3.5.0.0__b77a5c561934e089\System.Core.dll)
[ERROR]         mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
[ERROR]         System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]     mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
[ERROR]     ConfuserEx2IssueTestNETF472, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null (C:\PSI\Projetos\ConfuserEx2IssueTestNETF472\ConfuserEx2IssueTestNETF472\bin\Debug\ConfuserEx2IssueTestNETF472.exe)
[ERROR]         mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         ExcelDataReader, Version=3.6.0.0, Culture=neutral, PublicKeyToken=93517dbe6a4012fa
[ERROR]         System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
[ERROR]         ExcelDataReader.DataSet, Version=3.6.0.0, Culture=neutral, PublicKeyToken=93517dbe6a4012fa
[ERROR] ---END DEBUG INFO---
Failed at 15:10, 0:00 elapsed.
hp-psi commented 2 years ago

After some debuging and research, noticed the exception came right after doing assembly resolve.

Confuser.Protections.MildMode

Confuser.Core.DnlibUtils

Confuser.Core.ConfuserAssemblyResolver

Throws exception after return, the assembly is {mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089} and the sourceModule is {ExcelDataReader.DataSet.dll}.

ExcelDataReader target framework is .NET Framework 4.5. ExcelDataReader.DataSet target framework is .NET Framework 3.5.

I don't know exactly why it fails, is mscorlib missing? I reinstalled .NET Framework 3.5 and the GAC folder contains mscorlib 2.0.0.0: C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089 C:\Windows\assembly\GAC_64\mscorlib\2.0.0.0__b77a5c561934e089

Ran ConfuserEx again and still failed, decided to build ExcelDataReader and ExcelDataReader.DataSet targeting .NET Framework 4.7.2 and ConfuserEx successfully obfuscated the main binary using reference proxy in mild mode.

While this fixes the issue it is a contour of the problem. I still have no clue exactly on why it happens.

hp-psi commented 2 years ago

Created a new more simplified test project, this includes only a console application (4.7.2) with a Program.cs and a class library (3.5) with Class1.cs.

This always triggers an exception in ConfuserEx when using reference proxy mild.

ConfuserEx2IssueTest.zip

mkaring commented 2 years ago

Your exception looks like it's just missing a reference to the ExcelDataReader.DataSet assembly. Does it work if you just add that example as external reference to your Confuser project or if you add the location of this assembly to the probe paths?

This should sort the issue out.

hp-psi commented 2 years ago

Hi, I created a new test sample (link above) that does not use nuggets and uses instead an external referenced dll.

From what I tested I noticed that this only happens when the referenced dll is in .NET Framework 3.5 (atleast in 4.7.2 the issue does not exist) .

Example that always triggers the issue:

.NET Framework 4.7.2 Console Application (will be obfuscated): Contais only one class called Program.cs, has an external reference to a Class Library targeted for .NET Framework 3.5.

using ConfuserEx2IssueTest.Lib;
using System;

namespace ConfuserEx2IssueTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Class1 c = new Class1();

            c.FuncTest = () => "";

            Console.WriteLine();
            Console.ReadKey();
        }
    }
}

.NET Framework 3.5 Class Library (will NOT be obfuscated) Contais only one class called Class1.cs, will be referenced by the Console Application.

using System;

namespace ConfuserEx2IssueTest.Lib
{
    public class Class1
    {
        public Func<string> FuncTest { get; set; }
    }
}

Now one just has to compile and obfuscate the Console Application using reference proxy in mild mode (strong mode works and does not have any issues).

What makes the process fail is the use of Func<> object, if it was any other object like string, int, etc... or the use of an actual function there would be no problem.

I do not really know what makes it fail, my best guess from the debugging I did was that it was interpreting the set Func<> object as an actual function.

github-actions[bot] commented 2 years ago

This issue needs more information and has not had recent activity. Please provide the missing information or it will be closed in 7 days. Thanks!