Giter Club home page Giter Club logo

hanabi's Introduction

花火

Hassle-free Obfuscator-Enabled Apple Clang without any sort of compromise.

License

Please refer to License.

Note that this linked version of license text overrides any artifact left in source code

Must be this tall to ride

Due to its hackish nature (Which is why I don't want to do this in the first place), you should probably know some LLVM/macOS Hooking/Binary Patching and stuff to debug this thing

Modifications

This project uses a slightly modified Hikari upstream ported back to LLVM 6.0.1 (The version Apple is using) to avoid any potential issues, although it should work with LLVM7.0 as base. Most of the modifications are done to load options without hacking llvm::cl as well as some LLVM building configurations.

Using Release Builds

  • Extract the zipped file and move two extracted dylibs under /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
  • Run optool install -c load -p @executable_path/libInjector.dylib -t /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -b /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/

Building

Obtaining Source

  • git clone --recursive https://github.com/HikariObfuscator/Hanabi.git
  • cd Hanabi
  • git submodule update --remote --recursive

Core

Create a folder called build/ in project root, inside it build the attached LLVM with cmake ../LLVM -DHIKARI_ENABLE_FP=OFF -DCMAKE_BUILD_TYPE=Release -DLLVM_ABI_BREAKING_CHECKS=FORCE_OFF -G Ninja and ninja LLVMObfuscation LLVMCore LLVMTransformUtils LLVMAnalysis.

Loader

Create a folder called build/ in Loader/, inside it build the Loader with cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ../ and ninja. Copy Loader/build/libInjector.dylib and Loader/libsubstitute.dylib to /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/

Patching

You need to build https://github.com/alexzielenski/optool and put it in your $PATH, then optool install -c load -p @executable_path/libInjector.dylib -t /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang (Remember to backup your original Clang first)

Using

Due to many LLVM internal design choices, you can no longer pass options from command line and instead you'll have to use environment variables. Currently it supports the following:

  • SPLITOBF EnableBasicBlockSplit
  • SUBOBF EnableSubstitution
  • ALLOBF EnableAllObfuscation
  • FCO EnableFunctionCallObfuscate
  • STRCRY EnableStringEncryption
  • INDIBRAN EnableIndirectBranching
  • FUNCWRA EnableFunctionWrapper
  • BCFOBF EnableBogusControlFlow
  • ACDOBF EnableAntiClassDump
  • CFFOBF EnableFlattening

Basically it means you will need to follow the following steps:

  • Open up a terminal
  • export the env vars you need
  • /Applications/Xcode.app/Contents/MacOS/Xcode

This should get you a properly initialized Xcode.

Or alternatively, manually edit LoadEnv() in Obfuscation.cpp to initialize the flags in a way you prefer

Known Issues

  • LLVM 6.0.1 (which Apple's Clang and this project is currently based on) has bugs related to indirectbr CodeGeneration, you might get a crash if you enable INDIBRAN. Another more robust solution would be hook those parts and pipe the CodeGeneration pipeline back to LLVM7.0 but I couldn't be less bothered for that
  • Floating Point Instructions will sometimes result in an infinite loop in shipped LLVM's ConstantFP(Thanks to @UESTC-LXY for discovering this) This has been fixed by adding an option in upstream core to disable FP operations

Future enhancements

  • Hijacking PMB is IMHO a little bit too late into the compilation pipeline. A better approach would be hijacking Clang's raw AST, reuse our own shipped Clang CG, run through the rest of our own optimization pipeline then transfer the processed LLVM IR back to Apple LLVM? Maybe? We need more research into Apple's LLVM for this
  • Mapping LLVMContext with Apple's Context. Since the majority of IR/Constant is binded with one specific context
  • We can use LLVM's very own -mllvm -load options, however in my personal experience that thing is very troublesome and usually even more unstable.

Credits

  • Thanks to @AloneMonkey for compiling substitute and ship it with his amazing project MonkeyDev
  • Thanks to @UESTC-LXY for testing and discussion because I didn't bother to do so.

hanabi's People

Contributors

naville avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.