diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..220442ff --- /dev/null +++ b/.dockerignore @@ -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/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..d72aae9d --- /dev/null +++ b/Dockerfile @@ -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"] diff --git a/Dockerfile.wine b/Dockerfile.wine new file mode 100644 index 00000000..125c6702 --- /dev/null +++ b/Dockerfile.wine @@ -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"] diff --git a/README.md b/README.md index d15d95a0..5510f0c7 100644 --- a/README.md +++ b/README.md @@ -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 ================================ @@ -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.