Skip to content

Commit

Permalink
Merge pull request #188 from sunnamed434/fixes
Browse files Browse the repository at this point in the history
Fixes and refactoring
  • Loading branch information
sunnamed434 authored Aug 11, 2024
2 parents ae541ad + c5e3dea commit c84ec14
Show file tree
Hide file tree
Showing 60 changed files with 392 additions and 230 deletions.
2 changes: 2 additions & 0 deletions BitMono.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=JS/@EntryIndexedValue">JS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=NET/@EntryIndexedValue">NET</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PE/@EntryIndexedValue">PE</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=criticals/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Decryptor/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ldasm/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mprotect/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nops/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=obfuscator/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=renamer/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

## BitMono

[![Codefactor][image_codefactor]][codefactor]
[![DeepSource][image_deepsource]][deepsource]
[![MIT License][image_license]][license]
[![BitMono Discord][image_bitmono_discord]][bitmono_discord]

Expand Down Expand Up @@ -73,6 +71,7 @@ Read the **[docs][bitmono_docs]** to read protection, functionality, and more.
* FullRenamer
* AntiDebugBreakpoints
* AntiDecompiler
* BitDecompiler (fixed version of BitDotNet for newer Unity Versions)
* BitDateTimeStamp
* BitMono
* BillionNops
Expand Down Expand Up @@ -182,8 +181,6 @@ Credits

**[drakonia][author_drakonia]** for her **[costura decompressor][simple_costura_decompressor_source]**.

[codefactor]: https://www.codefactor.io/repository/github/sunnamed434/bitmono/overview/main
[deepsource]: https://deepsource.io/gh/sunnamed434/BitMono/?ref=repository-badge
[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
Expand Down
18 changes: 12 additions & 6 deletions docs/source/configuration/protections.rst
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
Configure Protections
=====================
Protections
===========

Let's say you want to execute the same protection twice or even execute protections in a different orders, etc.

Keep in mind:

- The order of execution is determined by the position of each protection in the ``protections.json`` file within the configuration file. For example, AntiILdasm is executed first (because this protection is first in configuration) and Packers always run last after all protections, even if you set this ``Packer`` protection as a first one in configuration it will anyway gonna be called last.

Use ``protections.json`` - by default all protections are configured as they should, if something works not as intentionally you always may disable something, enable and even remove.
Default config (it can be different with new updates, but just let's see how it looks like):


.. code-block:: json
{
"Protections": [
{
"Name": "AntiILdasm",
"Name": "AntiILdasm", // This is going to be executed first
"Enabled": false
},
{
Expand Down Expand Up @@ -54,15 +60,15 @@ Use ``protections.json`` - by default all protections are configured as they sho
"Enabled": false
},
{
"Name": "BitTimeDateStamp",
"Name": "BitTimeDateStamp", // Packer
"Enabled": false
},
{
"Name": "BitDotNet",
"Name": "BitDotNet", // Packer
"Enabled": true
},
{
"Name": "BitMono",
"Name": "BitMono", // This is going to be executed last because its a Packer, even if you put this before AntiILdasm it going to be called last anyway.
"Enabled": true
}
]
Expand Down
2 changes: 0 additions & 2 deletions docs/source/developers/do-not-resolve-members.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ Add attribute ``[DoNotResolve(MemberInclusionFlags.Reflection)]`` with ``MemberI

.. code-block:: csharp
[UsedImplicitly] // This is not intentional, but suppresses warnings by ReSharper
[DoNotResolve(MemberInclusionFlags.Reflection)]
public class MagicProtection : Protection
Expand All @@ -43,7 +42,6 @@ You can specify multiple inclusion flags.
.. code-block:: csharp
[UsedImplicitly]
[DoNotResolve(MemberInclusionFlags.SpecialRuntime | MemberInclusionFlags.Reflection)]
public class MagicProtection : Protection
Expand Down
14 changes: 5 additions & 9 deletions docs/source/developers/first-protection.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,15 @@ Creating your first Protection
BitMono provides a lot of examples in source code with existing protection and maximum functional usage, you can find them in BitMono.Protections project.


Always create your protection ONLY in BitMono.Protections, DI (dependency injection) container will catch all of your protections automatically and Obfuscation Engine of BitMono will automatically call your protection depending on which protection is it.
Create your protection in the ``BitMono.Protections`` namespace.

- The Dependency Injection (DI) container will automatically register your protections.
- The BitMono Obfuscation Engine will invoke your protection based on its type and the order specified in the configuration file.
- The order of execution is determined by the position of each protection in the ``protections.json`` file within the configuration file. For example, AntiILdasm is executed first (because this protection is first in configuration) and Packers always run last after all protections, even if you set this ``Packer`` protection as a first one in configuration it will anyway gonna be called last.


.. code-block:: csharp
// Mark the Protection as [UsedImplicitly] because for JetBrains Rider or ReSharper users protection will look kinda is not used,
// and other developers might delete it as an unnecessary class in the project,
// because protections are instantiated via DI container, so, its invisible for JetBrains Rider and ReSharper,
// the goal is remove weird warning,
// In simple words, saying to the rider:
// "It's ok, protection created somewhere else but you can't see it,
// please don't worry, and remove your warnings"
[UsedImplicitly]
public class StandardProtection : Protection
{
// Inject services right here
Expand Down
27 changes: 14 additions & 13 deletions docs/source/developers/obfuscation-execution-order.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ Obfuscation Engine Execution Order
BitMono uses its own obfuscation execution order which is good to be known, and it reminds ConfuserEx a lot, if you're familiar with it you can be easier with it.

1. Output Loaded Module Info
2. Sort Protections
3. Basic output information about Protections
4. Elapsed time counter
5. Output Information of Running Framework
6. Resolve References
7. Expand Macros
8. Run Protection, PipelineProtection and child pipeline protections
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


.. code-block:: csharp
Expand All @@ -20,16 +21,16 @@ BitMono uses its own obfuscation execution order which is good to be known, and
public class Pipeline : PipelineProtection
9. Optimize Macros
10. [ObfuscationAttribute] cleanup
11. Create PE Image
12. Write Module
13. Run Packers
11. Optimize Macros
12. [ObfuscationAttribute] cleanup
13. Create PE Image
14. Write Module
15. Run Packers
.. code-block:: csharp
public class Packer : PackerProtection
14. Output Elapsed Time since obfuscation
16. Output Elapsed Time since obfuscation
2 changes: 0 additions & 2 deletions docs/source/developers/protection-runtime-moniker.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ By default BitMono provides an opportunity to talk with the users, to warn them,

.. code-block:: csharp
[UsedImplicitly]
[RuntimeMonikerMono] // Add this Attribute which says this protections works only with Mono Runtime
public class MonoPacker : Packer
Expand Down Expand Up @@ -69,7 +68,6 @@ Specify Rust Runtime Moniker Attribute.

.. code-block:: csharp
[UsedImplicitly]
[RuntimeMonikerRust] // Add this Attribute which says this protections works only with Rust Runtime
public class RustPacker : Packer // or instead use Protection or PipelineProtection
Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Table of Contents:
protections/antiildasm
protections/antide4dot
protections/bitdotnet
protections/bitdecompiler
protections/bitmono
protections/bittimedatestamp
protections/bitmethoddotnet
Expand Down
11 changes: 11 additions & 0 deletions docs/source/protections/bitdecompiler.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
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 =)


.. warning::

This protection compatible only with Mono.
1 change: 1 addition & 0 deletions src/BitMono.API/Analyzing/ICriticalAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace BitMono.API.Analyzing;

[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
public interface ICriticalAnalyzer<in TObject>
{
bool NotCriticalToMakeChanges(TObject @object);
Expand Down
1 change: 1 addition & 0 deletions src/BitMono.API/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
global using System.Diagnostics.CodeAnalysis;
global using System.Threading.Tasks;
global using BitMono.API.Protections;
global using JetBrains.Annotations;
global using IModule = Autofac.Core.IModule;
1 change: 1 addition & 0 deletions src/BitMono.API/Protections/IProtection.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
namespace BitMono.API.Protections;

[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)]
public interface IProtection
{
Task ExecuteAsync();
Expand Down
14 changes: 0 additions & 14 deletions src/BitMono.CLI/Modules/CLIBitMonoModuleFileResolver.cs

This file was deleted.

30 changes: 26 additions & 4 deletions src/BitMono.CLI/Modules/CLIObfuscationNeedsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@ public CLIObfuscationNeedsFactory(string[] args, ObfuscationSettings obfuscation
_logger = logger.ForContext<CLIObfuscationNeedsFactory>();
}

public ObfuscationNeeds Create()
public ObfuscationNeeds Create(CancellationToken cancellationToken)
{
var fileName = CLIBitMonoModuleFileResolver.Resolve(_args);
var fileName = GetFileName(_args);
var specifyingFile = true;
while (specifyingFile)
{
try
{
_logger.Information("Please, specify file or drag-and-drop in BitMono CLI");

cancellationToken.ThrowIfCancellationRequested();

fileName = PathFormatterUtility.Format(Console.ReadLine());
if (string.IsNullOrWhiteSpace(fileName) == false)
{
Expand All @@ -41,6 +44,10 @@ public ObfuscationNeeds Create()
_logger.Warning("Unable to specify empty null or whitespace file, please, try again!");
}
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
_logger.Warning("Something went wrong while specifying the file: " + ex);
Expand All @@ -66,6 +73,8 @@ public ObfuscationNeeds Create()
{
try
{
cancellationToken.ThrowIfCancellationRequested();

if (Directory.Exists(dependenciesDirectoryName))
{
_logger.Information("Dependencies (libs) successfully found automatically: {0}!",
Expand Down Expand Up @@ -95,10 +104,13 @@ public ObfuscationNeeds Create()
_logger.Information("Unable to specify empty (libs), please, try again!");
}
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
_logger.Information("Something went wrong while specifying the dependencies (libs) path: " +
ex);
_logger.Error(ex, "Something went wrong while specifying the dependencies (libs) path");
}
}
}
Expand All @@ -119,4 +131,14 @@ public ObfuscationNeeds Create()
OutputPath = outputDirectoryName
};
}

private string GetFileName(string[] args)
{
string? file = null;
if (args.IsEmpty() == false)
{
file = PathFormatterUtility.Format(args[0]);
}
return file;
}
}
3 changes: 1 addition & 2 deletions src/BitMono.CLI/Modules/CLIOptionsObfuscationNeedsFactory.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
namespace BitMono.CLI.Modules;

[SuppressMessage("ReSharper", "InconsistentNaming")]
public class CLIOptionsObfuscationNeedsFactory
{
private readonly string[] _args;
Expand All @@ -16,7 +15,7 @@ public CLIOptionsObfuscationNeedsFactory(string[] args,
}

[SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
public ObfuscationNeeds? Create()
public ObfuscationNeeds? Create(CancellationToken cancellationToken)
{
var parser = new Parser(with =>
{
Expand Down
6 changes: 3 additions & 3 deletions src/BitMono.CLI/Modules/ObfuscationNeedsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ public ObfuscationNeedsFactory(string[] args,
_logger = logger;
}

public ObfuscationNeeds? Create()
public ObfuscationNeeds? Create(CancellationToken cancellationToken)
{
return _args.IsEmpty()
? new CLIObfuscationNeedsFactory(_args, _obfuscationSettings, _logger).Create()
: new CLIOptionsObfuscationNeedsFactory(_args, _obfuscationSettings, _logger).Create();
? new CLIObfuscationNeedsFactory(_args, _obfuscationSettings, _logger).Create(cancellationToken)
: new CLIOptionsObfuscationNeedsFactory(_args, _obfuscationSettings, _logger).Create(cancellationToken);
}
}
16 changes: 13 additions & 3 deletions src/BitMono.CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace BitMono.CLI;
internal class Program
{
private static readonly CancellationTokenSource CancellationTokenSource = new();
private static CancellationToken CancellationToken => CancellationTokenSource.Token;
private static readonly string BitMonoFileVersionText =
$"BitMono v{FileVersionInfo.GetVersionInfo(typeof(Program).Assembly.Location).FileVersion}";
private static readonly string AsciiArt = @$"
Expand Down Expand Up @@ -33,13 +34,15 @@ private static async Task<int> Main(string[] args)
var logger = serviceProvider
.GetRequiredService<ILogger>()
.ForContext<Program>();
var needs = new ObfuscationNeedsFactory(args, obfuscation, logger).Create();
var needs = new ObfuscationNeedsFactory(args, obfuscation, logger).Create(CancellationToken);
if (needs == null)
{
statusCode = KnownReturnStatuses.Failure;
return statusCode;
}

CancellationToken.ThrowIfCancellationRequested();

if (obfuscation.ClearCLI)
{
Console.Clear();
Expand All @@ -62,7 +65,14 @@ private static async Task<int> Main(string[] args)

if (obfuscation.OpenFileDestinationInFileExplorer)
{
Process.Start(needs.OutputPath);
try
{
Process.Start(needs.OutputPath);
}
catch (Exception ex)
{
logger.Error(ex, "An error occured while opening the destination file in explorer!");
}
}
}
catch (OperationCanceledException)
Expand All @@ -83,7 +93,7 @@ private static async Task<int> Main(string[] args)
return statusCode;
}

private static void OnCancelKeyPress(object sender, ConsoleCancelEventArgs e)
private static void OnCancelKeyPress(object? sender, ConsoleCancelEventArgs e)
{
CancellationTokenSource.Cancel();
e.Cancel = true;
Expand Down
Loading

0 comments on commit c84ec14

Please sign in to comment.