From a055d785e5faca03219587bdabfcae3d24be5794 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 25 Aug 2024 11:48:15 +0300 Subject: [PATCH 01/10] Remove removed option from troubleshooting #196 --- troubleshooting.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/troubleshooting.md b/troubleshooting.md index b41f6b79..8dd3bc01 100644 --- a/troubleshooting.md +++ b/troubleshooting.md @@ -4,8 +4,4 @@ Here we describe most known issues and its solution, something like Faq. #### Access Denied: -Try to set `OpenFileDestinationInFileExplorer` to `false` in `obfuscation.json` - -#### Output file changed its bits: - -If your output file is changed from x32 to x64 or something similar, and it cause issues for you then set `AllowPotentialBreakingChangesToModule` to `false` in `obfuscation.json`, however be careful changing it, because some protections may be dependent on this configurations (for example UnmanagedString). \ No newline at end of file +Try to set `OpenFileDestinationInFileExplorer` to `false` in `obfuscation.json` \ No newline at end of file From 4a12ed989f344c532fa9c34bf5765bec69ad2f97 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 25 Aug 2024 11:50:28 +0300 Subject: [PATCH 02/10] Add ConfigureForNativeCodeAttribute --- .../ConfigureForNativeCodeAttribute.cs | 10 +++ .../Contexts/ProtectionContext.cs | 23 ----- .../Extensions/ProtectionExtensions.cs | 10 +++ src/BitMono.Host/BitMonoApplication.cs | 2 +- src/BitMono.Host/obfuscation.json | 4 + src/BitMono.Obfuscation/BitMonoObfuscator.cs | 83 ++++++++++++------- src/BitMono.Obfuscation/GlobalUsings.cs | 1 + src/BitMono.Protections/UnmanagedString.cs | 3 +- .../Models/ObfuscationSettings.cs | 1 + 9 files changed, 82 insertions(+), 55 deletions(-) create mode 100644 src/BitMono.Core/Attributes/ConfigureForNativeCodeAttribute.cs diff --git a/src/BitMono.Core/Attributes/ConfigureForNativeCodeAttribute.cs b/src/BitMono.Core/Attributes/ConfigureForNativeCodeAttribute.cs new file mode 100644 index 00000000..2e185707 --- /dev/null +++ b/src/BitMono.Core/Attributes/ConfigureForNativeCodeAttribute.cs @@ -0,0 +1,10 @@ +namespace BitMono.Core.Attributes; + +/// +/// This is necessary to make native code work inside the assembly. +/// See more here: https://docs.washi.dev/asmresolver/guides/dotnet/unmanaged-method-bodies.html +/// However, sometimes it causes issues with the assembly like , +/// that's why you need to manually mark your with . +/// +[AttributeUsage(AttributeTargets.Class, Inherited = false)] +public class ConfigureForNativeCodeAttribute : Attribute; \ No newline at end of file diff --git a/src/BitMono.Core/Contexts/ProtectionContext.cs b/src/BitMono.Core/Contexts/ProtectionContext.cs index 3a53173d..c5963f54 100644 --- a/src/BitMono.Core/Contexts/ProtectionContext.cs +++ b/src/BitMono.Core/Contexts/ProtectionContext.cs @@ -26,27 +26,4 @@ public void ThrowIfCancellationTokenRequested() { CancellationToken.ThrowIfCancellationRequested(); } - /// - /// This is necessary to make native code work inside the assembly. - /// See more here: https://docs.washi.dev/asmresolver/guides/dotnet/unmanaged-method-bodies.html - /// However, sometimes it causes issues with the assembly like `System.BadImageFormatException` - /// at the end when running the protected file, so that's why it's here but not at some startup point. - /// - public void ConfigureForNativeCode() - { - Module.IsILOnly = false; - var x64 = Module.MachineType == MachineType.Amd64; - if (x64) - { - Module.PEKind = OptionalHeaderMagic.PE32Plus; - Module.MachineType = MachineType.Amd64; - Module.IsBit32Required = false; - } - else - { - Module.PEKind = OptionalHeaderMagic.PE32; - Module.MachineType = MachineType.I386; - Module.IsBit32Required = true; - } - } } \ No newline at end of file diff --git a/src/BitMono.Core/Extensions/ProtectionExtensions.cs b/src/BitMono.Core/Extensions/ProtectionExtensions.cs index afad8d1e..e1b4c844 100644 --- a/src/BitMono.Core/Extensions/ProtectionExtensions.cs +++ b/src/BitMono.Core/Extensions/ProtectionExtensions.cs @@ -35,6 +35,16 @@ public static RuntimeMonikerAttribute[] GetRuntimeMonikerAttributes(this IProtec .GetType() .GetRuntimeMonikerAttributes(); } + public static ConfigureForNativeCodeAttribute? GetConfigureForNativeCodeAttribute(this Type source, bool inherit = false) + { + return source.GetCustomAttribute(inherit); + } + public static ConfigureForNativeCodeAttribute? GetConfigureForNativeCodeAttribute(this IProtection source) + { + return source + .GetType() + .GetConfigureForNativeCodeAttribute(); + } public static bool TryGetObsoleteAttribute(this Type source, out ObsoleteAttribute? attribute, bool inherit = false) { attribute = source.GetCustomAttribute(inherit); diff --git a/src/BitMono.Host/BitMonoApplication.cs b/src/BitMono.Host/BitMonoApplication.cs index d69f4115..18f1e17e 100644 --- a/src/BitMono.Host/BitMonoApplication.cs +++ b/src/BitMono.Host/BitMonoApplication.cs @@ -8,7 +8,7 @@ public class BitMonoApplication : IApplication public BitMonoApplication() { _containerBuilder = new ContainerBuilder(); - _modules = new List(); + _modules = []; } public IApplication Populate(IEnumerable descriptors) diff --git a/src/BitMono.Host/obfuscation.json b/src/BitMono.Host/obfuscation.json index 3f5bbe26..0f14aa69 100644 --- a/src/BitMono.Host/obfuscation.json +++ b/src/BitMono.Host/obfuscation.json @@ -67,6 +67,10 @@ // Set to true indicates whether enabled "OutputRuntimeMonikerWarnings": true, + // Output warnings saying that protection is requires native code configuration + // Set to true indicates whether enabled + "OutputConfigureForNativeCodeWarnings": true, + // Opens directory with protected file in file explorer in top of the screen, if set to true "OpenFileDestinationInFileExplorer": true, diff --git a/src/BitMono.Obfuscation/BitMonoObfuscator.cs b/src/BitMono.Obfuscation/BitMonoObfuscator.cs index 519355a9..52c24ff0 100644 --- a/src/BitMono.Obfuscation/BitMonoObfuscator.cs +++ b/src/BitMono.Obfuscation/BitMonoObfuscator.cs @@ -6,11 +6,12 @@ public class BitMonoObfuscator private readonly StarterContext _context; private readonly IDataWriter _dataWriter; private readonly ObfuscationSettings _obfuscationSettings; - private readonly InvokablePipeline _invokablePipeline; + private readonly InvokablePipeline _pipeline; private readonly ObfuscationAttributeResolver _obfuscationAttributeResolver; private readonly ObfuscationAttributesStripper _obfuscationAttributesStripper; private readonly ObfuscationAttributesStripNotifier _obfuscationAttributesStripNotifier; private readonly ProtectionsNotifier _protectionsNotifier; + private readonly ProtectionsConfigureForNativeCodeNotifier _protectionsConfigureForNativeCodeNotifier; private readonly ProtectionExecutionNotifier _protectionExecutionNotifier; private readonly ILogger _logger; private ProtectionsSort? _protectionsSort; @@ -28,7 +29,7 @@ public BitMonoObfuscator( _context = context; _dataWriter = dataWriter; _obfuscationSettings = obfuscationSettings; - _invokablePipeline = new InvokablePipeline(); + _pipeline = new InvokablePipeline(); _obfuscationAttributeResolver = _serviceProvider.GetRequiredService(); var obfuscateAssemblyAttributeResolver = _serviceProvider.GetRequiredService(); _obfuscationAttributesStripper = new ObfuscationAttributesStripper( @@ -36,6 +37,7 @@ public BitMonoObfuscator( _logger = logger.ForContext(); _obfuscationAttributesStripNotifier = new ObfuscationAttributesStripNotifier(_logger); _protectionsNotifier = new ProtectionsNotifier(_obfuscationSettings, _logger); + _protectionsConfigureForNativeCodeNotifier = new ProtectionsConfigureForNativeCodeNotifier(_obfuscationSettings, _logger); _protectionExecutionNotifier = new ProtectionExecutionNotifier(_logger); } @@ -43,23 +45,24 @@ public async Task ProtectAsync() { _context.ThrowIfCancellationRequested(); - _invokablePipeline.OnFail += OnFailHandleAsync; + _pipeline.OnFail += OnFailHandleAsync; - await _invokablePipeline.InvokeAsync(OutputLoadedModule); - await _invokablePipeline.InvokeAsync(OutputBitMonoInfo); - await _invokablePipeline.InvokeAsync(OutputCompatibilityIssues); - await _invokablePipeline.InvokeAsync(SortProtections); - await _invokablePipeline.InvokeAsync(OutputProtectionsAsync); - await _invokablePipeline.InvokeAsync(StartTimeCounter); - await _invokablePipeline.InvokeAsync(ResolveDependencies); - await _invokablePipeline.InvokeAsync(ExpandMacros); - await _invokablePipeline.InvokeAsync(RunProtectionsAsync); - await _invokablePipeline.InvokeAsync(OptimizeMacros); - await _invokablePipeline.InvokeAsync(StripObfuscationAttributes); - await _invokablePipeline.InvokeAsync(CreatePEImage); - await _invokablePipeline.InvokeAsync(WriteModuleAsync); - await _invokablePipeline.InvokeAsync(PackAsync); - await _invokablePipeline.InvokeAsync(OutputElapsedTime); + await _pipeline.InvokeAsync(OutputLoadedModule); + await _pipeline.InvokeAsync(OutputBitMonoInfo); + await _pipeline.InvokeAsync(OutputCompatibilityIssues); + await _pipeline.InvokeAsync(SortProtections); + await _pipeline.InvokeAsync(OutputProtectionsAsync); + await _pipeline.InvokeAsync(ConfigureForNativeCode); + await _pipeline.InvokeAsync(StartTimeCounter); + await _pipeline.InvokeAsync(ResolveDependencies); + await _pipeline.InvokeAsync(ExpandMacros); + await _pipeline.InvokeAsync(RunProtectionsAsync); + await _pipeline.InvokeAsync(OptimizeMacros); + await _pipeline.InvokeAsync(StripObfuscationAttributes); + await _pipeline.InvokeAsync(CreatePEImage); + await _pipeline.InvokeAsync(WriteModuleAsync); + await _pipeline.InvokeAsync(PackAsync); + await _pipeline.InvokeAsync(OutputElapsedTime); } private void OutputLoadedModule() @@ -89,11 +92,11 @@ private void OutputBitMonoInfo() /// but BitMono is running on .NET Core, or vice versa. /// See more info: https://bitmono.readthedocs.io/en/latest/obfuscationissues/corlib-not-found.html /// - private bool OutputCompatibilityIssues() + private void OutputCompatibilityIssues() { if (_context.Module.Assembly!.TryGetTargetFramework(out var targetAssemblyRuntime) == false) { - return true; + return; } if (targetAssemblyRuntime.IsNetCoreApp && DotNetRuntimeInfoEx.IsNetFramework()) { @@ -101,7 +104,7 @@ private bool OutputCompatibilityIssues() "The module is built for .NET (Core), but you're using a version of BitMono intended for .NET Framework." + " To avoid potential issues, ensure the target framework matches the BitMono framework, " + "or switch to a .NET Core build of BitMono."); - return true; + return; } if (targetAssemblyRuntime.IsNetFramework && DotNetRuntimeInfoEx.IsNetCoreOrLater()) { @@ -109,8 +112,8 @@ private bool OutputCompatibilityIssues() "The module is built for .NET Framework, but you're using a version of BitMono intended for .NET (Core)." + " To avoid potential issues, ensure the target framework matches the BitMono framework, " + "or switch to a .NET Framework build of BitMono."); + return; } - return true; } private bool SortProtections() { @@ -137,6 +140,31 @@ private bool OutputProtectionsAsync() _protectionsNotifier.Notify(_protectionsSort, _context.CancellationToken); return true; } + private void ConfigureForNativeCode() + { + if (_protectionsSort!.ConfigureForNativeCodeProtections.Any() == false) + { + return; + } + + _protectionsConfigureForNativeCodeNotifier.Notify(_protectionsSort); + + var module = _context.Module; + module.IsILOnly = false; + var x64 = module.MachineType == MachineType.Amd64; + if (x64) + { + module.PEKind = OptionalHeaderMagic.PE32Plus; + module.MachineType = MachineType.Amd64; + module.IsBit32Required = false; + } + else + { + module.PEKind = OptionalHeaderMagic.PE32; + module.MachineType = MachineType.I386; + module.IsBit32Required = true; + } + } private void StartTimeCounter() { _startTime = Stopwatch.GetTimestamp(); @@ -171,7 +199,7 @@ private bool ResolveDependencies() } return true; } - private bool ExpandMacros() + private void ExpandMacros() { foreach (var method in _context.Module.FindMembers().OfType()) { @@ -184,9 +212,8 @@ private bool ExpandMacros() body.Instructions.ExpandMacros(); } - return true; } - private async Task RunProtectionsAsync() + private async Task RunProtectionsAsync() { _logger.Information("Executing Protections... this could take for a while..."); if (_protectionsSort == null) @@ -215,9 +242,8 @@ private async Task RunProtectionsAsync() _protectionExecutionNotifier.Notify(phase); } } - return true; } - private bool OptimizeMacros() + private void OptimizeMacros() { foreach (var method in _context.Module.FindMembers().OfType()) { @@ -225,12 +251,11 @@ private bool OptimizeMacros() if (method.CilMethodBody is not { } body) { - return true; + continue; } body.Instructions.OptimizeMacros(); } - return true; } private void StripObfuscationAttributes() { diff --git a/src/BitMono.Obfuscation/GlobalUsings.cs b/src/BitMono.Obfuscation/GlobalUsings.cs index 65ea7c4e..c044cc7c 100644 --- a/src/BitMono.Obfuscation/GlobalUsings.cs +++ b/src/BitMono.Obfuscation/GlobalUsings.cs @@ -20,6 +20,7 @@ global using AsmResolver.PE.File; global using BitMono.API; global using BitMono.API.Protections; +global using BitMono.Core.Attributes; global using BitMono.Core.Contexts; global using BitMono.Core.Pipeline; global using BitMono.Core.Resolvers; diff --git a/src/BitMono.Protections/UnmanagedString.cs b/src/BitMono.Protections/UnmanagedString.cs index 348bb308..1c365547 100644 --- a/src/BitMono.Protections/UnmanagedString.cs +++ b/src/BitMono.Protections/UnmanagedString.cs @@ -1,5 +1,6 @@ namespace BitMono.Protections; +[ConfigureForNativeCode] [RuntimeMonikerNETCore] [RuntimeMonikerNETFramework] public class UnmanagedString : Protection @@ -10,8 +11,6 @@ public UnmanagedString(IServiceProvider serviceProvider) : base(serviceProvider) public override Task ExecuteAsync() { - Context.ConfigureForNativeCode(); - var moduleImporter = Context.ModuleImporter; var stringSbytePointerCtor = moduleImporter.ImportMethod(typeof(string).GetConstructor(new[] { typeof(sbyte*) })!); diff --git a/src/BitMono.Shared/Models/ObfuscationSettings.cs b/src/BitMono.Shared/Models/ObfuscationSettings.cs index ee882634..7cc0bb65 100644 --- a/src/BitMono.Shared/Models/ObfuscationSettings.cs +++ b/src/BitMono.Shared/Models/ObfuscationSettings.cs @@ -17,6 +17,7 @@ public class ObfuscationSettings public bool OutputPEImageBuildErrors { get; set; } public bool FailOnNoRequiredDependency { get; set; } public bool OutputRuntimeMonikerWarnings { get; set; } + public bool OutputConfigureForNativeCodeWarnings { get; set; } public bool OpenFileDestinationInFileExplorer { get; set; } public bool SpecificNamespacesObfuscationOnly { get; set; } public string[]? SpecificNamespaces { get; set; } From 866ab46db5bc25d34153e2de28fc0e10be2c4b4a Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 25 Aug 2024 11:50:39 +0300 Subject: [PATCH 03/10] Refactor tests --- test/BitMono.Obfuscation.Tests/GlobalUsings.cs | 1 + .../Referencing/CosturaReferencesDataResolverTest.cs | 12 +++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/test/BitMono.Obfuscation.Tests/GlobalUsings.cs b/test/BitMono.Obfuscation.Tests/GlobalUsings.cs index 03ef1bbf..b0132bf8 100644 --- a/test/BitMono.Obfuscation.Tests/GlobalUsings.cs +++ b/test/BitMono.Obfuscation.Tests/GlobalUsings.cs @@ -1,4 +1,5 @@ global using System.Linq; +global using System.Threading; global using AsmResolver.DotNet; global using BitMono.Obfuscation.Referencing; global using BitMono.Utilities.AsmResolver; diff --git a/test/BitMono.Obfuscation.Tests/Referencing/CosturaReferencesDataResolverTest.cs b/test/BitMono.Obfuscation.Tests/Referencing/CosturaReferencesDataResolverTest.cs index 3da7568b..774d52bf 100644 --- a/test/BitMono.Obfuscation.Tests/Referencing/CosturaReferencesDataResolverTest.cs +++ b/test/BitMono.Obfuscation.Tests/Referencing/CosturaReferencesDataResolverTest.cs @@ -3,21 +3,19 @@ public class CosturaReferencesDataResolverTest { [Fact] - public void - WhenCosturaReferencesDataResolving_AndModuleHasCostura_ThenCountOfReferencesShouldHaveCountAsInModule() + public void CheckSameAmountOfCostura() { var resolver = new CosturaReferencesDataResolver(); var module = ModuleDefinition.FromFile(typeof(TestCases.CosturaDecompressor.Program).Assembly.Location); - var countOfEmbeddedCosturaResources = module.Resources.Count(r => r.IsEmbeddedCosturaResource()); + var countOfEmbeddedCosturaResources = module.Resources.Count(x => x.IsEmbeddedCosturaResource()); - var result = resolver.Resolve(module); + var result = resolver.Resolve(module, CancellationToken.None); result .Should() .NotBeEmpty().And .HaveCount(countOfEmbeddedCosturaResources); } - [Theory] [InlineData("costura.asmresolver.dll.compressed")] [InlineData("costura.asmresolver.pe.dll.compressed")] @@ -32,11 +30,11 @@ public void [InlineData("costura.microsoft.extensions.logging.dll.compressed")] [InlineData("costura.microsoft.extensions.options.dll.compressed")] [InlineData("costura.microsoft.extensions.primitives.dll.compressed")] - public void WhenIsEmbeddedCosturaResource_AndResourceIsCostura_ThenShouldBeTrue(string costuraResourceName) + public void FindCosturaResource(string costuraResourceName) { var module = ModuleDefinition.FromFile(typeof(TestCases.CosturaDecompressor.Program).Assembly.Location); - var result = module.Resources.First(r => r.Name.Value.Equals(costuraResourceName)); + var result = module.Resources.First(x => x.Name.Value.Equals(costuraResourceName)); result .IsEmbeddedCosturaResource() From a4781a8606a086fb8cf05a6e63ad1653faa3d6ed Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 25 Aug 2024 11:51:14 +0300 Subject: [PATCH 04/10] Add info about BitMono usage in readme --- README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4521d77c..ec8e8da3 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ [![MIT License][image_license]][license] [![BitMono Discord][image_bitmono_discord]][bitmono_discord] -BitMono is a free, open-source C# obfuscator designed mainly for Mono, a version of the .NET framework used by Unity and other platforms. You can use it with the full .NET framework, but some features might not work as expected. Some protections work with .NET Core but not Mono. +BitMono is a free, open-source C# obfuscator that was initially designed and intended mainly for Mono, however, now you're feel free to use it for any .NET app, but, be careful some protections work on .NET Framework, some on .NET, some on Mono, some on Unity only. -BitMono uses [AsmResolver][asmresolver] instead of dnlib for handling assemblies. If you have questions or issues, please let us know [here][bitmono_issues]. Download the latest version of BitMono [here][bitmono_releases]. +BitMono uses [AsmResolver][asmresolver] instead of [dnlib][dnlib] (which we used in the past) for handling assemblies. If you have questions or issues, please let us know [here][bitmono_issues]. Download the latest version of BitMono [here][bitmono_releases]. You can also use BitMono as an engine to build custom obfuscators. It is built using dependency injection (DI) using Autofac and follows the latest C# best practices. @@ -83,6 +83,16 @@ Read the **[docs][bitmono_docs]** to read protection, functionality, and more. ## Usage +### Download + +Go and get [Latest BitMono Release][bitmono_latest_release] and download preferred archive file, and make sure to select the similar or same Target Framework of the app that you are going to protect, for example: + +- Your Target File is for .NET 8 then use BitMono for .NET 8 `BitMono-v0.25.3+e64e54d3-CLI-net8.0-win-x64.zip` +- Your Target File is for .netstandard then use BitMono for .NET Framework or .NET 8 `BitMono-v0.25.3+e64e54d3-CLI-net8.0-win-x64.zip` +- Your Target File is .NET Framework then use BitMono for .NET Framework `BitMono-v0.25.3+e64e54d3-CLI-net462-win-x64.zip` + +If you select wrong BitMono build you have a risk that your file going to be protected incorrectly, because you use different target framework build. + ### Pre-Require Set one of setting from `protections.json` to `true`. @@ -188,6 +198,7 @@ Credits [license]: https://github.com/sunnamed434/BitMono/blob/main/LICENSE [previews]: https://github.com/sunnamed434/BitMono/blob/main/PREVIEWS.md [asmresolver]: https://github.com/Washi1337/AsmResolver +[dnlib]: https://github.com/0xd4d/dnlib [bitmono_issues]: https://github.com/sunnamed434/BitMono/issues [bitmono_releases]: https://github.com/sunnamed434/BitMono/releases [bitmono_docs]: https://bitmono.readthedocs.io/en/latest/ @@ -207,6 +218,7 @@ Credits [author_kao_blog]: https://lifeinhex.com/ [author_drakonia]: https://github.com/dr4k0nia [author_sunnamed434]: https://github.com/sunnamed434 +[bitmono_latest_release]: https://github.com/sunnamed434/BitMono/releases/latest [bitmono_discord]: https://discord.gg/sFDHd47St4 [troubleshooting]: https://github.com/sunnamed434/BitMono/blob/main/troubleshooting.md From 736dd161b8ca38692068270916f8710555406b36 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 25 Aug 2024 11:51:58 +0300 Subject: [PATCH 05/10] Refactoring --- .editorconfig | 10 ++++- docs/source/developers/native-code.rst | 15 +++++++ .../obfuscation-execution-order.rst | 23 +++++----- .../faq/unable-to-reference-after-protect.rst | 14 ++++-- docs/source/index.rst | 1 + src/BitMono.API/Protections/IPacker.cs | 4 +- .../Protections/IPhaseProtection.cs | 4 +- .../Analyzing/ReflectionCriticalAnalyzer.cs | 2 +- .../Attributes/RuntimeMonikerAttribute.cs | 2 +- .../Attributes/RuntimeMonikerMonoAttribute.cs | 2 +- .../Attributes/RuntimeMonikerNETCore.cs | 2 +- .../Attributes/RuntimeMonikerNETFramework.cs | 2 +- ...otectionsConfigureForNativeCodeNotifier.cs | 28 ++++++++++++ .../Notifiers/ProtectionsNotifier.cs | 10 ++--- .../ProtectionsRuntimeMonikerNotifier.cs | 22 +++------- .../Protections/ProtectionsSort.cs | 44 ++++++++++++++++--- .../Protections/ProtectionsSorter.cs | 42 +++++++++++------- .../AutomaticPathReferencesDataResolver.cs | 7 ++- .../AutomaticReferencesDataResolver.cs | 4 +- .../CosturaReferencesDataResolver.cs | 26 ++++++----- .../Referencing/IReferencesDataResolver.cs | 2 +- .../Referencing/ReferencesDataResolver.cs | 7 +-- .../Starter/BitMonoContextFactory.cs | 4 +- .../Starter/BitMonoStarter.cs | 5 +-- .../AsmResolver/ModuleDefinitionExtensions.cs | 1 - 25 files changed, 180 insertions(+), 103 deletions(-) create mode 100644 docs/source/developers/native-code.rst create mode 100644 src/BitMono.Obfuscation/Notifiers/ProtectionsConfigureForNativeCodeNotifier.cs diff --git a/.editorconfig b/.editorconfig index 6c787df3..ad72d3f9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,4 +11,12 @@ indent_style = space [*.{proj,csproj,vbproj,props,targets,resx,vsixmanifest}] indent_size = 2 -indent_style = space \ No newline at end of file +indent_style = space + +[*.cs] +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0290 +csharp_style_prefer_primary_constructors = false +dotnet_diagnostic.IDE0290.severity = none + +# https://www.jetbrains.com/help/rider/ConvertToPrimaryConstructor.html +resharper_convert_to_primary_constructor_highlighting = none \ No newline at end of file diff --git a/docs/source/developers/native-code.rst b/docs/source/developers/native-code.rst new file mode 100644 index 00000000..03e72bde --- /dev/null +++ b/docs/source/developers/native-code.rst @@ -0,0 +1,15 @@ +Native Code +########### + +If you want to use a native code in the protection you must do the following: + + +.. code-block:: csharp + + [ConfigureForNativeCode] // Add this attribute on top of the protection class + public class CustomProtection : Protection + + +A good example is ``UnmanagedString`` protection. It uses native code to encrypt strings. You can find the source code in the ``UnmanagedString`` file. + +This thing is so important to do, before actually it was automatically done before the obfuscation without any attributes, however we found that this might break an app, because it changes the architecture of the app, so we decided to make it optional. \ No newline at end of file diff --git a/docs/source/developers/obfuscation-execution-order.rst b/docs/source/developers/obfuscation-execution-order.rst index 5e4436c8..96a38930 100644 --- a/docs/source/developers/obfuscation-execution-order.rst +++ b/docs/source/developers/obfuscation-execution-order.rst @@ -7,11 +7,12 @@ BitMono uses its own obfuscation execution order which is good to be known, and 2. Output Information about BitMono (example, is it intended for .NET Core or Mono or .NET Framework, etc.) and running OS, etc. 3. Output Compatibility Issues in case of module is built for .NET Framework, but BitMono is running on .NET Core, or vice versa. 4. Sort Protections -5. Basic output information about Protections -6. Elapsed time counter -7. Resolve References -8. Expand Macros -10. Run Protection, PipelineProtection and child pipeline protections +5. Information about Protections +6. Configuration for Native Code +7. Elapsed time counter +8. Resolve References +9. Expand Macros +11. Run Protection, PipelineProtection and child pipeline protections .. code-block:: csharp @@ -21,11 +22,11 @@ BitMono uses its own obfuscation execution order which is good to be known, and public class Pipeline : PipelineProtection -11. Optimize Macros -12. [ObfuscationAttribute] cleanup -13. Create PE Image -14. Write Module -15. Run Packers +12. Optimize Macros +13. [ObfuscationAttribute] cleanup +14 Create PE Image +15. Write Module +16. Run Packers .. code-block:: csharp @@ -33,4 +34,4 @@ BitMono uses its own obfuscation execution order which is good to be known, and public class Packer : PackerProtection -16. Output Elapsed Time since obfuscation \ No newline at end of file +17. Output Elapsed Time since obfuscation \ No newline at end of file diff --git a/docs/source/faq/unable-to-reference-after-protect.rst b/docs/source/faq/unable-to-reference-after-protect.rst index 56f51d77..157146a0 100644 --- a/docs/source/faq/unable-to-reference-after-protect.rst +++ b/docs/source/faq/unable-to-reference-after-protect.rst @@ -1,4 +1,12 @@ -Unable to reference after protect? -================================== +Unable to Reference After Protection +==================================== -You're probably stuck on a problem, when you want to use your ``.dll`` after protection, you protect it via BitMono and try to reference it in IDE or whatever else, you're doing a bit wrong, you need to have an original copy and use it as a reference, and as output folder (i.e Release\...) drop there a protected version of your ``.dll``. \ No newline at end of file +If you're having trouble referencing your ``.dll`` file after protecting it with BitMono, follow these steps: + +1. **Keep an Original Copy**: Always keep an original, unprotected copy of your ``.dll`` file. This will be used as a reference in your IDE or other tools. + +2. **Protect the DLL**: Use BitMono to protect your ``.dll`` file. + +3. **Set Up Output Folder**: In your output folder (e.g., ``Release\...``), place the protected version of your ``.dll`` file. + +By following these steps, you can ensure that your project references the original ``.dll`` while deploying the protected version. \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index 22db563e..d71af2a1 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -43,6 +43,7 @@ Table of Contents: developers/obfuscation-execution-order developers/which-base-protection-select developers/protection-runtime-moniker + developers/native-code developers/do-not-resolve-members developers/configuration diff --git a/src/BitMono.API/Protections/IPacker.cs b/src/BitMono.API/Protections/IPacker.cs index 80811f62..70063989 100644 --- a/src/BitMono.API/Protections/IPacker.cs +++ b/src/BitMono.API/Protections/IPacker.cs @@ -1,5 +1,3 @@ namespace BitMono.API.Protections; -public interface IPacker : IProtection -{ -} \ No newline at end of file +public interface IPacker : IProtection; \ No newline at end of file diff --git a/src/BitMono.API/Protections/IPhaseProtection.cs b/src/BitMono.API/Protections/IPhaseProtection.cs index 86defffd..21fddb52 100644 --- a/src/BitMono.API/Protections/IPhaseProtection.cs +++ b/src/BitMono.API/Protections/IPhaseProtection.cs @@ -1,5 +1,3 @@ namespace BitMono.API.Protections; -public interface IPhaseProtection : IProtection -{ -} \ No newline at end of file +public interface IPhaseProtection : IProtection; \ No newline at end of file diff --git a/src/BitMono.Core/Analyzing/ReflectionCriticalAnalyzer.cs b/src/BitMono.Core/Analyzing/ReflectionCriticalAnalyzer.cs index 9ec0b673..c2a82535 100644 --- a/src/BitMono.Core/Analyzing/ReflectionCriticalAnalyzer.cs +++ b/src/BitMono.Core/Analyzing/ReflectionCriticalAnalyzer.cs @@ -17,7 +17,7 @@ public class ReflectionCriticalAnalyzer : ICriticalAnalyzer public ReflectionCriticalAnalyzer(IOptions obfuscation) { _obfuscationSettings = obfuscation.Value; - _cachedMethods = new List(); + _cachedMethods = []; } public IReadOnlyList CachedMethods => _cachedMethods.AsReadOnly(); diff --git a/src/BitMono.Core/Attributes/RuntimeMonikerAttribute.cs b/src/BitMono.Core/Attributes/RuntimeMonikerAttribute.cs index b0205e75..482fa080 100644 --- a/src/BitMono.Core/Attributes/RuntimeMonikerAttribute.cs +++ b/src/BitMono.Core/Attributes/RuntimeMonikerAttribute.cs @@ -2,7 +2,7 @@ namespace BitMono.Core.Attributes; /// /// Represents a mechanism that specifies the runtime moniker of the protection. -/// i.e if you see this attribute on protection, then only specified attributes are the supported runtime monikers for the protection. +/// i.e. if you see this attribute on protection, then only specified attributes are the supported runtime monikers for the protection. /// If you don't see any of the attributes, then it works everywhere, also, users will get a message via /// [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = true)] diff --git a/src/BitMono.Core/Attributes/RuntimeMonikerMonoAttribute.cs b/src/BitMono.Core/Attributes/RuntimeMonikerMonoAttribute.cs index f8327568..f7aff72d 100644 --- a/src/BitMono.Core/Attributes/RuntimeMonikerMonoAttribute.cs +++ b/src/BitMono.Core/Attributes/RuntimeMonikerMonoAttribute.cs @@ -5,7 +5,7 @@ namespace BitMono.Core.Attributes; /// i.e if you see this attribute on protection then only specified attributes are the supported runtime monikers for the protection. /// If you don't see any of the attributes then it works everywhere, also, users will get a message via /// -[AttributeUsage(AttributeTargets.Class, Inherited = false)] +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public class RuntimeMonikerMonoAttribute : RuntimeMonikerAttribute { public RuntimeMonikerMonoAttribute() : base(KnownRuntimeMonikers.Mono) diff --git a/src/BitMono.Core/Attributes/RuntimeMonikerNETCore.cs b/src/BitMono.Core/Attributes/RuntimeMonikerNETCore.cs index 1c1225db..30d16456 100644 --- a/src/BitMono.Core/Attributes/RuntimeMonikerNETCore.cs +++ b/src/BitMono.Core/Attributes/RuntimeMonikerNETCore.cs @@ -1,6 +1,6 @@ namespace BitMono.Core.Attributes; -[AttributeUsage(AttributeTargets.Class, Inherited = false)] +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public class RuntimeMonikerNETCore : RuntimeMonikerAttribute { public RuntimeMonikerNETCore() : base(KnownRuntimeMonikers.NETCore) diff --git a/src/BitMono.Core/Attributes/RuntimeMonikerNETFramework.cs b/src/BitMono.Core/Attributes/RuntimeMonikerNETFramework.cs index d8aa9975..58158703 100644 --- a/src/BitMono.Core/Attributes/RuntimeMonikerNETFramework.cs +++ b/src/BitMono.Core/Attributes/RuntimeMonikerNETFramework.cs @@ -1,6 +1,6 @@ namespace BitMono.Core.Attributes; -[AttributeUsage(AttributeTargets.Class, Inherited = false)] +[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] public class RuntimeMonikerNETFramework : RuntimeMonikerAttribute { public RuntimeMonikerNETFramework() : base(KnownRuntimeMonikers.NETFramework) diff --git a/src/BitMono.Obfuscation/Notifiers/ProtectionsConfigureForNativeCodeNotifier.cs b/src/BitMono.Obfuscation/Notifiers/ProtectionsConfigureForNativeCodeNotifier.cs new file mode 100644 index 00000000..c8b73f2c --- /dev/null +++ b/src/BitMono.Obfuscation/Notifiers/ProtectionsConfigureForNativeCodeNotifier.cs @@ -0,0 +1,28 @@ +namespace BitMono.Obfuscation.Notifiers; + +public class ProtectionsConfigureForNativeCodeNotifier +{ + private readonly ObfuscationSettings _obfuscationSettings; + private readonly ILogger _logger; + + public ProtectionsConfigureForNativeCodeNotifier(ObfuscationSettings obfuscationSettings, ILogger logger) + { + _obfuscationSettings = obfuscationSettings; + _logger = logger.ForContext(); + } + + public void Notify(ProtectionsSort protectionsSort) + { + if (_obfuscationSettings.OutputConfigureForNativeCodeWarnings == false) + { + return; + } + if (protectionsSort.ConfigureForNativeCodeProtections.Any() == false) + { + return; + } + + _logger.Warning( + "Enabled protections may create native code configurations, which can sometimes break the app. Proceed with caution. If issues arise, disable the following protections."); + } +} \ No newline at end of file diff --git a/src/BitMono.Obfuscation/Notifiers/ProtectionsNotifier.cs b/src/BitMono.Obfuscation/Notifiers/ProtectionsNotifier.cs index 06791f9d..4b9bed49 100644 --- a/src/BitMono.Obfuscation/Notifiers/ProtectionsNotifier.cs +++ b/src/BitMono.Obfuscation/Notifiers/ProtectionsNotifier.cs @@ -34,12 +34,12 @@ public void Notify(ProtectionsSort protectionsSort, CancellationToken cancellati stringBuilder.Append(", "); stringBuilder.Append(string.Join(", ", protectionsSort.Packers.Select(x => x.GetName()))); } - var enabledProtectionsCount = protectionsSort.SortedProtections.Count() - + protectionsSort.Pipelines.Count() - + protectionsSort.Packers.Count(); + var enabledProtectionsCount = protectionsSort.SortedProtections.Count + + protectionsSort.Pipelines.Count + + protectionsSort.Packers.Count; _logger.Information("({0}) Enabled protection(s): {1}", enabledProtectionsCount, stringBuilder.ToString()); - var runtimeMonikerNotifier = new ProtectionsRuntimeMonikerNotifier(_obfuscationSettings, protectionsSort, _logger); - runtimeMonikerNotifier.Notify(cancellationToken); + var runtimeMonikerNotifier = new ProtectionsRuntimeMonikerNotifier(_obfuscationSettings, _logger); + runtimeMonikerNotifier.Notify(protectionsSort, cancellationToken); if (protectionsSort.DeprecatedProtections.Any()) { _logger.Warning("Skip deprecated protection(s): {0}", string.Join(", ", protectionsSort.DeprecatedProtections.Select(p => p?.GetName()))); diff --git a/src/BitMono.Obfuscation/Notifiers/ProtectionsRuntimeMonikerNotifier.cs b/src/BitMono.Obfuscation/Notifiers/ProtectionsRuntimeMonikerNotifier.cs index c3789f26..e98d1dd9 100644 --- a/src/BitMono.Obfuscation/Notifiers/ProtectionsRuntimeMonikerNotifier.cs +++ b/src/BitMono.Obfuscation/Notifiers/ProtectionsRuntimeMonikerNotifier.cs @@ -3,31 +3,22 @@ namespace BitMono.Obfuscation.Notifiers; public class ProtectionsRuntimeMonikerNotifier { private readonly ObfuscationSettings _obfuscationSettings; - private readonly ProtectionsSort _protectionsSort; private readonly ILogger _logger; - public ProtectionsRuntimeMonikerNotifier(ObfuscationSettings obfuscationSettings, ProtectionsSort protectionsSort, ILogger logger) + public ProtectionsRuntimeMonikerNotifier(ObfuscationSettings obfuscationSettings, ILogger logger) { _obfuscationSettings = obfuscationSettings; - _protectionsSort = protectionsSort; _logger = logger.ForContext(); } - public void Notify(CancellationToken cancellationToken) + public void Notify(ProtectionsSort protectionsSort, CancellationToken cancellationToken) { if (_obfuscationSettings.OutputRuntimeMonikerWarnings == false) { return; } - - var protectionsWithAttributes = _protectionsSort.SortedProtections - .Concat(_protectionsSort.Pipelines) - .Concat(_protectionsSort.Packers) - .Select(x => new { Protection = x, Attributes = x.GetRuntimeMonikerAttributes() }) - .Where(x => x.Attributes.Length > 0) - .ToList(); - - if (protectionsWithAttributes.Count == 0) + var runtimeMonikerProtections = protectionsSort.RuntimeMonikerProtections; + if (runtimeMonikerProtections.Count == 0) { return; } @@ -35,13 +26,10 @@ public void Notify(CancellationToken cancellationToken) _logger.Warning( "Protections marked as \"Intended for ...\" are designed for specific runtimes. Using them with other runtimes may cause crashes or other issues. Proceed with caution."); - foreach (var item in protectionsWithAttributes) + foreach (var (protection, attributes) in runtimeMonikerProtections) { cancellationToken.ThrowIfCancellationRequested(); - var protection = item.Protection; - var attributes = item.Attributes; - foreach (var runtimeMonikerAttribute in attributes) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/src/BitMono.Obfuscation/Protections/ProtectionsSort.cs b/src/BitMono.Obfuscation/Protections/ProtectionsSort.cs index b9cbce51..a37a1496 100644 --- a/src/BitMono.Obfuscation/Protections/ProtectionsSort.cs +++ b/src/BitMono.Obfuscation/Protections/ProtectionsSort.cs @@ -2,13 +2,43 @@ public class ProtectionsSort { + public ProtectionsSort( + ProtectionsResolve protectionsResolve, + IReadOnlyCollection allProtections, + IReadOnlyCollection sortedProtections, + IReadOnlyCollection pipelines, + IReadOnlyCollection packers, + IReadOnlyCollection deprecatedProtections, + IReadOnlyCollection obfuscationAttributeExcludeProtections, + IReadOnlyCollection configureForNativeCodeProtections, + IReadOnlyCollection<(IProtection, RuntimeMonikerAttribute[])> runtimeMonikerProtections, + bool hasProtections) + { + ProtectionsResolve = protectionsResolve; + AllProtections = allProtections; + SortedProtections = sortedProtections; + Pipelines = pipelines; + Packers = packers; + DeprecatedProtections = deprecatedProtections; + ObfuscationAttributeExcludeProtections = obfuscationAttributeExcludeProtections; + ConfigureForNativeCodeProtections = configureForNativeCodeProtections; + RuntimeMonikerProtections = runtimeMonikerProtections; + HasProtections = hasProtections; + } + #pragma warning disable CS8618 - public ProtectionsResolve ProtectionsResolve { get; set; } - public IEnumerable SortedProtections { get; set; } - public IEnumerable Pipelines { get; set; } - public IEnumerable Packers { get; set; } - public IEnumerable DeprecatedProtections { get; set; } - public IEnumerable ObfuscationAttributeExcludeProtections { get; set; } - public bool HasProtections { get; set; } + public ProtectionsResolve ProtectionsResolve { get; } + /// + /// Gets a collection of , , and . + /// + public IReadOnlyCollection AllProtections { get; } + public IReadOnlyCollection SortedProtections { get; } + public IReadOnlyCollection Pipelines { get; } + public IReadOnlyCollection Packers { get; } + public IReadOnlyCollection DeprecatedProtections { get; } + public IReadOnlyCollection ObfuscationAttributeExcludeProtections { get; } + public IReadOnlyCollection ConfigureForNativeCodeProtections { get; } + public IReadOnlyCollection<(IProtection, RuntimeMonikerAttribute[])> RuntimeMonikerProtections { get; } + public bool HasProtections { get; } #pragma warning restore CS8618 } \ No newline at end of file diff --git a/src/BitMono.Obfuscation/Protections/ProtectionsSorter.cs b/src/BitMono.Obfuscation/Protections/ProtectionsSorter.cs index fb890b2d..9cff47c8 100644 --- a/src/BitMono.Obfuscation/Protections/ProtectionsSorter.cs +++ b/src/BitMono.Obfuscation/Protections/ProtectionsSorter.cs @@ -14,36 +14,44 @@ public ProtectionsSorter(ObfuscationAttributeResolver obfuscationAttributeResolv [SuppressMessage("ReSharper", "PossibleMultipleEnumeration")] public ProtectionsSort Sort(List protections, IEnumerable protectionSettings) { - var protectionsResolve = new ProtectionsResolver(protections, protectionSettings) - .Sort(); + var protectionsResolve = new ProtectionsResolver(protections, protectionSettings).Sort(); var obfuscationAttributeProtections = - protectionsResolve.FoundProtections.Where(p => - _obfuscationAttributeResolver.Resolve(p.GetName(), _assemblyDefinition)); + protectionsResolve.FoundProtections.Where(x => + _obfuscationAttributeResolver.Resolve(x.GetName(), _assemblyDefinition)); var deprecatedProtections = - protectionsResolve.FoundProtections.Where(p => p.TryGetObsoleteAttribute(out _)); + protectionsResolve.FoundProtections.Where(x => x.TryGetObsoleteAttribute(out _)); var sortedProtections = protectionsResolve.FoundProtections .Except(obfuscationAttributeProtections) .Except(deprecatedProtections); var pipelineProtections = sortedProtections - .Where(p => p is IPipelineProtection) + .Where(x => x is IPipelineProtection) .Cast(); var packers = sortedProtections - .Where(p => p is IPacker) + .Where(x => x is IPacker) .Cast(); sortedProtections = sortedProtections .Except(packers) .Except(pipelineProtections); + var allProtections = sortedProtections.Concat(pipelineProtections).Concat(packers); + + var configureForNativeCodeProtections = allProtections.Where( + x => x.GetConfigureForNativeCodeAttribute() != null); + var runtimeMonikerProtections = allProtections + .Select(x => (x, x.GetRuntimeMonikerAttributes())) + .Where(x => x.Item2.Any()); var hasProtections = sortedProtections.IsEmpty() == false || packers.IsEmpty() == false; - return new ProtectionsSort - { - ProtectionsResolve = protectionsResolve, - SortedProtections = sortedProtections, - Pipelines = pipelineProtections, - Packers = packers, - ObfuscationAttributeExcludeProtections = obfuscationAttributeProtections, - DeprecatedProtections = deprecatedProtections, - HasProtections = hasProtections - }; + + return new ProtectionsSort( + protectionsResolve, + allProtections.ToList(), + sortedProtections.ToList(), + pipelineProtections.ToList(), + packers.ToList(), + obfuscationAttributeProtections.ToList(), + deprecatedProtections.ToList(), + configureForNativeCodeProtections.ToList(), + runtimeMonikerProtections.ToList(), + hasProtections); } } \ No newline at end of file diff --git a/src/BitMono.Obfuscation/Referencing/AutomaticPathReferencesDataResolver.cs b/src/BitMono.Obfuscation/Referencing/AutomaticPathReferencesDataResolver.cs index bf316941..a4deb795 100644 --- a/src/BitMono.Obfuscation/Referencing/AutomaticPathReferencesDataResolver.cs +++ b/src/BitMono.Obfuscation/Referencing/AutomaticPathReferencesDataResolver.cs @@ -11,11 +11,10 @@ public AutomaticPathReferencesDataResolver(string referencesDirectoryPath) _costuraReferencesDataResolver = new CosturaReferencesDataResolver(); } - [SuppressMessage("ReSharper", "ConvertIfStatementToReturnStatement")] - public List Resolve(ModuleDefinition module) + public List Resolve(ModuleDefinition module, CancellationToken cancellationToken) { - var referencesData = _referencesDataResolver.Resolve(module); - var costuraReferencesData = _costuraReferencesDataResolver.Resolve(module); + var referencesData = _referencesDataResolver.Resolve(module, cancellationToken); + var costuraReferencesData = _costuraReferencesDataResolver.Resolve(module, cancellationToken); if (costuraReferencesData.IsEmpty() == false) { referencesData.AddRange(costuraReferencesData); diff --git a/src/BitMono.Obfuscation/Referencing/AutomaticReferencesDataResolver.cs b/src/BitMono.Obfuscation/Referencing/AutomaticReferencesDataResolver.cs index b0498f32..db5e0f40 100644 --- a/src/BitMono.Obfuscation/Referencing/AutomaticReferencesDataResolver.cs +++ b/src/BitMono.Obfuscation/Referencing/AutomaticReferencesDataResolver.cs @@ -11,9 +11,9 @@ public AutomaticReferencesDataResolver(List referencesData) _costuraReferencesDataResolver = new CosturaReferencesDataResolver(); } - public List Resolve(ModuleDefinition module) + public List Resolve(ModuleDefinition module, CancellationToken cancellationToken) { - var costuraReferencesData = _costuraReferencesDataResolver.Resolve(module); + var costuraReferencesData = _costuraReferencesDataResolver.Resolve(module, cancellationToken); costuraReferencesData.AddRange(_referencesData); return costuraReferencesData; } diff --git a/src/BitMono.Obfuscation/Referencing/CosturaReferencesDataResolver.cs b/src/BitMono.Obfuscation/Referencing/CosturaReferencesDataResolver.cs index 4670e00d..a5be330e 100644 --- a/src/BitMono.Obfuscation/Referencing/CosturaReferencesDataResolver.cs +++ b/src/BitMono.Obfuscation/Referencing/CosturaReferencesDataResolver.cs @@ -2,24 +2,26 @@ namespace BitMono.Obfuscation.Referencing; public class CosturaReferencesDataResolver : IReferencesDataResolver { - [SuppressMessage("ReSharper", "ForCanBeConvertedToForeach")] - [SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")] - [SuppressMessage("ReSharper", "InvertIf")] - public List Resolve(ModuleDefinition module) + public List Resolve(ModuleDefinition module, CancellationToken cancellationToken) { var result = new List(); var resources = module.Resources; - for (var i = 0; i < resources.Count; i++) + + foreach (var resource in resources) { - var resource = resources[i]; - if (resource.IsEmbeddedCosturaResource()) + cancellationToken.ThrowIfCancellationRequested(); + + if (resource.IsEmbeddedCosturaResource() == false) { - var rawData = resource.GetData(); - if (rawData != null) - { - result.Add(Decompress(rawData)); - } + continue; } + var rawData = resource.GetData(); + if (rawData == null) + { + continue; + } + + result.Add(Decompress(rawData)); } return result; } diff --git a/src/BitMono.Obfuscation/Referencing/IReferencesDataResolver.cs b/src/BitMono.Obfuscation/Referencing/IReferencesDataResolver.cs index b2123b11..49298fa1 100644 --- a/src/BitMono.Obfuscation/Referencing/IReferencesDataResolver.cs +++ b/src/BitMono.Obfuscation/Referencing/IReferencesDataResolver.cs @@ -2,5 +2,5 @@ public interface IReferencesDataResolver { - List Resolve(ModuleDefinition module); + List Resolve(ModuleDefinition module, CancellationToken cancellationToken); } \ No newline at end of file diff --git a/src/BitMono.Obfuscation/Referencing/ReferencesDataResolver.cs b/src/BitMono.Obfuscation/Referencing/ReferencesDataResolver.cs index 31c7e81c..2eb221eb 100644 --- a/src/BitMono.Obfuscation/Referencing/ReferencesDataResolver.cs +++ b/src/BitMono.Obfuscation/Referencing/ReferencesDataResolver.cs @@ -9,15 +9,12 @@ public ReferencesDataResolver(string referencesDirectoryName) _referencesDirectoryName = referencesDirectoryName; } - [SuppressMessage("ReSharper", "ForCanBeConvertedToForeach")] - [SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")] - public List Resolve(ModuleDefinition module) + public List Resolve(ModuleDefinition module, CancellationToken cancellationToken) { var result = new List(); var references = Directory.GetFiles(_referencesDirectoryName); - for (var i = 0; i < references.Length; i++) + foreach (var reference in references) { - var reference = references[i]; result.Add(File.ReadAllBytes(reference)); } return result; diff --git a/src/BitMono.Obfuscation/Starter/BitMonoContextFactory.cs b/src/BitMono.Obfuscation/Starter/BitMonoContextFactory.cs index 3f551f00..9a1558f0 100644 --- a/src/BitMono.Obfuscation/Starter/BitMonoContextFactory.cs +++ b/src/BitMono.Obfuscation/Starter/BitMonoContextFactory.cs @@ -14,9 +14,9 @@ public BitMonoContextFactory(ModuleDefinition module, IReferencesDataResolver re _obfuscationSettings = obfuscationSettings; } - public BitMonoContext Create(string filePath, string outputDirectoryName) + public BitMonoContext Create(string filePath, string outputDirectoryName, CancellationToken cancellationToken) { - var referencesData = _referencesDataResolver.Resolve(_module); + var referencesData = _referencesDataResolver.Resolve(_module, cancellationToken); var fileName = Path.GetFileName(filePath); return new BitMonoContext { diff --git a/src/BitMono.Obfuscation/Starter/BitMonoStarter.cs b/src/BitMono.Obfuscation/Starter/BitMonoStarter.cs index b0cee6c1..5d525180 100644 --- a/src/BitMono.Obfuscation/Starter/BitMonoStarter.cs +++ b/src/BitMono.Obfuscation/Starter/BitMonoStarter.cs @@ -1,8 +1,5 @@ namespace BitMono.Obfuscation.Starter; -[SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")] -[SuppressMessage("ReSharper", "IdentifierTypo")] -[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] public class BitMonoStarter { private readonly IServiceProvider _serviceProvider; @@ -35,7 +32,7 @@ public Task StartAsync(FinalFileInfo info, IModuleFactory moduleFactory, I var runtimeModule = ModuleDefinition.FromFile(typeof(Runtime.Data).Assembly.Location); var moduleFactoryResult = moduleFactory.Create(); var bitMonoContextFactory = new BitMonoContextFactory(moduleFactoryResult.Module, referencesDataResolver, _obfuscationSettings); - var bitMonoContext = bitMonoContextFactory.Create(info.FilePath, info.OutputDirectoryPath); + var bitMonoContext = bitMonoContextFactory.Create(info.FilePath, info.OutputDirectoryPath, cancellationToken); var engineContextFactory = new StarterContextFactory(moduleFactoryResult, runtimeModule, bitMonoContext, cancellationToken); var engineContext = engineContextFactory.Create(); _engineContextAccessor.Instance = engineContext; diff --git a/src/BitMono.Utilities/AsmResolver/ModuleDefinitionExtensions.cs b/src/BitMono.Utilities/AsmResolver/ModuleDefinitionExtensions.cs index 059dac4a..ebcc9e2a 100644 --- a/src/BitMono.Utilities/AsmResolver/ModuleDefinitionExtensions.cs +++ b/src/BitMono.Utilities/AsmResolver/ModuleDefinitionExtensions.cs @@ -13,7 +13,6 @@ public static TMember ResolveOrThrow(this ModuleDefinition source, Type throw new ArgumentException($"Unable to resolve member {type.FullName}"); } [SuppressMessage("ReSharper", "UseObjectOrCollectionInitializer")] - [SuppressMessage("ReSharper", "ReturnTypeCanBeEnumerable.Global")] public static List FindMembers(this ModuleDefinition source) { var members = new List(); From 9aa86eca440052ac82f3c2c2b1e60bac87ad889b Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 25 Aug 2024 11:56:34 +0300 Subject: [PATCH 06/10] Update ProtectionParameters.cs --- src/BitMono.API/Protections/ProtectionParameters.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/BitMono.API/Protections/ProtectionParameters.cs b/src/BitMono.API/Protections/ProtectionParameters.cs index 183f5dcd..ebe38d18 100644 --- a/src/BitMono.API/Protections/ProtectionParameters.cs +++ b/src/BitMono.API/Protections/ProtectionParameters.cs @@ -1,6 +1,5 @@ namespace BitMono.API.Protections; -[SuppressMessage("ReSharper", "UnusedType.Global")] public class ProtectionParameters { public ProtectionParameters(List members) From f65224ceed1cccd893bc33fab72ed3705cda73e9 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 25 Aug 2024 12:58:00 +0300 Subject: [PATCH 07/10] Refactoring --- .../ModifyInjectTypeClonerListener.cs | 5 +-- .../AutofacContainerBuilderExtensions.cs | 2 +- src/BitMono.Protections/StringsEncryption.cs | 44 ++++++++++++------- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/BitMono.Core/Injection/ModifyInjectTypeClonerListener.cs b/src/BitMono.Core/Injection/ModifyInjectTypeClonerListener.cs index 27607291..afc36b62 100644 --- a/src/BitMono.Core/Injection/ModifyInjectTypeClonerListener.cs +++ b/src/BitMono.Core/Injection/ModifyInjectTypeClonerListener.cs @@ -1,6 +1,5 @@ namespace BitMono.Core.Injection; -[SuppressMessage("ReSharper", "ForCanBeConvertedToForeach")] public class ModifyInjectTypeClonerListener : InjectTypeClonerListener { public ModifyInjectTypeClonerListener(ModifyFlags modify, Renamer renamer, ModuleDefinition targetModule) : base(targetModule) @@ -27,9 +26,9 @@ public override void OnClonedMember(IMemberDefinition original, IMemberDefinitio if (cloned is MethodDefinition method) { var parameterDefinitions = method.ParameterDefinitions; - for (var i = 0; i < parameterDefinitions.Count; i++) + foreach (var parameter in parameterDefinitions) { - parameterDefinitions[i].Name = string.Empty; + parameter.Name = string.Empty; } } } diff --git a/src/BitMono.Host/Extensions/AutofacContainerBuilderExtensions.cs b/src/BitMono.Host/Extensions/AutofacContainerBuilderExtensions.cs index 00c2d36a..972cc61b 100644 --- a/src/BitMono.Host/Extensions/AutofacContainerBuilderExtensions.cs +++ b/src/BitMono.Host/Extensions/AutofacContainerBuilderExtensions.cs @@ -9,7 +9,7 @@ public static class AutofacContainerBuilderExtensions public static ContainerBuilder AddProtections(this ContainerBuilder source, string? file = null) { var workingDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - var protectionsFilePath = Path.Combine(workingDirectory, ProtectionsFileName); + var protectionsFilePath = Path.Combine(workingDirectory!, ProtectionsFileName); var rawData = File.ReadAllBytes(file ?? protectionsFilePath); Assembly.Load(rawData); diff --git a/src/BitMono.Protections/StringsEncryption.cs b/src/BitMono.Protections/StringsEncryption.cs index 82e0fca1..8869a621 100644 --- a/src/BitMono.Protections/StringsEncryption.cs +++ b/src/BitMono.Protections/StringsEncryption.cs @@ -19,7 +19,7 @@ public override Task ExecuteAsync() var saltBytesField = MscorlibInjector.InjectCompilerGeneratedArray(Context.Module, globalModuleType, Data.SaltBytes, _renamer.RenameUnsafely()); var runtimeDecryptorType = Context.RuntimeModule.ResolveOrThrow(typeof(Decryptor)); - var runtimeDecryptMethod = runtimeDecryptorType.Methods.Single(c => c.Name!.Equals(nameof(Decryptor.Decrypt))); + var runtimeDecryptMethod = runtimeDecryptorType.Methods.Single(x => x.Name!.Equals(nameof(Decryptor.Decrypt))); var listener = new ModifyInjectTypeClonerListener(ModifyFlags.All, _renamer, Context.Module); var memberCloneResult = new MemberCloner(Context.Module, listener) .Include(runtimeDecryptorType) @@ -29,25 +29,35 @@ public override Task ExecuteAsync() foreach (var method in Context.Parameters.Members.OfType()) { - if (method.CilMethodBody is { } body) + if (method.CilMethodBody is not { } body) { - for (var i = 0; i < body.Instructions.Count; i++) + continue; + } + + var instructions = body.Instructions; + for (var i = 0; i < instructions.Count; i++) + { + var instruction = instructions[i]; + if (instruction.OpCode.Equals(CilOpCodes.Ldstr) == false) { - if (body.Instructions[i].OpCode.Equals( CilOpCodes.Ldstr) && body.Instructions[i].Operand is string content) - { - var data = Encryptor.EncryptContent(content, Data.SaltBytes, Data.CryptKeyBytes); - var arrayName = _renamer.RenameUnsafely(); - var encryptedDataFieldDef = MscorlibInjector.InjectCompilerGeneratedArray(Context.Module, globalModuleType, data, arrayName); - - body.Instructions[i].ReplaceWith(CilOpCodes.Ldsfld, encryptedDataFieldDef); - body.Instructions.InsertRange(i + 1, new CilInstruction[] - { - new(CilOpCodes.Ldsfld, saltBytesField), - new(CilOpCodes.Ldsfld, cryptKeyField), - new(CilOpCodes.Call, decryptMethod), - }); - } + continue; } + if (instruction.Operand is not string content) + { + continue; + } + + var data = Encryptor.EncryptContent(content, Data.SaltBytes, Data.CryptKeyBytes); + var arrayName = _renamer.RenameUnsafely(); + var encryptedDataFieldDef = MscorlibInjector.InjectCompilerGeneratedArray(Context.Module, globalModuleType, data, arrayName); + + instruction.ReplaceWith(CilOpCodes.Ldsfld, encryptedDataFieldDef); + instructions.InsertRange(i + 1, + [ + new CilInstruction(CilOpCodes.Ldsfld, saltBytesField), + new CilInstruction(CilOpCodes.Ldsfld, cryptKeyField), + new CilInstruction(CilOpCodes.Call, decryptMethod) + ]); } } return Task.CompletedTask; From f38f50866b588052ec0524e8614ffd312e243130 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 25 Aug 2024 13:05:32 +0300 Subject: [PATCH 08/10] Add more info about native code features --- src/BitMono.Obfuscation/BitMonoObfuscator.cs | 2 +- .../ProtectionsConfigureForNativeCodeNotifier.cs | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/BitMono.Obfuscation/BitMonoObfuscator.cs b/src/BitMono.Obfuscation/BitMonoObfuscator.cs index 52c24ff0..2e41ddb4 100644 --- a/src/BitMono.Obfuscation/BitMonoObfuscator.cs +++ b/src/BitMono.Obfuscation/BitMonoObfuscator.cs @@ -147,7 +147,7 @@ private void ConfigureForNativeCode() return; } - _protectionsConfigureForNativeCodeNotifier.Notify(_protectionsSort); + _protectionsConfigureForNativeCodeNotifier.Notify(_protectionsSort, _context.CancellationToken); var module = _context.Module; module.IsILOnly = false; diff --git a/src/BitMono.Obfuscation/Notifiers/ProtectionsConfigureForNativeCodeNotifier.cs b/src/BitMono.Obfuscation/Notifiers/ProtectionsConfigureForNativeCodeNotifier.cs index c8b73f2c..aeec4b5f 100644 --- a/src/BitMono.Obfuscation/Notifiers/ProtectionsConfigureForNativeCodeNotifier.cs +++ b/src/BitMono.Obfuscation/Notifiers/ProtectionsConfigureForNativeCodeNotifier.cs @@ -11,18 +11,25 @@ public ProtectionsConfigureForNativeCodeNotifier(ObfuscationSettings obfuscation _logger = logger.ForContext(); } - public void Notify(ProtectionsSort protectionsSort) + public void Notify(ProtectionsSort protectionsSort, CancellationToken cancellationToken) { if (_obfuscationSettings.OutputConfigureForNativeCodeWarnings == false) { return; } - if (protectionsSort.ConfigureForNativeCodeProtections.Any() == false) + var configureForNativeCodeProtections = protectionsSort.ConfigureForNativeCodeProtections; + if (configureForNativeCodeProtections.Any() == false) { return; } _logger.Warning( "Enabled protections may create native code configurations, which can sometimes break the app. Proceed with caution. If issues arise, disable the following protections."); + foreach (var protection in configureForNativeCodeProtections) + { + cancellationToken.ThrowIfCancellationRequested(); + + _logger.Warning("{Name} - is using Native Code.", protection.GetName()); + } } } \ No newline at end of file From 5db7194810857b74d4db3924c0d3869790e50b36 Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 25 Aug 2024 13:06:22 +0300 Subject: [PATCH 09/10] Update native-code.rst --- docs/source/developers/native-code.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/developers/native-code.rst b/docs/source/developers/native-code.rst index 03e72bde..a662c9e9 100644 --- a/docs/source/developers/native-code.rst +++ b/docs/source/developers/native-code.rst @@ -7,7 +7,7 @@ If you want to use a native code in the protection you must do the following: .. code-block:: csharp [ConfigureForNativeCode] // Add this attribute on top of the protection class - public class CustomProtection : Protection + public class CustomProtection : Protection A good example is ``UnmanagedString`` protection. It uses native code to encrypt strings. You can find the source code in the ``UnmanagedString`` file. From 46bba8b16f91fef3de529e1cc9f76dcdf47aeb1c Mon Sep 17 00:00:00 2001 From: sunnamed434 Date: Sun, 25 Aug 2024 13:14:13 +0300 Subject: [PATCH 10/10] Add in docs protections types #195 --- docs/source/protections/antide4dot.rst | 6 ++++++ docs/source/protections/antidebugbreakpoints.rst | 8 +++++++- docs/source/protections/antidecompiler.rst | 6 ++++++ docs/source/protections/antiildasm.rst | 8 +++++++- docs/source/protections/billionnops.rst | 7 ++++++- docs/source/protections/bitdecompiler.rst | 6 ++++++ docs/source/protections/bitdotnet.rst | 6 ++++++ docs/source/protections/bitmethoddotnet.rst | 6 ++++++ docs/source/protections/bitmono.rst | 6 ++++++ docs/source/protections/bittimedatestamp.rst | 8 +++++++- docs/source/protections/calltocalli.rst | 6 ++++++ docs/source/protections/dotnethook.rst | 8 +++++++- docs/source/protections/fullrenamer.rst | 8 +++++++- docs/source/protections/nonamespaces.rst | 8 +++++++- docs/source/protections/objectreturntype.rst | 8 +++++++- docs/source/protections/stringsencryption.rst | 6 ++++++ docs/source/protections/unmanagedstring.rst | 6 ++++++ 17 files changed, 109 insertions(+), 8 deletions(-) diff --git a/docs/source/protections/antide4dot.rst b/docs/source/protections/antide4dot.rst index 044ead3e..f06e1f52 100644 --- a/docs/source/protections/antide4dot.rst +++ b/docs/source/protections/antide4dot.rst @@ -3,8 +3,14 @@ AntiDe4dot How it works? ------------- + Protection adds multiple attributes of known obfuscators/protectors and as a result fools de4dot. +Protection Type +--------------- + +The protection type is `Protection`. + .. warning:: diff --git a/docs/source/protections/antidebugbreakpoints.rst b/docs/source/protections/antidebugbreakpoints.rst index 7b201d80..79b47771 100644 --- a/docs/source/protections/antidebugbreakpoints.rst +++ b/docs/source/protections/antidebugbreakpoints.rst @@ -3,4 +3,10 @@ AntiDebugBreakpoints How it works? ------------- -Protection adds things in method bodies that check if from the last execution passed more than the const value, then as a result the program will be crashed. \ No newline at end of file + +Protection adds things in method bodies that check if from the last execution passed more than the const value, then as a result the program will be crashed. + +Protection Type +--------------- + +The protection type is `Protection`. \ No newline at end of file diff --git a/docs/source/protections/antidecompiler.rst b/docs/source/protections/antidecompiler.rst index 6a92f856..107441bd 100644 --- a/docs/source/protections/antidecompiler.rst +++ b/docs/source/protections/antidecompiler.rst @@ -3,10 +3,16 @@ AntiDecompiler How it works? ------------- + Protection looks for a nested type in and sets non-public accessibility attributes, according to ECMA CIL standard nested types should always have one of them applied, but Mono doesn't care about this standard. That means if someone will try to analyze the protected nested type, dnSpy will crash, however in a newer version, this exploit was fixed. +Protection Type +--------------- + +The protection type is `Packer`. + .. warning:: diff --git a/docs/source/protections/antiildasm.rst b/docs/source/protections/antiildasm.rst index 31ab0a5b..e5305155 100644 --- a/docs/source/protections/antiildasm.rst +++ b/docs/source/protections/antiildasm.rst @@ -3,4 +3,10 @@ AntiILdasm How it works? ------------- -Protection adds ``[SuppressIldasmAttribute]`` which prevents the Ildasm (IL Disassembler) from disassembling the protected file. \ No newline at end of file + +Protection adds ``[SuppressIldasmAttribute]`` which prevents the Ildasm (IL Disassembler) from disassembling the protected file. + +Protection Type +--------------- + +The protection type is `Protection`. \ No newline at end of file diff --git a/docs/source/protections/billionnops.rst b/docs/source/protections/billionnops.rst index 0f219367..24d9caf6 100644 --- a/docs/source/protections/billionnops.rst +++ b/docs/source/protections/billionnops.rst @@ -16,4 +16,9 @@ As a result when someone will try to analyze this method will cause a crashed dn Cons ---- -Be careful because this protection will increase a file size a lot, and a bigger file size will cause more questions by users, most of us when see a big file size think that this file is obfuscated. \ No newline at end of file +Be careful because this protection will increase a file size a lot, and a bigger file size will cause more questions by users, most of us when see a big file size think that this file is obfuscated. + +Protection Type +--------------- + +The protection type is `Protection`. \ No newline at end of file diff --git a/docs/source/protections/bitdecompiler.rst b/docs/source/protections/bitdecompiler.rst index daea83c7..97a01980 100644 --- a/docs/source/protections/bitdecompiler.rst +++ b/docs/source/protections/bitdecompiler.rst @@ -3,8 +3,14 @@ BitDecompiler How it works? ------------- + This protection works the same as BitDotnet protection, but with some fixes. However, since after Unity 2021 and higher it stopped working correctly and since many of users asked to figure something out we made this protection as a solution =) +Protection Type +--------------- + +The protection type is `Packer`. + .. warning:: diff --git a/docs/source/protections/bitdotnet.rst b/docs/source/protections/bitdotnet.rst index 8dca6f39..17e83881 100644 --- a/docs/source/protections/bitdotnet.rst +++ b/docs/source/protections/bitdotnet.rst @@ -3,10 +3,16 @@ BitDotNet How it works? ------------- + The protection uses dnlib exploit and modifies the file metadata (PE) to make it unrecognizable for dnSpy, as the result, at first sight, it will look like not a .NET file, for example, a C++ file. Mono doesn't care about the thing which dnlib care about, and because of that it does what it does +Protection Type +--------------- + +The protection type is `Packer`. + .. warning:: diff --git a/docs/source/protections/bitmethoddotnet.rst b/docs/source/protections/bitmethoddotnet.rst index 390cf22f..9e0901d7 100644 --- a/docs/source/protections/bitmethoddotnet.rst +++ b/docs/source/protections/bitmethoddotnet.rst @@ -3,8 +3,14 @@ BitMethodDotnet How it works? ------------- + Protection adds invalid IL code in the file, as the result in the old dnSpy version it's going to be harder to see the C# code of the method body. +Protection Type +--------------- + +The protection type is `Protection`. + .. warning:: diff --git a/docs/source/protections/bitmono.rst b/docs/source/protections/bitmono.rst index 6ade5653..e15fe816 100644 --- a/docs/source/protections/bitmono.rst +++ b/docs/source/protections/bitmono.rst @@ -3,10 +3,16 @@ BitMono How it works? ------------- + Protection modifies the file metadata (PE) to make it unrecognizable for decompilers or other tools such as Detect It Easy, as the result most of the tools will be fooled to think that this is an MS-DOS Executable as Detect It Easy does, decompilers will just not be able to open it up. Mono doesn't care about the things which decompilers/tools care about, and because of that it does what it does. +Protection Type +--------------- + +The protection type is `Packer`. + .. warning:: diff --git a/docs/source/protections/bittimedatestamp.rst b/docs/source/protections/bittimedatestamp.rst index 481a4c1c..8e739ab1 100644 --- a/docs/source/protections/bittimedatestamp.rst +++ b/docs/source/protections/bittimedatestamp.rst @@ -3,4 +3,10 @@ BitTimeDateStamp How it works? ------------- -Protection modifies the file metadata (PE) and erases the TimeDateStamp, as the result no one will be able to know when this file was compiled. \ No newline at end of file + +Protection modifies the file metadata (PE) and erases the TimeDateStamp, as the result no one will be able to know when this file was compiled. + +Protection Type +--------------- + +The protection type is `Packer`. \ No newline at end of file diff --git a/docs/source/protections/calltocalli.rst b/docs/source/protections/calltocalli.rst index 9e8b4c59..15855ee9 100644 --- a/docs/source/protections/calltocalli.rst +++ b/docs/source/protections/calltocalli.rst @@ -3,8 +3,14 @@ CallToCalli How it works? ------------- + Protection replaces call opcode to calli and calls method by its function pointer. +Protection Type +--------------- + +The protection type is `Protection`. + .. warning:: diff --git a/docs/source/protections/dotnethook.rst b/docs/source/protections/dotnethook.rst index 178e2222..144a7d4b 100644 --- a/docs/source/protections/dotnethook.rst +++ b/docs/source/protections/dotnethook.rst @@ -3,4 +3,10 @@ DotNetHook How it works? ------------- -Protection hooks methods, as a result, will call empty methods but, in fact, a completely different method will be called (the original one). \ No newline at end of file + +Protection hooks methods, as a result, will call empty methods but, in fact, a completely different method will be called (the original one). + +Protection Type +--------------- + +The protection type is `Protection`. \ No newline at end of file diff --git a/docs/source/protections/fullrenamer.rst b/docs/source/protections/fullrenamer.rst index 154c7581..e9b16e40 100644 --- a/docs/source/protections/fullrenamer.rst +++ b/docs/source/protections/fullrenamer.rst @@ -3,8 +3,14 @@ FullRenamer How it works? ------------- + Protection renames types/methods/fields, however, ignores things such as reflection, Unity Methods (Update/FixedUpdate/LateUpdate, i.e all of them), overrides from Thanking (OV_methodName), and the most popular frameworks for plugin development in Unturned and Rust on GitHub - RocketMod, OpenMod, and rust-oxide-umod, you even could specify your methods/types to ignore. If you want you can easily configure `criticals.json` to ignore strings and lot of stuff. -Be careful, because renamer is tricky protection, not always useful, and does not always work properly. But, if you configure BitMono correctly Renamer can be a great protection (I'm about big projects, not crackmes). \ No newline at end of file +Be careful, because renamer is tricky protection, not always useful, and does not always work properly. But, if you configure BitMono correctly Renamer can be a great protection (I'm about big projects, not crackmes). + +Protection Type +--------------- + +The protection type is `Protection`. \ No newline at end of file diff --git a/docs/source/protections/nonamespaces.rst b/docs/source/protections/nonamespaces.rst index 100a2506..0ba6627e 100644 --- a/docs/source/protections/nonamespaces.rst +++ b/docs/source/protections/nonamespaces.rst @@ -3,4 +3,10 @@ NoNamespaces How it works? ------------- -Protection removes all namespaces. \ No newline at end of file + +Protection removes all namespaces. + +Protection Type +--------------- + +The protection type is `Protection`. \ No newline at end of file diff --git a/docs/source/protections/objectreturntype.rst b/docs/source/protections/objectreturntype.rst index fc33f7aa..7c396ef9 100644 --- a/docs/source/protections/objectreturntype.rst +++ b/docs/source/protections/objectreturntype.rst @@ -3,4 +3,10 @@ ObjectReturnType How it works? ------------- -Protection changes the nonvoid method return types to object return types. \ No newline at end of file + +Protection changes the nonvoid method return types to object return types. + +Protection Type +--------------- + +The protection type is `Protection`. \ No newline at end of file diff --git a/docs/source/protections/stringsencryption.rst b/docs/source/protections/stringsencryption.rst index 1801c92d..afb1462c 100644 --- a/docs/source/protections/stringsencryption.rst +++ b/docs/source/protections/stringsencryption.rst @@ -3,8 +3,14 @@ StringsEncryption How it works? ------------- + Protection encrypts strings using basic AES encryption, but not everyone like it because it makes the worse performance of application, but can be used with AntiDecompiler to crash dnSpy while analyzing the used class, also makes the RVA of the byte[] 0 +Protection Type +--------------- + +The protection type is `Protection`. + .. warning:: diff --git a/docs/source/protections/unmanagedstring.rst b/docs/source/protections/unmanagedstring.rst index 11fbe0a4..d9dcbe34 100644 --- a/docs/source/protections/unmanagedstring.rst +++ b/docs/source/protections/unmanagedstring.rst @@ -3,8 +3,14 @@ UnmanagedString How it works? ------------- + Protection creates native method with assembly code and protects strings only that can be encoded with `Windows-1252` encoding. +Protection Type +--------------- + +The protection type is `Protection`. + .. warning::