> For the complete documentation index, see [llms.txt](https://alham-rizvi.gitbook.io/alhamrizvi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://alham-rizvi.gitbook.io/alhamrizvi/binary-exp/04.-stack-overflow/05.-stack-overflow-protections.md).

# Stack Overflow Protections

## Table of Contents

1. [What Is a Stack Overflow?](#what-is-a-stack-overflow)
2. [Protection 1 — Stack Canaries](#1-stack-canaries)
3. [Protection 2 — NX / DEP (No-Execute)](#2-nx--dep-no-execute)
4. [Protection 3 — ASLR (Address Space Layout Randomization)](#3-aslr)
5. [Protection 4 — PIE (Position Independent Executable)](#4-pie)
6. [Protection 5 — Shadow Stack / CET](#5-shadow-stack--cet)
7. [Protection 6 — SafeStack / ShadowCallStack](#6-safestack--shadowcallstack)
8. [Checking Protections on a Binary](#checking-protections-on-a-binary)
9. [Protection Interaction Matrix](#protection-interaction-matrix)
10. [Scripts & Tools](#scripts--tools)

## What Is a Stack Overflow?

A **stack-based buffer overflow** occurs when data written to a stack buffer exceeds its allocated size, overwriting adjacent memory — most critically the **saved return address** and **saved base pointer (RBP/EBP)**.

```
HIGH ADDRESS
┌──────────────────────┐
│   argv, envp         │
├──────────────────────┤
│   Stack frame N      │
│   [return addr]  ◄───── attacker overwrites this
│   [saved RBP]        │
│   [local vars]       │
│   [BUFFER]       ◄───── overflow starts here
├──────────────────────┤
│   Stack frame N-1    │
└──────────────────────┘
LOW ADDRESS
```

**Classic exploit flow:**

1. Overflow `BUFFER` past its bounds
2. Overwrite `return address` with attacker-controlled value
3. On `ret`, CPU jumps to attacker's address
4. Execute shellcode / ROP chain

## 1. Stack Canaries

### What It Is

A **random secret value** placed between local variables and the saved return address at function entry. Checked before `ret`; if modified → program aborts.

```
┌──────────────────┐
│  return address  │
│  saved RBP       │
│  CANARY VALUE    │  ◄── if overwritten → __stack_chk_fail()
│  local variables │
│  BUFFER          │
└──────────────────┘
```

### Types

| Type                  | Description                                     |
| --------------------- | ----------------------------------------------- |
| **Terminator canary** | `\x00\xff\x0a\x0d` — stops string functions     |
| **Random canary**     | Randomized per-process at startup (most common) |
| **Random XOR canary** | Random XOR'd with control data                  |

### How It's Implemented

```c
// Compiler inserts this at function prologue (simplified):
// mov rax, [fs:0x28]        ; load canary from TLS
// mov [rbp-0x8], rax        ; store on stack

// At epilogue before ret:
// mov rax, [rbp-0x8]        ; read canary back
// xor rax, [fs:0x28]        ; compare with original
// jnz __stack_chk_fail      ; abort if mismatch
```

### Compile-Time Controls

```bash
# Enable (default with -O2+)
gcc -fstack-protector-all target.c -o target

# Strong protection (GCC 4.9+) — recommended
gcc -fstack-protector-strong target.c -o target

# Disable (for CTF/research only)
gcc -fno-stack-protector target.c -o target
```

### Bypass Techniques

| Technique                            | Conditions Required                                                  |
| ------------------------------------ | -------------------------------------------------------------------- |
| **Leak canary via format string**    | Format string bug exists before overflow                             |
| **Brute-force (32-bit)**             | 1-in-256 chance per byte on forking servers                          |
| **Overwrite canary + fix it**        | Know the canary value (via leak)                                     |
| **Jump over canary**                 | Overwrite only data after canary (e.g., function pointers in struct) |
| **Heap overflow → indirect control** | Avoid the stack entirely                                             |

```python
# Example: Brute force null byte (canary always ends in \x00 on Linux)
# canary = \x00 ?? ?? ??  (LSB is always null)
# Leak remaining 3 bytes one at a time on a forking server
canary = b'\x00'
for i in range(3):
    for byte in range(256):
        payload = b'A' * offset + canary + bytes([byte])
        # send and check if process continues (didn't crash)
        if process_survived(payload):
            canary += bytes([byte])
            break
```

## 2. NX / DEP (No-Execute)

### What It Is

**NX (No-eXecute)** / **DEP (Data Execution Prevention)** marks memory regions as either writable OR executable — never both. The stack is writable but **not executable**.

| Region           | Read | Write | Execute |
| ---------------- | ---- | ----- | ------- |
| `.text` (code)   | ✅    | ❌     | ✅       |
| `.data` / `.bss` | ✅    | ✅     | ❌       |
| Stack            | ✅    | ✅     | ❌       |
| Heap             | ✅    | ✅     | ❌       |

### Hardware Support

* **Intel/AMD**: NX bit in page table entries (bit 63 of PTE in 64-bit mode)
* **ARM**: XN (Execute Never) bit
* **Requires**: PAE on 32-bit x86, enabled by default on all modern 64-bit OS

### Compile-Time Controls

```bash
# Check if NX is enabled
readelf -l binary | grep GNU_STACK
# "RW " = NX enabled (no execute bit)
# "RWE" = NX disabled (stack is executable)

# Disable NX (for research)
gcc -z execstack target.c -o target

# Explicitly enable (default)
gcc -z noexecstack target.c -o target
```

### Bypass Techniques

**NX does NOT prevent code reuse attacks** — it only blocks injected shellcode.

| Bypass                                | Description                                                 |
| ------------------------------------- | ----------------------------------------------------------- |
| **ret2libc**                          | Return to existing `system()` function in libc              |
| **ROP (Return-Oriented Programming)** | Chain existing code "gadgets" ending in `ret`               |
| **ret2plt**                           | Return to PLT stub to call libc functions                   |
| **mprotect / mmap abuse**             | Use ROP to mark a region executable, then jump to shellcode |

```python
# ret2libc example (no ASLR)
from pwn import *

elf = ELF('./target')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

system_addr = libc.symbols['system']
bin_sh_addr = next(libc.search(b'/bin/sh'))
pop_rdi     = 0x401234  # gadget: pop rdi ; ret

payload  = b'A' * 72           # padding to return address
payload += p64(pop_rdi)        # set RDI = first arg
payload += p64(bin_sh_addr)    # arg = "/bin/sh"
payload += p64(system_addr)    # call system("/bin/sh")
```

## 3. ASLR

### What It Is

**Address Space Layout Randomization** randomizes the base addresses of the stack, heap, and shared libraries on each execution. Even if an attacker knows the offset of `system()` from libc's base, they don't know where libc is loaded.

### Entropy Levels

| Region              | 64-bit entropy | 32-bit entropy |
| ------------------- | -------------- | -------------- |
| Stack               | \~20 bits      | \~8 bits       |
| Heap                | \~13 bits      | \~8 bits       |
| Libraries           | \~28 bits      | \~8 bits       |
| Executable (no PIE) | **0 bits**     | **0 bits**     |

```bash
# Check ASLR level on Linux
cat /proc/sys/kernel/randomize_va_space
# 0 = disabled
# 1 = randomize stack, VDSO, shared libraries
# 2 = also randomize heap (default)

# Disable ASLR globally (root, for testing)
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

# Disable for one run
setarch $(uname -m) -R ./target
```

### Bypass Techniques

| Technique                         | Requirements                                                          |
| --------------------------------- | --------------------------------------------------------------------- |
| **Leak address at runtime**       | Info leak bug (format string, out-of-bounds read)                     |
| **Brute force (32-bit)**          | Only \~256 positions for stack on 32-bit                              |
| **Partial overwrite**             | Overwrite only low bytes of address (preserves randomized high bytes) |
| **ret2plt (no libc leak needed)** | PLT stubs have fixed addresses when no PIE                            |
| **Heap spray**                    | Fill large memory region; increase hit probability                    |
| **JIT spraying**                  | Spray JIT-compiled code (browser exploits)                            |

## 4. PIE

### What It Is

**Position Independent Executable** — when compiled with PIE, even the `.text` (code) section of the binary itself is loaded at a random base address (combined with ASLR). Without PIE, `.text` is always at a fixed address.

```bash
# Check if binary has PIE
file binary         # "pie executable" vs "executable"
checksec binary     # shows PIE: enabled/disabled

# Compile without PIE
gcc -no-pie -fno-pie target.c -o target

# Compile with PIE (default on most modern distros)
gcc -pie -fPIE target.c -o target
```

### PIE + ASLR

When both are active:

* **Every** address (stack, heap, libc, binary) is randomized
* Hardcoded gadget addresses are useless
* **Must leak an address** before building ROP chain

```python
# Typical exploit flow with PIE + ASLR:
# 1. Trigger info leak → get one address in binary or libc
# 2. Calculate base = leaked_addr - known_offset
# 3. Add base to all gadget/symbol offsets
# 4. Send ROP chain with correct addresses

leaked_puts = u64(io.recv(6).ljust(8, b'\x00'))
libc_base   = leaked_puts - libc.symbols['puts']
system      = libc_base + libc.symbols['system']
bin_sh      = libc_base + next(libc.search(b'/bin/sh'))
```

## 5. Shadow Stack / CET

### What It Is

**Intel CET (Control-flow Enforcement Technology)** — hardware-enforced shadow stack. A separate, non-writable copy of return addresses is maintained. On `ret`, the CPU compares the stack return address with the shadow stack copy.

```
Normal Stack        Shadow Stack (read-only)
┌─────────────┐     ┌─────────────┐
│ return addr │     │ return addr │  ← CPU compares these on ret
│ saved RBP   │     │             │
│ locals      │     │             │
└─────────────┘     └─────────────┘
```

Also includes **IBT (Indirect Branch Tracking)** — every indirect `jmp`/`call` target must start with `ENDBR64` instruction.

### Status

* Available on Intel Tiger Lake (11th gen+), AMD Zen 3+
* Linux kernel 6.6+ supports CET shadow stack for user space
* Windows 10 21H1+ enables CET for some system processes

### Bypasses (research-level)

* **Type confusion / virtual dispatch abuse** with IBT
* **JOP (Jump-Oriented Programming)** using ENDBR64 gadgets
* Heap-based control flow corruption (doesn't touch return addresses)

## 6. SafeStack / ShadowCallStack

### SafeStack (Clang/LLVM)

Splits the stack into two:

* **Safe stack**: contains return addresses (in random location)
* **Unsafe stack**: buffers that might overflow (accessible normally)

```bash
# Compile with SafeStack
clang -fsanitize=safe-stack target.c -o target
```

### ShadowCallStack (Android / AArch64)

Hardware register `x18` holds a pointer to a shadow return address stack. Used widely on Android.

```bash
# Compile with ShadowCallStack (AArch64 only)
clang -fsanitize=shadow-call-stack target.c -o target
```

## Checking Protections on a Binary

### checksec (most common)

```bash
pip install checksec.py
checksec target

# Or with pwntools
python3 -c "from pwn import *; e=ELF('./target'); print(e.checksec())"
```

**Output example:**

```
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
```

### Manual checks

```bash
# NX
readelf -l target | grep GNU_STACK

# Canary
strings target | grep stack_chk
objdump -d target | grep __stack_chk

# PIE
file target
readelf -h target | grep Type   # ET_DYN = PIE, ET_EXEC = no PIE

# RELRO
readelf -l target | grep RELRO
```

### GDB with PEDA / GEF / pwndbg

```bash
gdb ./target
# In GDB:
checksec          # (pwndbg/GEF command)
vmmap             # view memory regions + permissions
```

## Protection Interaction Matrix

| Attack →                     | Shellcode | ret2libc         | ROP              |
| ---------------------------- | --------- | ---------------- | ---------------- |
| **Canary only**              | ❌ Blocked | ❌ Blocked        | ❌ Blocked        |
| **NX only**                  | ❌ Blocked | ✅ Works          | ✅ Works          |
| **ASLR only**                | ✅ Works\* | ⚠️ Needs leak    | ⚠️ Needs leak    |
| **NX + ASLR**                | ❌ Blocked | ⚠️ Needs leak    | ⚠️ Needs leak    |
| **NX + ASLR + PIE**          | ❌ Blocked | ⚠️ Needs leak    | ⚠️ Needs leak    |
| **NX + ASLR + PIE + Canary** | ❌ Blocked | ⚠️ Needs 2 leaks | ⚠️ Needs 2 leaks |
| **Full CET**                 | ❌ Blocked | ❌ Blocked        | ❌ Blocked\*      |

\*CET with IBT limits ROP gadgets to those starting with ENDBR64

## Scripts & Tools

### Python helper: binary protection checker

```python
#!/usr/bin/env python3
"""Quick binary protection summary using pwntools."""
from pwn import *
import sys

def check_binary(path):
    e = ELF(path, checksec=False)
    print(f"\n{'='*50}")
    print(f"  Binary: {path}")
    print(f"{'='*50}")
    print(f"  Arch   : {e.arch}-{e.bits}")
    print(f"  Canary : {'✅ YES' if e.canary else '❌ NO'}")
    print(f"  NX     : {'✅ YES' if e.nx else '❌ NO'}")
    print(f"  PIE    : {'✅ YES' if e.pie else '❌ NO'}")
    print(f"  RELRO  : {e.relro}")
    print(f"  Entry  : {hex(e.entry)}")
    print(f"  libc   : {e.libc.path if e.libc else 'N/A'}")
    print()

if __name__ == '__main__':
    for path in sys.argv[1:]:
        check_binary(path)
```

### Bash: disable all protections for lab setup

```bash
#!/bin/bash
# FOR RESEARCH/CTF ONLY - disables all stack protections

TARGET=$1
OUTPUT="${1}_vulnerable"

gcc \
    -fno-stack-protector \
    -z execstack \
    -no-pie \
    -fno-pie \
    -D_FORTIFY_SOURCE=0 \
    -O0 \
    "$TARGET.c" \
    -o "$OUTPUT"

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

echo "[+] Built $OUTPUT with all protections disabled"
echo "[+] ASLR disabled system-wide"
```

### pwntools skeleton with protection-aware setup

```python
#!/usr/bin/env python3
from pwn import *

binary = './target'
elf    = ELF(binary)
libc   = elf.libc

context.binary = elf
context.log_level = 'info'

def start():
    if args.REMOTE:
        return remote('target.server', 1337)
    return process(binary)

io = start()

# Populate GOT if no PIE (addresses are fixed)
if not elf.pie:
    log.info(f"puts@PLT  = {hex(elf.plt['puts'])}")
    log.info(f"puts@GOT  = {hex(elf.got['puts'])}")

# Gadget hunting
rop = ROP(elf)
log.info(f"pop rdi   = {hex(rop.find_gadget(['pop rdi', 'ret'])[0])}")

io.interactive()
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://alham-rizvi.gitbook.io/alhamrizvi/binary-exp/04.-stack-overflow/05.-stack-overflow-protections.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
