LLVM obfuscation is a LLVM pass plugin, used to apply transformation on LLVM assembly language to provide obfuscation.
All credit goes to eShards and Forta for the implementation. I just updated 3 lines of code and wrote an exshaustive README.md file. The projects can be found below:
https://github.com/eshard/obfuscator-llvm
https://github.com/Cobalt-Strike/obfuscator-llvm
To build this plugin you need to build LLVM. Refer to the documentation for more information.
Navigate to Winlibs and install the latest release of GCC + LLVM/Clang + Mingw
Once installed, unzip the archive and move the directory to your preferred location. I recommend installing it in C:\mingw, as that’s what I use, and it will be easier to follow along.
To quickly access the System Properties in Windows to add or edit PATH variables, you can follow these steps:
- Press Windows + R to open the Run dialog.
- Type
sysdm.cpl
and hit Enter.
This will open the System Properties window. From there:
- Go to the Advanced tab.
- Click on the Environment Variables button.
- Under System variables, scroll down and select the Path variable, then click Edit to add or modify entries.
- Add the location of your mingw folder to Path.
To check the version of clang
in your system using PowerShell, follow these steps:
-
Open PowerShell (Press
Windows + X
and choose Windows PowerShell or Windows Terminal). -
Type the following command and press Enter:
clang.exe --version
You should see output similar to this:
(built by Brecht Sanders, r3) clang version 19.1.7 Target: x86_64-w64-windows-gnu Thread model: posix InstalledDir: C:/mingw64/bin PS C:\Users\dev>
My Clang version is 19.1.7, so I'll be using that.
# Obfuscator is your project; we'll use this for the LLVM & llvm-obfuscator directoreis.
mkdir Obfuscator
cd ./Obfuscator/
git clone --depth 1 --branch llvmorg-19.1.7 https://github.com/llvm/llvm-project.git
cd llvm-project
mkdir build
cd build
cmake -G "Ninja" `
-DCMAKE_INSTALL_PREFIX="C:\LLVM" `
-DCMAKE_C_COMPILER="C:\mingw64\bin\x86_64-w64-mingw32-gcc.exe" `
-DCMAKE_CXX_COMPILER="C:\mingw64\bin\x86_64-w64-mingw32-g++.exe" `
-DCMAKE_ASM_COMPILER="C:\mingw64\bin\x86_64-w64-mingw32-gcc.exe" `
-DCMAKE_CXX_STANDARD=17 `
-DPython3_EXECUTABLE="C:\mingw64\lib\python3.9\venv\scripts\nt\python.exe" `
-DBUILD_SHARED_LIBS=on `
-DCMAKE_BUILD_TYPE=Release `
..\llvm\
Depending on your hardware, you may want to increment/decrement the number of concurrent jobs (-j1, -j2, -j8)
ninja -j1
ninja install
cd ..\..
git clone https://github.com/rottaj/obfuscator-llvm.git
cd obfuscator-llvm
mkdir build
cd build
cmake -G "Ninja" `
-DLLVM_DIR="C:\LLVM\lib\cmake" `
-DCMAKE_C_COMPILER="C:\mingw64\bin\x86_64-w64-mingw32-gcc.exe" `
-DCMAKE_CXX_COMPILER="C:\mingw64\bin\x86_64-w64-mingw32-g++.exe" `
-DCMAKE_ASM_COMPILER="C:\mingw64\bin\x86_64-w64-mingw32-gcc.exe" `
-DCMAKE_CXX_STANDARD=17 `
-DPython3_EXECUTABLE="C:\mingw64\lib\python3.9\venv\scripts\nt\python.exe" `
-DBUILD_SHARED_LIBS=on `
-DCMAKE_BUILD_TYPE=Release `
..
ninja -j1
If everything worked, you'll see a libLLVMObfuscator.dll in the build directory of obfuscator-llvm, which you can use with Clang.
clang -fpass-plugin="C:\Users\dev\Obfuscator\obfuscator-llvm\build\libLLVMObfuscator.dll" \
.\main.c -o main.exe
If the compilation is successful the plugin is libLLVMObfuscator.so
and can be used with clang (-fpass-plugin=
) or opt (-load-pass-plugin
).
(Taken from original https://github.com/eshard/obfuscator-llvm & https://github.com/Cobalt-Strike/obfuscator-llvm)
This plugin can be used with clang's switch -fpass-plugin
and depending on your llvm version in addition
you may need to specify -fno-legacy-pass-manager
.
clang -fno-legacy-pass-manager -fpass-plugin=<path/to/llvm/obfuscation>/libLLVMObfuscator.so hello_world.c -o hello_world
You can chose to insert passes in the optimization pipeline by setting the following environment variables before running clang:
- LLVM_OBF_PEEPHOLE_PASSES
- LLVM_OBF_SCALAROPTIMIZERLATE_PASSES
- LLVM_OBF_VECTORIZERSTART_PASSES
- LLVM_OBF_PIPELINESTART_PASSES
- LLVM_OBF_PIPELINEEARLYSIMPLIFICATION_PASSES
- LLVM_OBF_OPTIMIZERLASTEP_PASSES
For instance if you want to run the flattening, bogus and substitution passes in that order, you can do:
export LLVM_OBF_SCALAROPTIMIZERLATE_PASSES="flattening,bogus,substitution,split-basic-blocks"
Refer to the llvm::PassBuilder documentation for more information on each insertion point.
opt
can be used to apply specific passes from LLRM-IR you
would pre-generate using clang
.
# pre-generate llvm bytecode
clang -01 -S -emit-llvm hello_world.c -o hello_world.bc
# apply the pass
opt --relocation-model=pic -load-pass-plugin <path/to/llvm/obfuscation>/libLLVMObfuscator.so
-passes="<my-pass-name>" hello_world.bc -o hello_world_obfuscated.bc
# generate an object file with llc
llc --relocation-model=pic -filetype=obj hello_world_obfuscated.bc -o hello_world_obfuscated.o
# generate the binary file with clang
clang hello_world_obfuscated.o -o hello_world_obfuscated
https://github.com/eshard/obfuscator-llvm
https://github.com/Cobalt-Strike/obfuscator-llvm