Skip to content

Commit

Permalink
Merge pull request #204 from sunnamed434/updates
Browse files Browse the repository at this point in the history
Updates
  • Loading branch information
sunnamed434 authored Sep 21, 2024
2 parents 7d9e3ac + 96af688 commit 7d25bb2
Show file tree
Hide file tree
Showing 25 changed files with 461 additions and 255 deletions.
7 changes: 6 additions & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ python:
- requirements: docs/requirements.txt

sphinx:
configuration: docs/source/conf.py
configuration: docs/source/conf.py

formats:
- pdf
- epub
- html
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,24 @@ Read the **[docs][bitmono_docs]** to read protection, functionality, and more.

### 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.
To download the latest release of BitMono, follow these steps:

1. Go to the [Latest BitMono Release][bitmono_latest_release].
2. Select and download the archive file that matches the Target Framework of the application you want to protect. Here are some examples:

- **Targeting .NET 8**: If your target file is built for .NET 8, download:
`BitMono-v0.25.3+e64e54d3-CLI-net8.0-win-x64.zip`

- **Targeting .NET Standard**: If your target file is built for .NET Standard, you can use either BitMono for .NET Framework or .NET 8:
`BitMono-v0.25.3+e64e54d3-CLI-net8.0-win-x64.zip`

- **Targeting .NET Framework**: If your target file is built for .NET Framework, download:
`BitMono-v0.25.3+e64e54d3-CLI-net462-win-x64.zip`

- **Targeting Mono or Unity Engine Runtime**: If your target file is built for .NET Framework and runs on Mono or Unity, use the .NET Framework version:
`BitMono-v0.25.3+e64e54d3-CLI-net462-win-x64.zip`

> **Note:** Be sure to select the correct version of BitMono that matches your Target Framework. Using the wrong version could result in compatibility issues.
### Pre-Require

Expand Down
1 change: 1 addition & 0 deletions docs/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
COMPOSE_PROJECT_NAME=bitmono-docs-project
Empty file added docs/.gitignore
Empty file.
19 changes: 19 additions & 0 deletions docs/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Use a base image with Python
FROM python:3.10-slim

# Set working directory
WORKDIR /docs

# Copy the documentation source into the container
COPY . /docs

# Install Sphinx and build the documentation
RUN pip install sphinx sphinx-rtd-theme
RUN sphinx-build -b html source build

# Expose the port the app runs on
EXPOSE 8000

# Command to run the HTTP server and output instructions
CMD echo "Documentation is available at http://localhost:8000" && \
python -m http.server 8000 --directory build
23 changes: 23 additions & 0 deletions docs/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
How to Run BitMono Docs Locally

Prerequisites:
- Ensure Docker is installed on your machine. If not, install Docker from https://docs.docker.com/get-docker/.

Running Locally:
1. Start Docker if it’s not already running.
2. Open a terminal and navigate to the directory containing your docker-compose.yml file.
3. Execute the following command to build and start the container:
docker-compose up --build
4. Open your browser and go to: http://localhost:8000 to view the documentation.

Restarting the Container:
1. To stop the container, press CTRL + C in the terminal where Docker is running, or close the terminal window.
2. To restart the container and apply any changes, execute:
docker-compose up --build
3. Refresh the browser page at http://localhost:8000 to see the latest updates.

To edit/update docs:
Prerequisites:
- Use Visual Studio Code, or any other tool. https://code.visualstudio.com/

Go to `source` folder and do your magic!
9 changes: 9 additions & 0 deletions docs/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:
docs:
build:
context: .
dockerfile: Dockerfile
image: bitmono-docs-image:latest
ports:
- "8000:8000"
entrypoint: ["sh", "-c", "echo 'Documentation is available at http://localhost:8000' && python -m http.server 8000 --directory build"]
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Table of Contents:
obfuscationissues/corlib-not-found
obfuscationissues/intended-for
obfuscationissues/compatibility
obfuscationissues/ready-to-run


.. toctree::
Expand Down
40 changes: 31 additions & 9 deletions docs/source/obfuscationissues/compatibility.rst
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
The module is built for ...
===========================

`The module is built for .NET (Core), but you're using a version of BitMono intended for .NET Framework.` - this message is very important because if your app is built on .NET Core but BitMono on .NET Framework after obfuscation your app just won't work.
Understanding Compatibility
---------------------------

Examples
--------
When using BitMono for obfuscation, it's critical to ensure that the version of BitMono matches the framework your application is built on.

Good:
For example, if your application is built on .NET Core, you **must** use the version of BitMono that is also built for .NET Core. Using an incompatible version will result in your application not functioning after obfuscation.

- BitMono on .NET Core and your app on .NET Core
- BitMono on .NET Framework and your app on .NET Framework
.. note::
A common error message you may encounter is:
``The module is built for .NET (Core), but you're using a version of BitMono intended for .NET Framework.``
This indicates a mismatch between your app's framework and BitMono's version.

Bad (IT WON'T WORK!!!):
Examples of Compatibility
--------------------------

- BitMono on .NET Core and your app on .NET Framework
- BitMono on .NET Framework and your app on .NET Core
Here are some examples of correct and incorrect configurations:

**✅ Good Configurations:**

- **BitMono for .NET Core** with an application built on **.NET Core**
- **BitMono for .NET Framework** with an application built on **.NET Framework**

**❌ Bad Configurations (These Won't Work!):**

- **BitMono for .NET Core** with an application built on **.NET Framework**
- **BitMono for .NET Framework** with an application built on **.NET Core**

Key Takeaways
-------------

- Always ensure that **BitMono's framework version** matches the **framework version** of your application.
- Incompatible configurations will break your app after obfuscation.
- Carefully check the framework version of both your app and the BitMono release you are using.

.. warning::
Mixing framework versions (e.g., using BitMono for .NET Framework with a .NET Core app) will cause the app to fail after obfuscation.
38 changes: 38 additions & 0 deletions docs/source/obfuscationissues/ready-to-run.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
ReadyToRun
==========

If you're encountering an error from BitMono regarding ReadyToRun, or your application is built using ReadyToRun, it means that your application is "protected" by being compiled into native code. However, BitMono cannot obfuscate it because it requires "managed" code.

To solve this issue, you can do the following:

Disable ReadyToRun
------------------

Simply go to your `.csproj` file, add the `PublishReadyToRun` option and set it to `false`. This will look like the following:

.. code-block:: xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishReadyToRun>false</PublishReadyToRun> <!-- Add this option and set to false -->
</PropertyGroup>
</Project>
Now, build the project and use `.dll` file that has a managed code, instead of native code.

`For more information, visit: <https://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run>`_

Use .dll File with Managed Code Instead of .exe File
----------------------------------------------------

Usually, in the output folder of your project (if it's a `.exe`), there should be a `.dll` file with managed code. Use this `.dll` file for obfuscation instead, if there's no such file or it has a native code then use upper solution.

Didn't Help?
------------

If none of the solutions worked, it likely means your file is either protected or broken. If this isn't the case, please open an issue on the BitMono GitHub repository or reach out to us on Discord for further assistance.
2 changes: 1 addition & 1 deletion src/BitMono.Core/Attributes/DoNotResolveAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace BitMono.Core.Attributes;

/// <summary>
/// Represents a sort logic which doesn't includes specified <see cref="MemberInclusionFlags"/> in arguments of Protection (i.e Members).
/// Represents a sort logic which doesn't include specified <see cref="MemberInclusionFlags"/> in <see cref="Protection"/> <see cref="ProtectionParameters.Members"/>.
/// </summary>
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class DoNotResolveAttribute : Attribute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static ContainerBuilder AddProtections(this ContainerBuilder source, stri
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
source.RegisterAssemblyTypes(assemblies)
.PublicOnly()
.Where(t => t.GetInterface(nameof(IPhaseProtection)) == null && t.GetInterface(nameof(IProtection)) != null)
.Where(x => x.GetInterface(nameof(IPhaseProtection)) == null && x.GetInterface(nameof(IProtection)) != null)
.OwnedByLifetimeScope()
.AsImplementedInterfaces()
.SingleInstance();
Expand Down
6 changes: 2 additions & 4 deletions src/BitMono.Obfuscation/BitMonoObfuscator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ private void OutputCompatibilityIssues()
return;
}
}
private bool SortProtections()
private void SortProtections()
{
var protectionSettings = _serviceProvider.GetRequiredService<IOptions<ProtectionSettings>>().Value.Protections!;
var protections = _serviceProvider
Expand All @@ -125,10 +125,8 @@ private bool SortProtections()
_protectionsSort = protectionsSorter.Sort(protections, protectionSettings);
if (_protectionsSort.HasProtections == false)
{
_logger.Fatal("No one protection were detected, please specify or enable them in protections.json!");
return false;
throw new Exception("No protections were detected. Please specify or enable them in `protections.json` file.");
}
return true;
}
private bool OutputProtectionsAsync()
{
Expand Down
1 change: 1 addition & 0 deletions src/BitMono.Obfuscation/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
global using AsmResolver.PE;
global using AsmResolver.PE.Builder;
global using AsmResolver.PE.DotNet;
global using AsmResolver.PE.DotNet.ReadyToRun;
global using AsmResolver.PE.File;
global using BitMono.API;
global using BitMono.API.Protections;
Expand Down
26 changes: 24 additions & 2 deletions src/BitMono.Obfuscation/Modules/ModuleFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ public class ModuleFactory : IModuleFactory
private readonly byte[] _bytes;
private readonly ObfuscationSettings _obfuscationSettings;
private readonly IErrorListener _errorListener;
private readonly ILogger _logger;
private readonly MetadataBuilderFlags _metadataBuilderFlags;

public ModuleFactory(byte[] bytes, ObfuscationSettings obfuscationSettings, IErrorListener errorListener,
public ModuleFactory(
byte[] bytes, ObfuscationSettings obfuscationSettings,
IErrorListener errorListener, ILogger logger,
MetadataBuilderFlags metadataBuilderFlags = MetadataBuilderFlags.None)
{
_bytes = bytes;
_obfuscationSettings = obfuscationSettings;
_errorListener = errorListener;
_logger = logger.ForContext<ModuleFactory>();
_metadataBuilderFlags = metadataBuilderFlags;
}

Expand All @@ -22,7 +26,25 @@ public ModuleFactoryResult Create()
{
PEReaderParameters = new PEReaderParameters(_errorListener)
};
var module = ModuleDefinition.FromBytes(_bytes, moduleReaderParameters);

ModuleDefinition module;
try
{

module = ModuleDefinition.FromBytes(_bytes, moduleReaderParameters);
}
catch (BadImageFormatException)
{
_logger.Error(
"The file appears to be using native code (ReadyToRun). " +
"Ensure you're using a `.dll` file with non-native (managed) code. " +
"If the file is using ReadyToRun, you can disable it by adding `<PublishReadyToRun>false</PublishReadyToRun>` to your `.csproj` file. " +
"For more information, visit: https://bitmono.readthedocs.io/en/latest/obfuscationissues/ready-to-run.html " +
"Alternatively, the file might be broken, protected, or obfuscated. " +
"If neither of these cases apply, please contact us for support."
);
throw;
}

var managedPEImageBuilder =
new ManagedPEImageBuilder(new DotNetDirectoryFactory(_metadataBuilderFlags), _errorListener);
Expand Down
4 changes: 2 additions & 2 deletions src/BitMono.Obfuscation/Starter/BitMonoStarter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ public Task<bool> StartAsync(FinalFileInfo info, IModuleFactory moduleFactory, I
public Task<bool> StartAsync(CompleteFileInfo info, CancellationToken cancellationToken)
{
return StartAsync(new FinalFileInfo(info.FileName, info.OutputDirectoryPath),
new ModuleFactory(info.FileData, _obfuscationSettings, new LogErrorListener(_logger, _obfuscationSettings)),
new ModuleFactory(info.FileData, _obfuscationSettings, new LogErrorListener(_logger, _obfuscationSettings), _logger),
new FileDataWriter(), new AutomaticReferencesDataResolver(info.FileReferences), cancellationToken);
}
public Task<bool> StartAsync(IncompleteFileInfo info, CancellationToken cancellationToken)
{
return StartAsync(new FinalFileInfo(info.FilePath, info.OutputDirectoryPath),
new ModuleFactory(File.ReadAllBytes(info.FilePath), _obfuscationSettings, new LogErrorListener(_logger, _obfuscationSettings)),
new ModuleFactory(File.ReadAllBytes(info.FilePath), _obfuscationSettings, new LogErrorListener(_logger, _obfuscationSettings), _logger),
new FileDataWriter(), new AutomaticPathReferencesDataResolver(info.ReferencesDirectoryPath), cancellationToken);
}
}
33 changes: 17 additions & 16 deletions src/BitMono.Protections/AntiDe4dot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,23 @@ public AntiDe4dot(IServiceProvider serviceProvider) : base(serviceProvider)

public override Task ExecuteAsync()
{
CustomInjector.InjectAttribute(Context.Module, "SmartAssembly.Attributes", "PoweredBy", string.Empty);
CustomInjector.InjectAttribute(Context.Module, "Xenocode.Client.Attributes.AssemblyAttributes", "PoweredBy", string.Empty);
CustomInjector.InjectAttribute(Context.Module, string.Empty, "ObfuscatedByGoliath", string.Empty);
CustomInjector.InjectAttribute(Context.Module, "SecureTeam.Attributes", "ObfuscatedByAgileDotNet", string.Empty);
CustomInjector.InjectAttribute(Context.Module, string.Empty, "TrinityObfuscator", string.Empty);
CustomInjector.InjectAttribute(Context.Module, "SecureTeam.Attributes", "ObfuscatedByCliSecure", string.Empty);
CustomInjector.InjectAttribute(Context.Module, string.Empty, "ZYXDNGuarder", string.Empty);
CustomInjector.InjectAttribute(Context.Module, string.Empty, "BabelObfuscator", string.Empty);
CustomInjector.InjectAttribute(Context.Module, string.Empty, "BabelObfuscator", string.Empty);
CustomInjector.InjectAttribute(Context.Module, string.Empty, "Dotfuscator", string.Empty);
CustomInjector.InjectAttribute(Context.Module, string.Empty, "Centos", string.Empty);
CustomInjector.InjectAttribute(Context.Module, string.Empty, "ConfusedBy", string.Empty);
CustomInjector.InjectAttribute(Context.Module, "NineRays.Obfuscator", "Evaluation", string.Empty);
CustomInjector.InjectAttribute(Context.Module, "CryptoObfuscator", "ProtectedWithCryptoObfuscator", string.Empty);
CustomInjector.InjectAttribute(Context.Module, string.Empty, "();\u0009", string.Empty);
CustomInjector.InjectAttribute(Context.Module, string.Empty, "EMyPID_8234_", string.Empty);
var module = Context.Module;
CustomInjector.InjectAttribute(module, "SmartAssembly.Attributes", "PoweredBy", string.Empty);
CustomInjector.InjectAttribute(module, "Xenocode.Client.Attributes.AssemblyAttributes", "PoweredBy", string.Empty);
CustomInjector.InjectAttribute(module, string.Empty, "ObfuscatedByGoliath", string.Empty);
CustomInjector.InjectAttribute(module, "SecureTeam.Attributes", "ObfuscatedByAgileDotNet", string.Empty);
CustomInjector.InjectAttribute(module, string.Empty, "TrinityObfuscator", string.Empty);
CustomInjector.InjectAttribute(module, "SecureTeam.Attributes", "ObfuscatedByCliSecure", string.Empty);
CustomInjector.InjectAttribute(module, string.Empty, "ZYXDNGuarder", string.Empty);
CustomInjector.InjectAttribute(module, string.Empty, "BabelObfuscator", string.Empty);
CustomInjector.InjectAttribute(module, string.Empty, "BabelObfuscator", string.Empty);
CustomInjector.InjectAttribute(module, string.Empty, "Dotfuscator", string.Empty);
CustomInjector.InjectAttribute(module, string.Empty, "Centos", string.Empty);
CustomInjector.InjectAttribute(module, string.Empty, "ConfusedBy", string.Empty);
CustomInjector.InjectAttribute(module, "NineRays.Obfuscator", "Evaluation", string.Empty);
CustomInjector.InjectAttribute(module, "CryptoObfuscator", "ProtectedWithCryptoObfuscator", string.Empty);
CustomInjector.InjectAttribute(module, string.Empty, "();\u0009", string.Empty);
CustomInjector.InjectAttribute(module, string.Empty, "EMyPID_8234_", string.Empty);
return Task.CompletedTask;
}
}
Loading

0 comments on commit 7d25bb2

Please sign in to comment.