Full Report
When referencing a null pointer in C, we assume this is invalid. What if this could point to valid memory in some conditions? In this blog post, they discuss how to do this on Linux. This article stems from an interview question: "What happens when the following C or C++ code executes: *(int*)(rand_int()) = 0x41424344; In reality this is undefined behavior. This will change depending on the CPU architecture, privilege level, or compiler version. This will succeed if the address is within the process-mapped virtual address space with write permissions. If the address is unmapped or lacks write permissions, the process will crash. Practically, this is more nauced, though. The invalid memory access will be intercepted by the CPU, which triggers an exception. The Linux kernel then sends a SIGSEGV signal to the process. To me, this is what makes it a great interview question: it allows you to dig into the interviewees' knowledge of the system without making them feel bad. Another edge case is that if the memory is barely in front of the stack address location, then it will attempt to expand the stack. Those CTF players definitely know their esoteric edge cases! What happens if the address is at 0x0? The Linux kernel configurable vm.mmap_min_addr is the minimum virtual address that a call to mmap can include. By default, it's set to 0x10000, but the root user can modify this and bypass this restriction altogether. The reason for this value and not 0x1 is that we want to protect against pointer dereferences with slight index offsets. This configuration was added in order to prevent null pointer dereferences in the Linux kernel leading to vulnerabilities with horrible impact. The idea would be to allocate data at address 0x0 then use a null pointer dereference to access this memory from the kernel to hijack the kernel. According to the author, this is a realic of the past though: SMAP and SMEP prevent this type of exploitation now-a-days. Overall, an interesting blog post! Good read with some fun edge cases.
Analysis Summary
# Tool/Technique: NULL Pointer Mapping & Exploitation (Linux)
## Overview
This technique involves mapping memory at the NULL address (`0x0`) on Linux systems. While modern operating systems typically treat NULL pointer dereferences as invalid, resulting in a segmentation fault (`SIGSEGV`), architectural or configuration-level changes can allow this address to point to valid, writable memory. Historically, this was a critical primitive for exploiting kernel-space NULL pointer dereference vulnerabilities to achieve local privilege escalation.
## Technical Details
- **Type:** Technique
- **Platform:** Linux (x86-64, others)
- **Capabilities:** Bypassing memory protection, Kernel exploitation, Local Privilege Escalation (LPE).
- **First Seen:** Historically significant across the 2000s; mitigated in modern kernels around 2007-2009 via `vm.mmap_min_addr`.
## MITRE ATT&CK Mapping
- **TA0004 - Privilege Escalation**
- **T1068 - Exploitation for Privilege Escalation**
- **TA0001 - Initial Access**
- **T1203 - Exploitation for Client Execution** (Indirectly, if used via a triggered bug)
## Functionality
### Core Capabilities
- **Direct Memory Mapping at 0x0:** Utilizing the `mmap()` system call with the `MAP_FIXED` flag to request that memory be allocated specifically at the zero address.
- **Kernel-to-User Transition:** If a kernel bug (NULL pointer dereference) occurs, the kernel attempts to access address `0x0`. If the attacker has mapped this in user space, the kernel may execute code or read data placed there by the attacker.
- **Stack Expansion:** Exploiting the kernel's behavior where access to memory "just below" the stack pointer triggers an automatic expansion of the stack mapping rather than a crash.
### Advanced Features
- **Bypassing `vm.mmap_min_addr`:** Requires root privileges or specific capabilities (CAP_SYS_RAWIO) to reset the threshold to `0` via `sysctl -w vm.mmap_min_addr=0`.
- **Offset Redirection:** Mapping a range of memory (e.g., up to `0x10000`) to account for structure offsets (e.g., `ptr->callback()`) rather than just a pure zero address.
## Indicators of Compromise
- **File Names:** `/proc/sys/vm/mmap_min_addr` (accessed for modification).
- **Behavioral Indicators:**
- Unexpected `mmap` calls targeting the `0x0` address.
- System configuration changes to `vm.mmap_min_addr` via `sysctl`.
- User-space processes attempting to trigger known kernel-mode NULL dereference bugs.
## Associated Threat Actors
- Historically used by various exploit developers and security researchers (e.g., Brad Spengler/Grsecurity researchers).
- Used in historical local privilege escalation (LPE) exploits targeting Linux kernel versions prior to the widespread adoption of modern mitigations.
## Detection Methods
- **Behavioral Detection:** Monitor for modifications to the `sysctl` parameter `vm.mmap_min_addr`. Modern EDR/SIEM should flag any attempt to set this value below the default (typically `65536`).
- **Auditd:** Monitor for `mmap` system calls with an `addr` argument of `0` combined with `MAP_FIXED`.
- **System Logs:** Look for "Kernel NULL pointer dereference" errors in `dmesg` or `/var/log/kern.log`.
## Mitigation Strategies
- **Kernel Hardening:** Keep `vm.mmap_min_addr` set to at least `4096` or the standard `65536` to prevent user-space mapping of low memory.
- **Hardware Mitigations:**
- **SMEP (Supervisor Mode Execution Prevention):** Prevents the kernel from executing code in user-space memory.
- **SMAP (Supervisor Mode Access Prevention):** Prevents the kernel from unintended data access to user-space memory.
- **Compiler Options:** Use `-fno-delete-null-pointer-checks` to prevent compilers from optimizing away NULL checks in the code.
## Related Tools/Techniques
- **Pwndbg/GDB:** Used for manual memory inspection and patching segments during vulnerability research.
- **KASLR (Kernel Address Space Layout Randomization):** A related defense that complicates redirecting kernel execution.
- **JVM NullPointerException Mechanism:** Uses similar OS-level signal handling to catch invalid accesses and convert them into managed exceptions.