NEW SigBreaker 1.0 is now public..

· 5 min read

A Deep Dive into Our LLVM-MSVC Integration

Repository for this blog

Introduction

At Back Engineering Labs, we are continuously pushing the boundaries of binary rewriting and recompilation with our powerful framework, BLARE. One of the standout features of BLARE is its Module Extension System, which allows us to statically link additional functions and data generated by llvm-msvc (our inhouse fork of llvm) into a pre-existing compiled program. This feature is essential for writing security solutions such as anti tamper, import protection, packers, anti-cheats, and much more.

Using llvm-msvc, you can write C, C++ and Rust code, including inline assembly, and build complete projects using our custom compiler settings. These projects are then compiled into a specialized file format that BLARE can parse. Once parsed, BLARE extracts the relevant functions and data from the compiled files. Passes written in BLARE manage how these functions and symbols are integrated into the target binary. For example, we can replace the entry point of a program with a custom function written and compiled with llvm-msvc to open a MessageBox displaying “Hello World”. This External Module System enables developers to integrate their anti-tamper solutions directly with any precompiled binary that BLARE supports, including those that weren’t originally written in C, C++ or Rust.

Traditionally, anti-cheat modules are delivered as DLLs, dynamically linked into the game. Unfortunately, this approach isolates the anti-cheat code, making it more vulnerable to attacks. BLARE’s static post-compilation linking provides a more robust and secure method of integration, making it harder for attackers to tamper with the code and offering much greater possibilities for security.

Technical Details

To enable seamless integration of external modules, BLARE employs a specialized DLL file format where each data directory is placed in its own dedicated section. By default, standard compilers merge sections such as .idata (import data) and .rdata (read-only data), which complicates the process of isolating specific regions of the binary. To address this, we modified llvm-msvc to include a custom compiler option that prevents these sections from being merged during compilation. This added degree of separation mitigates many of the traditionally undecidable aspects of binary rewriting, allowing blare to rearrange data and discard pieces that it will rewrite later after obfuscation. Furthermore, sections like .rdata, .data, and .bss are treated as distinct symbols. The diagram below illustrates how these modules are lifted and symbolized by BLARE.

image

After the lifting process, functions, which are now CodeSymbols, can be obfuscated the same as any other function from the original binary, using any one of BLARE’s existing obfuscation passes.

Advanced Relocation Management

Additionally, relocations are fully lifted to BLARE’s linker system, enabling symbols to reference one another in various ways, such as being relative to each other or offset from the start of a symbol. This is particularly useful for handling structures that contain constant references to strings, functions, and other data. For example:

struct {
    const char* pStr = “Hello World”;
    PIMAGE_DOS_HEADER pBase = &__ImageBase;
} Example;

In this structure:

  • The pStr field generates a relocation to the string “Hello World”, which resides in the .rdata section.
  • The pBase field produces a relocation pointing to the base of the image.

BLARE’s linker capabilities handle these relocations effortlessly, including resolving image base references and other complex symbol relationships, ensuring that all necessary data is correctly linked and symbolized.

Miscellaneous Features

Functions within external modules are seamlessly integrated with Control Flow Guard (CFG) protections if the main precompiled binary has them enabled, ensuring that critical security measures remain intact. This is particularly beneficial for anti-cheat and anti-tamper systems, where maintaining control flow integrity is essential to prevent attackers from hijacking execution control. Additionally, we’ve developed a powerful SDK that gives developers the ability to perform advanced tasks, such as making direct system calls that are unwind-safe. This capability is highly valuable in anti-cheat scenarios, allowing applications to bypass common user-mode hooks and protect sensitive functionality from tampering, all while maintaining the stability and reliability of the application.

Structured Exception Handling (SEH)

BLARE imposes no restrictions on exception handling in external modules, allowing developers to use C and C++ exceptions seamlessly without encountering compatibility issues. Additionally, setjmp and longjmp can be used without any complications. When longjmp is utilized, its targets are automatically inserted into the Control Flow Guard (CFG) longjmp target table, provided that this feature is enabled in the original precompiled binary. Moreover, if Safe Exception Handlers (SAFESEH) are enabled, exception-handling continuation basic blocks are correctly inserted into the SAFESEH table, ensuring that all exception-related operations remain secure and compliant with the target binary’s security policies.

Conclusion

The integration of llvm-msvc with BLARE offers developers the ability to build C, C++ and Rust projects that leverage LLVM’s powerful features while simultaneously benefiting from CodeDefender’s advanced obfuscation passes. The resulting build targets are then statically linked directly into the target binaries, providing a robust solution for enhancing security in applications. This technology paves the way for the development of sophisticated anti-cheat, anti-tamper and anti-debug techniques.

If you’re interested in contracting us to develop custom security solutions for your application, feel free to reach out at contact@back.engineering. Additionally, if you’re looking to develop your own llvm-msvc external module, we offer an SDK to help you get started.

    Share:
    Back to Blog