TL;DR
PaX protection makes format string exploits much harder but doesn’t completely eliminate the risk, especially with older kernels or misconfigurations. It focuses on preventing arbitrary writes to memory by restricting access and detecting malicious patterns. This guide explains how PaX works against format strings and potential bypass techniques.
Understanding Format String Exploits
A format string exploit occurs when a program uses user-supplied input directly as the format string in functions like printf, scanf, or similar. The attacker controls the format specifiers (e.g., %s, %d, %x) which can be used to read from and write to arbitrary memory locations.
How PaX Protects Against Format Strings
PaX introduces several protections that mitigate format string vulnerabilities:
- Stack Randomization (ASLR): Makes the stack address unpredictable, hindering reliable writes.
- Canaries: Places a known value (‘canary’) on the stack before the return address. A write to overwrite the canary is detected, terminating the program.
- Restricted Pointer Writes: PaX limits where pointers can be written in memory. This makes it difficult to directly overwrite function pointers or other critical data structures needed for code execution.
- Format String Detection (newer kernels): Some newer kernels have built-in detection mechanisms that identify and prevent the use of format string specifiers in user input.
Bypassing PaX – Potential Techniques
While challenging, bypassing PaX is possible under certain conditions. Here’s a breakdown of common approaches:
1. Information Leaks
- Leaking Stack Address: Even with ASLR, you can leak stack addresses using format string specifiers like
%por by repeatedly printing values until you find the stack base. - Example (leaking a stack variable):
printf("%p %p %p...");This will print successive values from the stack, allowing you to identify the address of your input buffer and other relevant variables.
2. Overwriting GOT/PLT Entries (Less Common with PaX)
The Global Offset Table (GOT) contains addresses of dynamically linked functions. If PaX allows it, overwriting an entry in the GOT can redirect function calls to attacker-controlled code.
- Identify a Target Function: Find a function in the GOT that you want to hijack (e.g.,
puts). - Calculate Offset: Determine the offset of the target GOT entry relative to your input buffer.
- Overwrite with New Address: Use format string specifiers like
%nto write a new address into the GOT entry.printf("%p %x %x %x... %n", &target_function_address);
3. Heap Exploitation (If Applicable)
If the vulnerable program uses heap memory extensively, you might be able to exploit heap vulnerabilities in conjunction with a format string vulnerability.
4. Kernel Vulnerabilities (Most Difficult)
Exploiting vulnerabilities directly within the kernel is extremely complex but can bypass PaX protections if successful.
Important Considerations
- Kernel Version: Older kernels are more susceptible to format string exploits due to weaker or missing PaX features.
- Compiler and Libraries: The compiler and libraries used by the program can affect the layout of memory and the effectiveness of PaX protections.
- Address Space Layout Randomization (ASLR): ASLR makes exploitation harder, but leaks can often bypass it.
- NX/DEP: Data Execution Prevention prevents code execution from data sections like the stack or heap. This must be bypassed to execute shellcode.
Mitigation
- Never use user-supplied input directly as a format string: Always use a fixed format string and pass user input as arguments.
printf("User input: %s", user_input); - Use safe functions: Prefer functions like
snprintforfprintf(stdout, "%s", user_input). - Keep your kernel and software up to date: Updates often include security patches that address format string vulnerabilities.

