Home

Awesome

emcc-obf

                                                              /##        /###### 
                                                             | ##       /##__  ##
  /######  /######/####   /#######  /#######         /###### | ####### | ##  \__/
 /##__  ##| ##_  ##_  ## /##_____/ /##_____//###### /##__  ##| ##__  ##| ####    
| ########| ## \ ## \ ##| ##      | ##     |______/| ##  \ ##| ##  \ ##| ##_/    
| ##_____/| ## | ## | ##| ##      | ##             | ##  | ##| ##  | ##| ##      
|  #######| ## | ## | ##|  #######|  #######       |  ######/| #######/| ##      
 \_______/|__/ |__/ |__/ \_______/ \_______/        \______/ |_______/ |__/      

This repository contains a modified version of the Emscripten compiler that includes an LLVM-based obfuscator. Specifically, it uses the Hikari obfuscator which is based on the obfuscator-llvm project.

Disclaimer: Some of the documentation is translated from 中文 to the best of my ability, sorry!

Table of Contents

Usage

The flags operate at the LLVM-level and have to be passed to Emscripten through the -mllvm flag. For instance, if you want to add bogus control flow and set the probability to 100% for each basic block, you would have to do:

emcc -mllvm -enable-bcfobf -mllvm -bcf_prob 100 <file>.c

To only obfuscate certain functions, see Function Annotations.

Note: You may need to turn off optimization so that the obfuscation is not optimized away by the compiler.

Flags

FlagDescriptionDefault
All obfuscation
enable-allobfEnable all obfuscation passes.false
AntiClassDump
enable-acdobfEnable AntiClassDump pass.false
acd-use-initializeInject codes to initialize.true
acd-rename-methodimpRename methods imp.false
AntiDebugging
enable-adbEnable AntiDebugging pass.false
adbextirpathExternal path pointing to pre-compiled AntiDebugging IR.""
adb_probProbability (%) for each function to be obfuscated by AntiDebugging.40
AntiHooking
enable-antihookEnable AntiHooking pass.false
adhexrirpathExternal path pointing to pre-compiled AntiHooking IR.""
ah_inlineCheck Inline Hook for AArch64.true
ah_objcruntimeCheck Objective-C Runtime Hook.true
ah_antirebindMake fishhook unavailable.false
BogusControlFlow
enable-bcfobfEnable BogusControlFlow pass.false
bcf_probProbability (%) for each basic block to be obfuscated by BogusControlFlow.70
bcf_loopHow many times the BogusControlFlow pass is applied per basic block.1
bcf_cond_complThe complexity of the expression used to generate branching condition.3
bcf_junkasmAdd junk assembly to each basic block.false
bcf_onlyjunkasmOnly add junk assembly to each basic block.false
bcf_junkasm_maxnumThe maximum number of junk assembly per basic block.4
bcf_junkasm_minnumThe minimum number of junk assembly per basic block.2
bcf_createfuncCreate function for each opaque predicate.``
BasicBlockSplit
enable-splitobfEnable BasicBlockSplit pass.false
split_numHow many times the BasicBlockSplit pass is applied per basic block.2
ConstantEncryption
enable-constencEnable ConstantEncryption pass.false
constenc_probProbability (%) that an instruction will be obfuscated by the ConstantEncryption pass.50
constenc_timesHow many times the ConstantEncryption pass is applied per function.1
constenc_subxorSubstitute xor operator of ConstantEncryption.false
constenc_togvReplace ConstantInt with GlobalVariable.false
Flattening
enable-cffobfEnable Flattening pass.false
FunctionCallObfuscate
enable-fcoEnable FunctionCallObfuscate pass.false
fcoconfigFunctionCallObfuscate configuration path."+-x/"
fco_flagThe value of RTLD_DEFAULT on your platform.-1
FunctionWrapper
enable-funcwraEnable FunctionWrapper pass.false
fw_probProbability (%) for each CallSite to be obfuscated by the FunctionWrapper pass.30
fw_timesHow many times the FunctionWrapper pass is applied per CallSite.2
IndirectBranches
enable-indibranEnable IndirectBranches pass.false
indibran-use-stackEnable stack-based indirect jumps.false
indibran-enc-jump-targetEncrypt jump target.false
Substitution
enable-subobfEnable Substitution pass.false
sub_probProbability (%) that an instruction will be obfuscated by the Substitution pass.50
sub_loopHow many times the Substitution pass is applied per function.1
StringEncryption
enable-strcryEnable StringEncryption pass.false
strcry_probProbability (%) that the StringEncryption pass is applied per element of ConstantDataSequential.100
Seed
aesSeedSeed for the PRNG.0x1337

Environment variables

Environment VariableDescription
ALLOBFEnable all obfuscation passes.
ACDOBFEnable AntiClassDump pass.
ADBEnable AntiDebugging pass.
ANTIHOOKEnable AntiHooking pass.
BCFOBFEnable BogusControlFlow pass.
SPLITOBFEnable BasicBlockSplit pass.
CONSTENCEnable ConstantEncryption pass.
CFFOBFEnable Flattening pass.
FCOEnable FunctionCallObfuscate pass.
FUNCWRAEnable FunctionWrapper pass.
INDIBRANEnable IndirectBranches pass.
SUBOBFEnable Substitution pass.
STRCRYEnable StringEncryption pass.

Building

Building with Docker

docker build -t emcc-obf .
docker run -it emcc-obf

Building from source

Emscripten does not require compilation as it uses Python. However, the LLVM (which provides Clang and wasm-ld) and Binaryen components need to be compiled. Once compiled, you can simply modify the .emscripten file to specify the correct paths for these tools using the LLVM_ROOT and BINARYEN_ROOT variables. These variables may already be correct depending on the output of emcc --generate-config. Also, for convenience the Emscripten folder should be added to your path.

Note that ninja install installs the compiled binaries in the appropriate directories (usually /usr/local/bin), which may conflict with existing installations. If you've already installed LLVM and Binaryen, omit the ninja install command and edit the .emscripten file accordingly.

Dependencies

Building locally requires the following dependencies:

Building LLVM

git clone --recursive -b llvm-16.0.0rel https://github.com/61bcdefg/Hikari-LLVM15.git hikari
cd hikari
git submodule update --remote --recursive
mkdir build && cd build
cmake -G "Ninja" -DCMAKE_BUILD_TYPE=MinSizeRel -DLLVM_APPEND_VC_REV=on -DLLVM_ENABLE_PROJECTS='lld;clang' -DLLVM_TARGETS_TO_BUILD="host;WebAssembly" -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DENABLE_LLVM_SHARED=1 ../llvm
ninja && ninja install

Building Binaryen

git clone https://github.com/WebAssembly/binaryen.git binaryen
cd binaryen
git checkout ecbebfbee12f2f25af648119604915fc37427f6f
git submodule init
git submodule update
mkdir build && cd build
cmake -G "Ninja" ..
ninja && ninja install

Configure emscripten

git clone https://github.com/emscripten-core/emscripten.git emscripten
git checkout fab93a2bff6273c882b0c7fb7b54eccc37276e03
emcc --generate-config
npm i

License

See Hikari/License.