Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.git
.github
.vs
.vscode
bin/
obj/
Debug/
Release/
publish/
publish-net8.0/
*.sln.user
*.suo
*.user
*.pdb
*.xml
*.ps1
build-beaengine-32/
build-beaengine-64/
build64/
beaengine/
deb-root/
63 changes: 63 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# ==============================================================================
# STAGE 1: Build BeaEngine (Native Library for ConfuserEx control flow cleaning)
# ==============================================================================
FROM ubuntu:22.04 AS beaengine-builder
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y \
git \
cmake \
build-essential \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /src
RUN git clone --depth 1 --branch v5.3.0 https://github.com/BeaEngine/beaengine.git

RUN cmake -S beaengine -B build64 \
-DoptBUILD_DLL=ON \
-DoptHAS_OPTIMIZED=ON \
-DoptHAS_SYMBOLS=OFF

RUN cmake --build build64

# Dynamically locate and move the compiled .so to a standardized path
RUN mkdir -p /app && \
SO_FILE=$(find build64 -name "libBeaEngine*.so" | head -n 1) && \
if [ -n "$SO_FILE" ]; then cp "$SO_FILE" /app/libBeaEngine.so; else echo "Error: libBeaEngine.so not found!" && exit 1; fi

# ==============================================================================
# STAGE 2: Build de4dotEx (.NET 8.0 Cross-Platform Release)
# ==============================================================================
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS dotnet-builder
WORKDIR /src

# Copy all files to build
COPY . .

# Publish de4dot targeting net8.0
RUN dotnet publish -c Release -f net8.0 -o /app/publish/de4dot de4dot/de4dot.csproj
RUN rm -rf /app/publish/**/*.pdb /app/publish/**/*.xml

# ==============================================================================
# STAGE 3: Final Runtime Image (.NET 8.0 on Ubuntu / Runtime)
# ==============================================================================
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS runtime
WORKDIR /app

# Install native dependencies required for execution (e.g. globalization)
RUN apt-get update && apt-get install -y \
libicu-dev \
&& rm -rf /var/lib/apt/lists/*

# Copy de4dot published folder
COPY --from=dotnet-builder /app/publish/de4dot ./de4dot

# Copy compiled libBeaEngine.so from Stage 1 standardized path to system libraries & register
COPY --from=beaengine-builder /app/libBeaEngine.so /usr/local/lib/libBeaEngine.so
RUN ldconfig

# Create symlink for global accessibility
RUN ln -s /app/de4dot/de4dot /usr/local/bin/de4dot

ENTRYPOINT ["de4dot"]
CMD ["--help"]
78 changes: 78 additions & 0 deletions Dockerfile.wine
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# ==============================================================================
# STAGE 1: Build the .NET Framework 4.8 Targets natively on Linux
# ==============================================================================
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS dotnet-framework-builder
WORKDIR /src

# Copy all files
COPY . .

# Compile de4dot.netframework.sln targeting net48 in Release mode
# Disable RuntimeIdentifierInference and ValidateExecutableRuntimeIdentifier to bypass architecture compatibility checks on ARM64 hosts
RUN dotnet build -c Release \
-p:SolutionName=de4dot.netframework \
-p:RuntimeIdentifierInference=false \
-p:ValidateExecutableRuntimeIdentifier=false \
de4dot.netframework.sln

# ==============================================================================
# STAGE 2: Package into Headless Wine Runtime Environment
# ==============================================================================
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive

# Install dependencies, 32-bit architecture, and Wine from standard Ubuntu repositories
# On ARM64 (Apple Silicon Mac), we restrict standard mirrors to arm64 to prevent apt-get update 404 failures on i386 lists.
RUN ARCH=$(dpkg --print-architecture) && \
if [ "$ARCH" = "arm64" ]; then sed -i 's/^deb /deb [arch=arm64] /g' /etc/apt/sources.list; fi && \
dpkg --add-architecture i386 && \
apt-get update && apt-get install -y \
software-properties-common \
wget \
gnupg2 \
cabextract \
xvfb \
unzip \
wine64 \
wine \
&& rm -rf /var/lib/apt/lists/*

# Install winetricks
RUN wget -O /usr/local/bin/winetricks https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks && \
chmod +x /usr/local/bin/winetricks

# Configure wine environment
ENV WINEARCH=win64
ENV WINEPREFIX=/root/.wine
ENV DISPLAY=:0

# Pre-download official Wine Mono MSI into Wine's global shared directory.
# During wineboot -u, Wine will automatically find and register this package.
RUN mkdir -p /usr/share/wine/mono && \
wget -q -O /usr/share/wine/mono/wine-mono-7.0.0-x86.msi https://dl.winehq.org/wine/wine-mono/7.0.0/wine-mono-7.0.0-x86.msi

# Initialize wine prefix silently using Xvfb
RUN Xvfb :0 -screen 0 1024x768x16 & \
sleep 2 && \
wineboot -u && \
wineserver -w

# Set working directory inside the Wine prefix or a dedicated folder
WORKDIR /app

# Copy the compiled .NET 4.8 targets directly from Stage 1 (dotnet-framework-builder)
COPY --from=dotnet-framework-builder /src/Release/net48/ .

# Create helper script to launch de4dot through Wine in a virtual frame buffer
RUN echo '#!/bin/bash\n\
# Launch virtual framebuffer silently in the background if not already running\n\
Xvfb :0 -screen 0 1024x768x16 >/dev/null 2>&1 & \n\
sleep 1\n\
wine /app/de4dot.exe "$@"' > /usr/local/bin/de4dot && \
chmod +x /usr/local/bin/de4dot

# Define default volume for binaries to deobfuscate
VOLUME ["/work"]
WORKDIR /work

ENTRYPOINT ["de4dot"]
138 changes: 138 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ Binaries

Get binaries from the build server [![](https://github.com/GDATAAdvancedAnalytics/de4dotEx/workflows/CI%20build/badge.svg)](https://github.com/GDATAAdvancedAnalytics/de4dotEx/actions).

Docker Support
==============

de4dotEx now has fully integrated **Docker containerization** support:

* **Docker Container:** Build a single container to run de4dotEx natively or inside a cross-platform headless Wine environment. See the [Docker Containerization](#docker-containerization) section below for build and run instructions.

It's FREE but there's NO SUPPORT
================================

Expand Down Expand Up @@ -215,3 +222,134 @@ Other options
-------------

Start `de4dot` without any arguments and it will show all options.


Docker Containerization
=======================

de4dotEx includes built-in cross-platform Docker containerization. You can build a single, lightweight container and run it in three different modes: as a standard command-line utility, as an HTTP Web API microservice, or as a containerized Stdio MCP server.

We offer two different Docker strategies depending on your needs:
1. **Strategy A (Native .NET 8.0 - Recommended):** Extremely fast, lightweight, and cross-platform. It automatically compiles the native C++ `BeaEngine` disassembler library inside the container so that advanced ConfuserEx deobfuscation works natively on Linux and macOS (ARM64/x64).
2. **Strategy B (Wine + .NET Framework 4.8):** Emulates a full Windows environment to support dynamic JIT-hook protectors (like ILProtector and Agile.NET) which rely on Windows-native memory APIs (`VirtualAlloc`, `VirtualProtect`).

Strategy A: Native .NET 8.0 Linux Container (Recommended)
--------------------------------------------------------

### 1. Build the Native Image
Execute the following command in the root folder of the repository:
```bash
docker build -t de4dotex -f Dockerfile .
```

### 2. Run the Native Image
The container has an intelligent, unified entrypoint script that automatically routes execution depending on the arguments you pass:

#### A. Run as standard de4dot CLI:
```bash
# Run help
docker run --rm de4dotex --help

# Deobfuscate an assembly in your current directory (mounts pwd to /work)
docker run --rm -v "$(pwd):/work" -w /work de4dotex MyObfuscatedApp.exe -o CleanApp.exe
```

#### B. Run as containerized HTTP Web API (on port 8080):
Start the container in the background to spin up a high-performance HTTP microservice:
```bash
# Start the HTTP Microservice in background
docker run -d -p 8080:8080 --name de4dotex-api de4dotex --mcp --http

# Upload an obfuscated file and download the cleaned output
curl -F "file=@MyObfuscatedApp.dll" http://localhost:8080/deobfuscate -o CleanApp.dll

# Upload with custom native flags (e.g. preserve tokens, decrypt string delegates)
curl -F "file=@MyObfuscatedApp.dll" \
-F "options=--preserve-tokens -str delegate" \
http://localhost:8080/deobfuscate -o CleanApp.dll
```

You can also use our convenient test script **`test_api.sh`** to automatically perform the upload and save the processed output next to the original file, appending `_cleaned` (e.g. `App.dll` -> `App_cleaned.dll`):
```bash
# Basic usage:
./test_api.sh MyObfuscatedApp.dll

# Usage with custom flags:
./test_api.sh MyObfuscatedApp.dll "--preserve-tokens -str delegate"
```

#### C. Run as containerized Stdio MCP server (for AI clients):
To run the containerized MCP server directly via Claude Desktop or Cursor, configure your MCP client configuration as follows:
```json
{
"mcpServers": {
"de4dotex-docker": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"de4dotex",
"--mcp"
]
}
}
}
```
*(The `-i` flag is required to keep standard input open so the JSON-RPC streams can communicate securely.)*


Strategy B: Wine-based Container (Full Windows Compatibility)
------------------------------------------------------------

This strategy configures a headless Wine environment on Ubuntu, installs the official .NET Framework runtime via `winetricks`, and executes the Windows `.NET Framework 4.8` assemblies under Wine.

**Fully Automated Build:**
Unlike older setups, this container uses a **multi-stage build** with a **Mono SDK** builder stage (`mono:6.12.0`) to automatically restore and compile the `.NET Framework 4.8` solution (`de4dot.netframework.sln`) inside the container. **You do not need to install .NET Framework or compile anything locally on your host machine!**

### 1. Build the Wine Image
Simply run this command to restore, compile, and package the complete Wine-compatible image:
```bash
docker build -t de4dotex-wine -f Dockerfile.wine .
```

### 2. Run the Wine Image
Run the container using Wine. A virtual framebuffer (`Xvfb`) is configured automatically in the background to handle Wine's GUI requirements in headless environments.
```bash
# Run help
docker run --rm de4dotex-wine --help

# Deobfuscate an assembly requiring dynamic JIT-hook decryption (e.g. ILProtector, Agile.NET)
docker run --rm -v "$(pwd):/work" de4dotex-wine MyProtectedApp.dll -o DecryptedApp.dll
```


Docker Troubleshooting & Tips
-----------------------------

### Apple Silicon / ARM64 Mac Hosts (M1 / M2 / M3)
* **Strategy A (Native):** Runs flawlessly on ARM64 hosts. Docker automatically targets ARM64 and compiles .NET 8.0 and BeaEngine natively for your CPU architecture.
* **Strategy B (Wine):** Because Strategy B installs standard x86 `.NET Framework 4.8` components, you **MUST** force Docker to build and run the image targeting the Intel platform (`linux/amd64`). Docker Desktop on macOS will automatically translate the CPU instructions using Rosetta 2 / QEMU:
```bash
# Build on ARM64 Mac using Intel emulation:
DOCKER_BUILDKIT=0 docker build --platform linux/amd64 -t de4dotex-wine -f Dockerfile.wine .

# Run on ARM64 Mac using Intel emulation:
docker run --platform linux/amd64 --rm -v "$(pwd):/work" de4dotex-wine MyProtectedApp.dll
```

### Docker BuildKit / Buildx Errors (Legacy Builder Warnings)
If you get a warning saying `DEPRECATED: The legacy builder is deprecated` or an error saying `BuildKit is enabled but the buildx component is missing or broken`, you can easily resolve this:
* **Workaround 1 (Fastest):** Prefix your build command with `DOCKER_BUILDKIT=0` to temporarily bypass BuildKit:
```bash
DOCKER_BUILDKIT=0 docker build -t de4dotex -f Dockerfile .
```
* **Workaround 2 (Recommended for macOS):** If you are on macOS and have Homebrew, install and register the missing `buildx` component:
```bash
brew install docker-buildx
mkdir -p ~/.docker/cli-plugins
ln -sfn $(brew --prefix)/opt/docker-buildx/bin/docker-buildx ~/.docker/cli-plugins/docker-buildx
```

### Globalization/Localization Issues
* Both images are configured with native globalization components (`libicu`). If you encounter encoding issues with non-ASCII or obfuscated class/method names, make sure your terminal and volume directories are UTF-8 compliant.
Loading