obfuscar / obfuscar

Open source obfuscation tool for .NET assemblies
https://www.obfuscar.com
MIT License
2.47k stars 399 forks source link

HidePrivateApi make application stackoverflow(it's fine before it's not obfuscated) #485

Open zhmacn opened 2 months ago

zhmacn commented 2 months ago

When I set the HidePrivateApi property to true, the obfuscated code doesn't run, and when I call one of my program's apis, it stackoverflows, but it's fine before it's not obfuscated

this is my obfuscar config:

<?xml version='1.0'?>

when i run my application and call webapi , The program will crash directly this is the error log,(The error message is too long, so I took a screenshot of it ,the main problem is stackoverflow)

Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List`1<System.Canon>, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.Collections.Generic.List1, System.String ByRef) at A.X3[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].A(System.String, System.Collections.Generic.List1) at A.j.Read(System.String, System.Collections.Generic.List`1)

I found that the corresponding source code should be this part: public BaseDataEntity<List> Read(string deviceId, List requests) => Handle(deviceId,requests); .... protected BaseDataEntity<List> Handle(string deviceId, List requests){ ...... }

I found the code that might be associated after the confusion is here:

public BaseDataEntity<List<PLCReadResponse>> Read(
  string deviceId,
  List<PLCReadRequest> requests)
{
  return this.A(deviceId, requests);
}

[return: A.a(2)]
protected override PLCReadResponse A([In] S obj0, [In] ITZPLC obj1, [In] PLCReadRequest obj2) => obj0.A(obj1, obj2);

protected new virtual bool A([In] List<PLCReadRequest> obj0, out string _param2) => new H(obj0).a(out _param2);
lextm commented 2 months ago

You might set ReuseNames to false as a workaround,

https://docs.lextudio.com/obfuscar/getting-started/configuration#settings

But no plan right now to further investigate this issue.

zhmacn commented 2 months ago

You might set ReuseNames to false as a workaround,

https://docs.lextudio.com/obfuscar/getting-started/configuration#settings

But no plan right now to further investigate this issue.

I've set the ReuseNames property to false, but it's still the same issue, here's my configuration

<?xml version='1.0'?>
<Obfuscator>
  <Var name="InPath" value=".\bin\Debug\net6.0" />
  <Var name="OutPath" value=".\bin\Debug\Final" />
  <Var name="KeepPublicApi" value="true" />
  <Var name="HidePrivateApi" value="true" />
  <Var name="HideStrings" value="false" />
  <Var name="UseUnicodeNames" value="false" />
  <Var name="ReuseNames" value="false" />
  <var name="RenameProperties" value="false"/>
  <Var name="RenameFields" value="false" />
  <Var name="RegenerateDebugInfo" value="false" />

  <Module file="$(InPath)\MyService.dll" >
      <SkipNamespace name="MyServiceApi.entity" />
  </Module>
  <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\6.0.10\" />
  <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.10\" />
</Obfuscator>
zhmacn commented 2 months ago

I found more information from the Mapping.txt Different methods in the same class (but with the same method parameter signature) are converted to the same name

here's the mapping in the mapping.txt

    [xxx.AbstractRequestHandleService`3::CheckRequestInner[2]( [System.Collections]System.Collections.Generic.List`1<!1>, [System.Runtime]System.String& ) -> A
    [xxx.AbstractRequestHandleService`3::CheckRequest[2]( [System.Collections]System.Collections.Generic.List`1<!1>, [System.Runtime]System.String& ) -> A

Both the "CheckRequestInner" and "CheckRequest" methods are converted to methods "A" So, when I call "CheckRequestInner" in the "CheckRequest" method, the program gets stuck in infinite recursion

here is mycode

internal abstract class AbstractRequestHandleService<H, REQ, RESP> : InnerContextStarter
        where REQ : BaseRequest where RESP : BaseEntity, new() where H : class, IStarter, INamed
    {
          protected bool CheckRequest(List<REQ> requests, out string msg)
        {
            msg = "ok";
            if (!this.Started)
            {
                msg = "server not started!";
                return false;
            }
            if (requests == null || requests.Any(req => req == null))
            {
                msg = "request is null!";
                return false;
            }
            return CheckRequestInner(requests, out msg);
        }

        protected abstract bool CheckRequestInner(List<REQ> request, out string msg);

    }
zhmacn commented 2 months ago

i find the problem, I created a demo project,With just three files, the issue can be reproduced

The solution is as follows, and there are three projects in the solution, each with only one file

  1. The API project is used to define external interfaces
  2. The core project is used to write services
  3. The TestObfuscar project is used for testing the sln structure: image

IReadService.cs file:

namespace Api
{
    public interface IReadService
    {
        public List<string> Read(string deviceId, List<string> request);

    }
}

AbstractService.cs file:

using Api;

namespace Core
{
    public abstract class AbstractService
    {
        public static IReadService GetReadService() => new ReadServiceImpl();
    }

    internal abstract class AbstractReadService<H, REQ, RESP> : AbstractService where H : class
    {
        protected bool CheckRequest(List<REQ> requests, out string msg)
        {
            Console.WriteLine("------------------AbstractReadService:CheckRequest--0");
            Thread.Sleep(200);
            Console.WriteLine("------------------AbstractReadService:CheckRequest--1");
            Thread.Sleep(200);
            return CheckRequestInner(requests, out msg);
        }
        protected abstract bool CheckRequestInner(List<REQ> request, out string msg);

    }

    internal class ReadServiceImpl : AbstractReadService<string, string, string>, IReadService
    {

        public List<string> Read(string deviceId, List<string> requests) 
        {
            if (!CheckRequest(requests, out string? msg)) return null!;
            return new List<string>();
        }
        protected override bool CheckRequestInner(List<string> requests, out string msg)
        {
            Console.WriteLine("That Right!!, CheckRequest Inner Method Called!!");
            Thread.Sleep(1000);
            msg = "inner check ok";
            return true;
        }

    }
}

Program.cs file

using Core;

AbstractService.GetReadService().Read("Device-001",new List<string>() { "abc"});

Console.Read();

afterBuild.bat

echo "start-copy files"
xcopy bin\Debug\net6.0\ bin\Debug\Final\ /s /e /y 
echo "copy file completed"
echo "start-obfuscar"
obfuscar.console ./Obfuscar.xml
echo "end-obfuscar"
del bin\Debug\Final\*.pdb

Obfuscar.xml

<?xml version='1.0'?>
<Obfuscator>
  <Var name="InPath" value=".\bin\Debug\net6.0" />
  <Var name="OutPath" value=".\bin\Debug\Final" />
  <Var name="KeepPublicApi" value="true" />
  <Var name="HidePrivateApi" value="true" />
  <Var name="HideStrings" value="false" />
  <Var name="UseUnicodeNames" value="false" />
  <Var name="ReuseNames" value="false" />
  <var name="RenameProperties" value="false"/>
  <Var name="RenameFields" value="false" />
  <Var name="RegenerateDebugInfo" value="false" />

  <Module file="$(InPath)\Core.dll" >
  </Module>

  <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\6.0.10\" />
  <AssemblySearchPath path="C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.10\" />
</Obfuscator>

Run results without confusion

------------------AbstractReadService:CheckRequest--0
------------------AbstractReadService:CheckRequest--1
That Right!!, CheckRequest Inner Method Called!!

The result of the code running after obfuscation

------------------AbstractReadService:CheckRequest--0
------------------AbstractReadService:CheckRequest--1
------------------AbstractReadService:CheckRequest--0
------------------AbstractReadService:CheckRequest--1
------------------AbstractReadService:CheckRequest--0
------------------AbstractReadService:CheckRequest--1
------------------AbstractReadService:CheckRequest--0
------------------AbstractReadService:CheckRequest--1
------------------AbstractReadService:CheckRequest--0
------------------AbstractReadService:CheckRequest--1
------------------AbstractReadService:CheckRequest--0
------------------AbstractReadService:CheckRequest--1
------------------AbstractReadService:CheckRequest--0
------------------AbstractReadService:CheckRequest--1

the sln attachment:

TestObfuscar.zip

my obfuscar version: image