If you, like me, want to distribute a binary executable program for macOS and introduce at least a minimal level of protection—such as hiding text and literals in the binary or obfuscating the code—you may notice that, as of now (end of 2024), few tools are available for this purpose. Unlike Windows, which has numerous EXE protection software options, macOS developers often find themselves at a disadvantage due to the lack of such tools.
This information may be helpful if you are developing in C or C++ and compiling your program using GCC or Clang.
I found “Hikari”, a custom Clang toolchain: https://github.com/HikariObfuscator/Hikari
Although its page says that it is already deprecated as of 2024, it is still usable and has at least a few actively maintained forks.
Hikari is a modified version of LLVM that incorporates several advanced obfuscation techniques to protect software from reverse engineering. Obfuscation in Hikari essentially transforms the code so that it is functionally the same but is much harder for a reverse engineer to analyze and understand. Here’s an overview of the main concepts and techniques involved in Hikari obfuscation:
1. Purpose of Obfuscation
Obfuscation aims to protect intellectual property, software algorithms, and proprietary logic from being extracted or understood through reverse engineering. By making the code harder to read or follow, obfuscation raises the difficulty of tasks like decompiling, debugging, or reconstructing code logic. It can increase the time, resources, and expertise needed to analyze a binary, deterring attackers or making reverse engineering impractical.
2. Techniques Used in Hikari Obfuscation
Hikari employs a variety of techniques, which can be enabled individually or as a package. Here are some of the core methods:
A. Control Flow Flattening
- Concept: Control flow flattening reorders and reorganizes the control flow in a way that hides the logical structure of the code.
- Implementation: Hikari uses a “dispatcher loop” that handles all branching within a function. Instead of straightforward conditional branches, a central dispatcher routes the program flow based on values, making it challenging to reconstruct the original branching structure.
- Effect: This approach confuses tools that attempt to follow the program’s execution path, making it much harder to understand the logic and purpose of functions.
B. Bogus Control Flow Insertion
- Concept: Bogus control flow adds fake or meaningless code paths that appear as potential execution paths but are never used.
- Implementation: Hikari inserts fake branches and conditions that look valid but do not affect the actual program outcome. These branches are interwoven with the real ones.
- Effect: By adding these paths, Hikari increases the complexity of the program’s control flow, making static analysis and decompilation much harder. The extraneous paths mislead reverse engineers, wasting their time on non-functional code paths.
C. Function Call Obfuscation
- Concept: Function call obfuscation hides or complicates direct calls to functions, making it harder to trace function calls and understand inter-function relationships.
- Implementation: Hikari can replace direct function calls with indirect calls or use lookup tables, where a function is called by referencing its address through an intermediary step.
- Effect: This obfuscation disrupts typical static analysis methods that rely on direct calls, making it harder to