SkillAgentSearch skills...

Obfusk8

Obfusk8: lightweight Obfuscation library based on C++17 / Header Only for windows binaries

Install / Use

/learn @x86byte/Obfusk8

README

Obfusk8: C++17-Based Obfuscation Library

Obfusk8 is a lightweight, header-only C++17 library designed to significantly enhance the obfuscation of your applications, making reverse engineering a substantially more challenging endeavor. It achieves this through a diverse set of compile-time and runtime techniques aimed at protecting your code's logic and data.

banner


Table of Contents

  1. Core Obfuscation Strategies
  2. Dependencies
  3. Visualisation
  4. Engine Analysis and Detection Profile
  5. Structural and Forensic Characteristics
  6. Usage
  7. Building
  8. Demo
  9. contribution & Feedback

Core Obfuscation Strategies

1. main Function Wrapping (_main Macro)

The entry point of your application (main) is transformed into a complex, multi-layered obfuscation engine:

  • Virtual Machine (VM) Execution (Conceptual): Before your actual main_body code is executed, a mini-VM (simulated CPU) runs a sequence of "encrypted" instructions. This conceals the true entry point and initial operations. The VM's state (registers, program counter, dispatch key) is initialized with runtime-randomized values.
  • Indirect Control Flow Flattening (ICFF): Critical loops within the _main macro (both in the prologue and epilogue) are transformed into intricate state machines. Control flow is not direct but determined by heavily "encrypted" state variables. The encoding/decoding keys for these state variables are dynamic, derived from VM state, loop counters, compile-time randomness (like __COUNTER__, __LINE__, __TIME__), and a global opaque seed. This makes static analysis of the control flow exceptionally difficult.
    • Two distinct ICFF engines (obf_icff_ns_dcff and obf_icff_ns_epd) are used with different state transition logic and key generation, further complicating analysis.
  • Bogus Control Flow (OBF_BOGUS_FLOW_* macros): Numerous misleading jump patterns and convoluted conditional structures are injected throughout _main. These use goto statements combined with opaque predicates (conditions that always evaluate to true or false but are computationally expensive or hard to determine statically). This creates a labyrinth of false paths for disassemblers and decompilers.
    • Includes OBF_BOGUS_FLOW_LABYRINTH, OBF_BOGUS_FLOW_GRID, OBF_BOGUS_FLOW_SCRAMBLE, OBF_BOGUS_FLOW_WEAVER, OBF_BOGUS_FLOW_CASCADE, and OBF_BOGUS_FLOW_CYCLONE to generate diverse and complex bogus flows.
  • Anti-Analysis & Anti-Debug Tricks (Runtime macro, SEH):
    • Forced Exceptions & SEH: Structured Exception Handling (SEH) is used to create paths that involve forced exceptions. The __except blocks can alter program state, making it hard to follow if the debugger skips exceptions.
    • Debugger Checks (Conceptual): The Runtime macro contains conditions that, if met (due to specific VM states or timing), could trigger __debugbreak() or throw exceptions, designed to disrupt debugging sessions.

2. Virtual ISA Engine (obf_vm_engine)

A core component of the _main macro's obfuscation:

  • Custom Mini-CPU Simulation: Simulates a CPU with volatile registers (r0, r1, r2), a program counter (pc), and a dispatch_key. It executes custom "instructions" (handlers).
  • Obfuscated Instructions: VM instruction handlers perform operations that are heavily disguised using Mixed Boolean-Arithmetic (MBA) and bitwise manipulations. Handlers include arithmetic, bitwise logic, key mangling, junk sequences, conditional updates, memory simulation, and PC mangling.
  • Dynamic Dispatch: The selection of the next VM instruction handler is randomized through multiple dispatch mechanisms:
    • Register-based dispatch (reg_dispatch_idx).
    • Memory-table based dispatch (scrambled function pointer table get_mem_dispatch_table).
    • Mixed dispatch (mixed_dispatch_idx). The dispatch_key is constantly mutated, making the sequence of executed handlers highly unpredictable.
  • Handler Table Mutation: The table of VM instruction handlers (vm_handler_table) is itself mutated at runtime within the _main prologue and epilogue, further obscuring the VM's behavior.

3. Compile-Time String Encryption (OBFUSCATE_STRING from AES8.hpp)

  • Hidden Strings: Encrypts all string literals at compile-time using a modified AES cipher.
  • Dynamic Keys: Encryption keys are unique per string instance, derived from string content, file location (__FILE__, __LINE__), and build time (__DATE__, __TIME__).
  • Just-In-Time Decryption: Strings are decrypted on the stack only when accessed at runtime, minimizing their plaintext lifetime in memory.
  • (Optional) Decoy PE Sections: Can store encrypted strings in custom PE sections designed to mimic common packer signatures, potentially misleading analysts (MSVC-specific feature from AES8.hpp).

4. Stealthy Windows API Calling (STEALTH_API_OBFSTR / STEALTH_API_OBF from Resolve8.hpp)

  • IAT Obscurity: Avoids leaving direct, easily identifiable entries for Windows APIs in the Import Address Table (IAT).
  • PEB-Based Resolution: Dynamically finds base addresses of loaded DLLs and the addresses of API functions by directly parsing Process Environment Block (PEB) data structures at runtime. This bypasses standard GetModuleHandle and GetProcAddress for initial resolution if those themselves are not yet resolved by this mechanism.
  • Hashed Names: Uses compile-time hashing (custom algorithm CT_HASH) of DLL and API names for lookups. This prevents plaintext DLL and API names from appearing in the binary's import-related data or string tables when using these macros.

5. Indirect Syscall Engine (K8_SYSCALL)

Obfusk8 now integrates a state-of-the-art Indirect Syscall mechanism to bypass User-Mode Hooks (EDRs/AVs) and static analysis checks.

  • "The Sorting Hat" Resolution: Instead of reading the .text section of ntdll.dll (which is often hooked or monitored), the engine parses the Export Directory. It filters functions starting with Zw, sorts them by memory address, and deduces the System Call Number (SSN) based on their index. This allows SSN resolution without ever touching executable code.
  • Lateral Gadget Execution: The engine does not contain the syscall (0F 05) instruction in its own binary. Instead, it locates a valid syscall; ret gadget inside ntdll.dll memory at runtime. Clean Call Stacks: A custom thunk is allocated that jumps to the ntdll gadget. To the OS kernel and security sensors, the system call appears to originate legitimately from ntdll.dll, maintaining a clean call stack.
  • Usage: Simply use K8_SYSCALL("ZwOpenProcess", ...) instead of NtOpenProcess.

6. Method-Based Obfuscation with (OBF_METHOD)

Obfusk8 now provides granular control over your binary's security through Method-Based Obfuscation. Instead of obfuscating your entire project (which can impact performance), you can now selectively protect specific, high-value functions or class methods.


How to Use

  1. Include the Pass
    Ensure you include the method obfuscation logic in your project:

    #include "../transform/PASSES/obf_cmethods.cxx"
    
  2. The Macro Syntax
    Define your method using the OBF_METHOD macro:

    OBF_METHOD(ret_type, func_name, params, method_body)
    
    • ret_type: The return type of your function (e.g., bool, int, void*).
    • func_name: The name of the method.
    • params: The function parameters (must be enclosed in parentheses).
    • method_body: The actual logic of your function enclosed in { }.

Example: Standard vs Obfuscated methods

In this example, PrintStatus is a normal, readable function. Obfusk8_PrintStatus is protected by Obfusk8.

#include "../Instrumentation/materialization/state/Obfusk8Core.hpp"
#include "../Instrumentation/materialization/transform/K8_UTILS/k8_utils.hpp" // for the printf_, u can change the printf_ with anything else...

class Obfusk8_C
{
public:
    // standard method which is visible to reverse engineers
    void PrintStatus(void)
    {
        printf_("method\n");
    }

    // Obfuscated method protected by Obfusk8
    OBF_METHOD_(void, Obfusk8_PrintStatus, (void),
    {
        printf_("same method but Obfuscated\n");
    })
};

_main({
    Obfusk8_C *pp = new Obfusk8_C;
    pp->PrintStatus();
    pp->Obfusk8_PrintStatus();
    delete pp;
})

You can view the full example here: obfusk8_methods.cpp


6. API Abstraction Classes with Built-in Stealth

Obfusk8 provides helper classes that encapsulate common sets of Windows APIs. These classes automatically use the stealthy API resolution mechanism (STEALTH_API_OBFSTR) during their construction, ensuring that the underlying Windows functions are resolved without leaving obvious static import traces.

  • K8_ProcessManipulationAPIs::ProcessAPI (k8_ProcessManipulationAPIs.hpp):
    • Provides convenient access to Windows APIs for process manipulation, such as OpenProcess, TerminateProcess, CreateRemoteThread, VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, GetProcAddress, GetModuleHandleA, NtQueryInformationProcess, SuspendThread, and GetCurrentProcessId.
    • Automatic Stealth Resolution: Resolves necessary functions from kernel32.dll and ntdll.dll stealthily.
    • Simplifies performing process-related operations with a reduced static analysis footprint. Includes the `P
View on GitHub
GitHub Stars664
CategoryDevelopment
Updated14h ago
Forks63

Languages

C++

Security Score

100/100

Audited on Mar 27, 2026

No findings