SkillAgentSearch skills...

RedFat

A binary hardening system

Install / Use

/learn @GJDuck/RedFat

README

RedFat -- A Binary Hardening System

RedFat is a tool for automatically hardening Linux x86_64 ELF binary executables against memory errors, including buffer overflows and use-after-free errors.

RedFat is based on an amalgamation of two complementary memory error detection technologies:

  • Poisoned Redzones
  • Low-Fat-Pointers

Using low-fat-pointers with binary code has some caveats, as is discussed below.

Releases

Binary releases of RedFat are available here:

Building

To build RedFat, simply run the script:

    $ ./build.sh

Basic Usage

To use RedFat. simply run redfat with the name of a binary executable, e.g.:

    $ ./redfat xterm

This will generate a hardened xterm.redfat binary. To run the binary, the libredfat.so runtime system must be LD_PRELOAD'ed as follows:

    $ LD_PRELOAD=$PWD/libredfat.so ./xterm.redfat

Advanced Usage

The basic usage may suffer from false detections with some binaries. This occurs when program (or compiler) deliberately creates out-of-bounds (OOB) pointers, and accessing such OOB pointers is indistinguishable from "real" memory errors under the basic low-fat-pointer checking.

To mitigate false detections, we can use dynamic analysis to determine which memory access operations are likely to cause false detections.

First, we build an allow-list-generation version of the binary:

    $ ./redfat -Xallowlist-gen xterm

This will generate an xterm.gen file that can be used to generate an allow-list. To use, run the gen version of the binary on a suitable test suite, ideally to maximize coverage:

    $ LD_PRELOAD=$PWD/libredfat.so ./xterm.gen

This process will generate an xterm.allow file which contains information about each memory access.

Next, we run redfat using the allow-list:

    $ ./redfat -Xallowlist-use xterm

This will generate a hardened xterm.redfat binary. This version uses a more conservative instrumentation for memory access operations that are likely to be false detections.

Options

The redfat tool supports several options to control the instrumentation and optimization levels.

The main instrumentation options are:

  • -Xlowfat (-Xlowfat=false): Enables (disables) low fat pointer instrumentation. If disabled, the tool will use redzone-only checking. Default: enabled.

  • -Xreads (-Xreads=false): Enables (disables) memory read instrumentation. If disabled, the tool will only instrument memory writes. Note that (1) read instrumentation is expensive, and (2) many exploits (e.g., control-flow-hijacking) require a memory write operation. For this reason, memory reads are not instrumented by default. Default: disabled.

  • -Xsize (-Xsize=false): Enables (disables) size metadata protection. RedFat stores object size metadata which itself may be vulnerable to attack. With size metadata protection, the size metadata is compared against the (immutable) low fat size metadata, which is sufficient to prevent overflows into adjacent objects. Default: enabled.

  • -Xdebug (-Xdebug=false): Enables "debugging" mode that prints detailed information about any memory error that is detected. See Debugging Mode below for more information. Default: disabled.

  • -Xadjust (-Xadjust=false): This experimental mode considers any pointer arithmetic from context instructions in the same basic-block. For example, if:

      add $0x8,%rdi
      mov $0x0,(%rdi,%rsi,8)
    

    Then the base pointer for the low-fat check will be %rdi-0x8 rather than just %rdi (the default). This can improve the accuracy of low-fat checking. However, this mode also assumes the correctness of the basic-block recovery algorithm, so is not enabled by default. This mode is also not currently compatible with -Xdebug or -Xallowlist.

The main optimization options are:

  • -Oglobals (-Oglobals=false): Enables (disables) the elimination of global object memory access instrumentation that cannot reach the heap. Default: enabled.
  • -Ostack (-Ostack=false): Enables (disables) the elimination of stack object memory access instrumentation that cannot reach the heap. This optimization assumes that the stack pointer %rsp value is in the default relocation which is far from the heap. This is generally true for most programs, but the assumption could be violated by programs that allocate and use custom stacks on the heap (e.g., malloc()+sigaltstack()). Default: enabled.
  • -Obatch=N: Group the instrumentation into batches of length N checks, where possible. This instrumentation depends on a static jump target recovery analysis. If the analysis is imperfect, this may result in missed instrumentation. However, the analysis should be accurate for most binaries. Default: 50.
  • -Omerge (-Omerge=false): In a given batch, attempt to merge checks where possible. Default: enabled.
  • -OCFR (-OCFR=false): Enables (disables) Control Flow Recovery (CFR) mode. This makes the rewritten binaries faster, but may introduce rewriting errors. Default: disabled.

The main allow-list options are:

  • -Xallowlist-mode=MODE: Set the allow-list instrumentation mode for advanced instrumentation control. Here, the MODE is represented by a 4-character string. The character index 0..3 determines how each allow-list entry (created by allow-list generation) should be instrumented. The possible index values are:

    • 0: Lowfat-unsafe (false detection observed)
    • 1: Lowfat-safe (no false detection observed)
    • 2: Only non-heap pointers observed
    • 3: Not reached

    The corresponding MODE[index] character determines the instrumentation:

    • L: Redzone+Lowfat instrumentation
    • R: Redzone-only instrumentation
    • -: No instrumentation

    Reasonable values for MODE are:

    • "RLRR": Use Redzone+Lowfat instrumentation only for (observed) lowfat-safe memory access. This is the default MODE.
    • "RL-R": Do not bother instrumenting memory access that was only (observed) using non-heap pointers. This can improve the performance of the instrumented binary, but at the risk of missing some memory errors on unexplored paths.
    • "RLLL": Use Redzone+Lowfat instrumentation on all memory access that was not (observed to be) Lowfat-unsafe. This eliminates the observed false detections, but retains the risk of false detections on unexplored paths.

The LowFat runtime also supports options that can be enabled using environment variables:

  • REDFAT_PROFILE=1: Enable profiling information such as the number of allocations and total library checks. Default: disabled.
  • REDFAT_TEST=N: Enable "test"-mode that randomly (once per N allocations) underallocates by a single byte. If instrumented code accesses the missing byte then a memory error should be detected. A zero value disables test-mode. Default: 0 (disabled).
  • REDFAT_QUARANTINE=N: Delay re-allocation of objects until N bytes have been free'ed. This can help detect reuse-after-free errors by not immediately reallocating objects, at the cost of increased memory overheads. However, this can increase memory overheads. Note that N is a per-region value for each allocation size-class, so the total overhead could be N*M where M is the number of regions (typically ~60). Default: 0.
  • REDFAT_ZERO=1: Enable the zero'ing of objects during deallocation. Provides additional defense against use-after-free errors and a basic defense against unititalized-read errors. However, zero'ing adds additional performance overheads. Default: disabled.
  • REDFAT_CANARY=1: Enables a randomized canary to be placed at the end of all allocated objects. The canary provides additional protection against out-of-bound write errors that may go undetected in uninstrumented code. This consumes an additional 8 bytes per allocation. Note that a canary is always placed at the beginning of all allocated objects since this does not consume additional space. Default: disabled.
  • REDFAT_ASLR=1: Enables Address Space Layout Randomization (ASLR) for heap allocations. Default: enabled.
  • REDFAT_SIGNAL=SIG: If an error occurs, raise signal SIG to terminate the program (or else fall back to abort). Default: SIGABRT.
  • REDFAT_LOG=N: Set N to be the log-level. Default: 2.

Debugging Mode

By default, RedFat can detect if a memory error occurs, but cannot report any information about the memory error, such as the kind of error (overflow, use-after-free), the accessed object, etc. This is by design, since tracking this information would make the instrumentation slower.

For more detailed information about memory errors, RedFat also supports a "debugging" mode that can be enabled via the -Xdebug option:

   $ ./redfat -Xdebug xterm

Unlike the default mode, the debugging mode will print detailed information about any memory error detected. For example:

    REDFAT WARNING: out-of-bounds error detected!
            instruction = movb $0x0, -0x20(%rdx) [0x2d698]
            access.ptr  = 0x3073820560
            access.size = 1
            access.obj  = [-48..+16]
            base.ptr    = 0x3073820580 (+32)
            base.obj    = [+48..+144] (free)

Here:

  • instruction: is the instruction and [address] where the memory error was detected.
  • access.ptr: is the pointer that was accessed by the instruction.
  • access.size: is the size of the access in bytes.
  • access.obj: is the (free?) object that was accessed (relative to access.ptr).
  • base.ptr: is the base pointer with (offset) relative to access.ptr.
  • base.obj: is the (free?) object pointed to by the base pointer (relative to `access
View on GitHub
GitHub Stars111
CategoryContent
Updated1mo ago
Forks11

Languages

C++

Security Score

100/100

Audited on Feb 20, 2026

No findings