Skip to content

Modified Emscripten compiler with LLVM-level obfuscation

Notifications You must be signed in to change notification settings

HakonHarnes/emcc-obf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 

Repository files navigation

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

Flag Description Default
All obfuscation
enable-allobf Enable all obfuscation passes. false
AntiClassDump
enable-acdobf Enable AntiClassDump pass. false
acd-use-initialize Inject codes to initialize. true
acd-rename-methodimp Rename methods imp. false
AntiDebugging
enable-adb Enable AntiDebugging pass. false
adbextirpath External path pointing to pre-compiled AntiDebugging IR. ""
adb_prob Probability (%) for each function to be obfuscated by AntiDebugging. 40
AntiHooking
enable-antihook Enable AntiHooking pass. false
adhexrirpath External path pointing to pre-compiled AntiHooking IR. ""
ah_inline Check Inline Hook for AArch64. true
ah_objcruntime Check Objective-C Runtime Hook. true
ah_antirebind Make fishhook unavailable. false
BogusControlFlow
enable-bcfobf Enable BogusControlFlow pass. false
bcf_prob Probability (%) for each basic block to be obfuscated by BogusControlFlow. 70
bcf_loop How many times the BogusControlFlow pass is applied per basic block. 1
bcf_cond_compl The complexity of the expression used to generate branching condition. 3
bcf_junkasm Add junk assembly to each basic block. false
bcf_onlyjunkasm Only add junk assembly to each basic block. false
bcf_junkasm_maxnum The maximum number of junk assembly per basic block. 4
bcf_junkasm_minnum The minimum number of junk assembly per basic block. 2
bcf_createfunc Create function for each opaque predicate. ``
BasicBlockSplit
enable-splitobf Enable BasicBlockSplit pass. false
split_num How many times the BasicBlockSplit pass is applied per basic block. 2
ConstantEncryption
enable-constenc Enable ConstantEncryption pass. false
constenc_prob Probability (%) that an instruction will be obfuscated by the ConstantEncryption pass. 50
constenc_times How many times the ConstantEncryption pass is applied per function. 1
constenc_subxor Substitute xor operator of ConstantEncryption. false
constenc_togv Replace ConstantInt with GlobalVariable. false
Flattening
enable-cffobf Enable Flattening pass. false
FunctionCallObfuscate
enable-fco Enable FunctionCallObfuscate pass. false
fcoconfig FunctionCallObfuscate configuration path. "+-x/"
fco_flag The value of RTLD_DEFAULT on your platform. -1
FunctionWrapper
enable-funcwra Enable FunctionWrapper pass. false
fw_prob Probability (%) for each CallSite to be obfuscated by the FunctionWrapper pass. 30
fw_times How many times the FunctionWrapper pass is applied per CallSite. 2
IndirectBranches
enable-indibran Enable IndirectBranches pass. false
indibran-use-stack Enable stack-based indirect jumps. false
indibran-enc-jump-target Encrypt jump target. false
Substitution
enable-subobf Enable Substitution pass. false
sub_prob Probability (%) that an instruction will be obfuscated by the Substitution pass. 50
sub_loop How many times the Substitution pass is applied per function. 1
StringEncryption
enable-strcry Enable StringEncryption pass. false
strcry_prob Probability (%) that the StringEncryption pass is applied per element of ConstantDataSequential. 100
Seed
aesSeed Seed for the PRNG. 0x1337

Environment variables

Environment Variable Description
ALLOBF Enable all obfuscation passes.
ACDOBF Enable AntiClassDump pass.
ADB Enable AntiDebugging pass.
ANTIHOOK Enable AntiHooking pass.
BCFOBF Enable BogusControlFlow pass.
SPLITOBF Enable BasicBlockSplit pass.
CONSTENC Enable ConstantEncryption pass.
CFFOBF Enable Flattening pass.
FCO Enable FunctionCallObfuscate pass.
FUNCWRA Enable FunctionWrapper pass.
INDIBRAN Enable IndirectBranches pass.
SUBOBF Enable Substitution pass.
STRCRY Enable 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:

  • gcc
  • cmake
  • ninja
  • nodejs
  • python3

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.

About

Modified Emscripten compiler with LLVM-level obfuscation

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages