Skip to main content

Heap Hardening Measures

Glibc provides several “hardening” features designed to make heap exploitation more difficult. Understanding these measures is crucial for both defensive security and for testing whether exploitation techniques work in hardened environments.
Hardening measures add runtime checks and modify heap behavior to detect or prevent exploitation attempts. While they raise the bar for exploitation, many are not foolproof defenses.

Environment Variables

Glibc respects several environment variables that enable heap debugging and hardening features.

MALLOC_CHECK_

Enable consistency checks

MALLOC_PERTURB_

Perturb allocated memory

MALLOC_MMAP_THRESHOLD_

Force mmap allocation

MALLOC_CHECK_

Overview

MALLOC_CHECK_ enables lightweight heap consistency checking. When set, glibc performs additional validation on heap operations.

Values

  • MALLOC_CHECK_=0 - Disabled (default)
  • MALLOC_CHECK_=1 - Print error message to stderr, continue execution
  • MALLOC_CHECK_=2 - Abort immediately on heap corruption
  • MALLOC_CHECK_=3 - Print error and abort (most verbose)

Usage

What It Detects

  • Double free - Freeing already-freed pointers
  • Invalid free - Freeing non-heap pointers
  • Heap corruption - Some metadata corruption
  • Use-after-free - Limited detection
Without MALLOC_CHECK_:
With MALLOC_CHECK_:

Testing how2heap Techniques

Many how2heap techniques will be detected by MALLOC_CHECK_:
MALLOC_CHECK_ adds overhead and is meant for debugging, not production use. Some sophisticated exploits can bypass these checks.

Limitations

  • Performance overhead - Slower execution
  • Not comprehensive - Doesn’t catch all corruption
  • Bypassable - Careful exploits can avoid detection
  • Debug only - Not suitable for production

MALLOC_PERTURB_

Overview

MALLOC_PERTURB_ causes malloc to initialize allocated memory and freed memory with specific byte patterns. This helps detect use-after-free and uninitialized memory bugs.

Values

  • MALLOC_PERTURB_=0 - Disabled (default)
  • MALLOC_PERTURB_=<N> - Fill with byte value N (1-255)
Common values:
  • MALLOC_PERTURB_=1 - Fill with 0x01
  • MALLOC_PERTURB_=255 - Fill with 0xFF
  • MALLOC_PERTURB_=170 - Fill with 0xAA (0b10101010)

Behavior

On allocation:
  • New allocations filled with ~N (bitwise NOT of N)
On free:
  • Freed memory filled with N

Usage

Without MALLOC_PERTURB_:
With MALLOC_PERTURB_:

Impact on Exploitation

Techniques affected:
  • Use-after-free - Freed objects contain predictable pattern instead of useful data
  • Heap spraying - Allocated memory no longer contains zeros
  • Information leaks - Uninitialized memory filled with pattern
  • Partial overwrites - Known values make detection easier

Testing with how2heap

Many heap exploitation techniques still work with MALLOC_PERTURB_ because they manipulate metadata rather than data contents.

Best Practices

For development:
For testing:

MALLOC_MMAP_THRESHOLD_

Overview

MALLOC_MMAP_THRESHOLD_ controls the size threshold above which malloc uses mmap() instead of heap allocation.

Default Behavior

  • Default threshold: 128 KB (131072 bytes)
  • Allocations >= threshold use mmap()
  • Allocations < threshold use heap (sbrk/brk)

Values

  • MALLOC_MMAP_THRESHOLD_=<bytes> - Set custom threshold
  • MALLOC_MMAP_THRESHOLD_=0 - Always use heap (never mmap)
  • MALLOC_MMAP_THRESHOLD_=1 - Almost always use mmap

Usage

Impact on Exploitation

When forcing mmap (threshold=1):
  • No heap chunks - Traditional heap techniques don’t apply
  • Different layout - Memory addresses non-contiguous
  • Different metadata - mmap chunks have different structure
  • Isolated allocations - Can’t overflow between chunks
When disabling mmap (threshold=0):
  • All heap allocated - Large allocations use heap
  • Heap exhaustion possible - Large allocations can exhaust heap
  • Different exploitation surface - Different techniques applicable

Testing with how2heap

Some how2heap examples like mmap_overlapping_chunks specifically target mmap’d allocations.

Relationship to Other Settings

Often combined with other malloc tuning:

Runtime Functions

Glibc provides programmatic APIs for heap debugging and hardening.

mcheck()

Enable heap consistency checks

mallopt()

Configure malloc behavior

mtrace()

Trace memory operations

mcheck()

Overview

mcheck() enables heap consistency checking similar to MALLOC_CHECK_, but controlled programmatically. Documentation: http://www.gnu.org/software/libc/manual/html_node/Heap-Consistency-Checking.html

Function Signature

Usage

Basic usage:
Custom abort handler:

Compilation

mprobe() - Manual Checking

Output:

Limitations

  • Must enable early - Before first malloc
  • Performance overhead - Adds checks to every operation
  • Not comprehensive - Won’t catch all corruption
  • Incompatible with custom allocators - Only works with glibc malloc

mallopt()

Overview

mallopt() allows fine-grained control over malloc behavior and parameters. Documentation: http://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html

Function Signature

Key Parameters

M_MMAP_THRESHOLD
M_MMAP_MAX
M_TRIM_THRESHOLD
M_TOP_PAD
M_ARENA_MAX / M_ARENA_TEST

Complete Example

Testing Techniques with mallopt()

mallopt() provides more granular control than environment variables but requires source code modification.

mtrace()

Overview

mtrace() enables memory allocation tracing, logging all malloc/free operations to a file for analysis. Man page: http://manpages.ubuntu.com/mtrace

Function Signature

Usage

Program code:
Compilation:
Running with trace:

Trace Output

Raw trace.log:
After mtrace analysis:

Analyzing how2heap Techniques

Run and analyze:

Advantages

  • Complete trace - Records all allocations/frees
  • Post-mortem analysis - Analyze after execution
  • Leak detection - Identifies memory leaks
  • Debugging aid - Understand allocation patterns

Limitations

  • Performance impact - Significant overhead
  • Large output - Trace files can be huge
  • Requires instrumentation - Must call mtrace() in code

Additional Tracing Tools

malloc_stats()

Man page: http://manpages.ubuntu.com/malloc_stats
Usage:
Output:

malloc_info()

Man page: http://manpages.ubuntu.com/malloc_info
Usage:
Output: XML format with detailed heap information

memusage

Man page: http://manpages.ubuntu.com/memusage
memusage is useful for understanding overall memory usage patterns and peak consumption.

Testing Techniques Against Hardening

Systematic Testing Approach

1. Baseline Test

2. Environment Variable Testing

3. Programmatic Testing

Modify technique source to include:

4. Results Analysis

Automated Testing Script

Usage:

Understanding Results

Reason: Technique manipulates metadata in a way that violates consistency checks.Options:
  1. Refine technique to maintain consistency
  2. Find alternative primitive that doesn’t trigger checks
  3. Exploit before checks are enabled
  4. Disable checks (if you control environment)
Reason: Technique exploits logic flaws rather than memory corruption, or corruption is subtle enough to bypass checks.Implication: Technique is more robust and likely to work in real-world scenarios.
Reason: Technique relies on heap allocation but target is mmap’d.Solution: Adapt technique for mmap allocations (see mmap_overlapping_chunks).

Defensive Recommendations

For Development

For Production

Production hardening should use compiler and kernel features rather than malloc debugging features due to performance implications.
Better alternatives:
  • Compiler: -D_FORTIFY_SOURCE=2, stack canaries, PIE
  • Kernel: ASLR, DEP/NX
  • Modern allocators: tcmalloc, jemalloc (with hardening enabled)
  • Sanitizers (development only): AddressSanitizer, MemorySanitizer

Testing vs Production

Next Steps

Techniques

Test how2heap techniques against hardening

Debugging Tools

Use GDB to analyze hardening detection