Concepts
generalMemory protection (NX / DEP / W^X)
Page permissions — read, write, execute — and the W^X rule that no page is both writable and executable. The mitigation that turned simple shellcode injection into ROP.
The CPU's paging unit attaches permission bits to every page of memory:
Read, Write and eXecute. The OS sets these per region, and the
hardware faults on any access that violates them (a SIGSEGV on Linux, an
access-violation on Windows).
The NX bit and W^X
The NX bit (No-eXecute; marketed as DEP, Data Execution Prevention, on Windows) lets a page be readable/writable without being executable. Modern systems enforce W^X — write XOR execute — the policy that no page is both writable and executable at the same time:
| Region | Typical perms | Why |
|---|---|---|
.text (code) | r-x | executable, not writable |
.rodata | r-- | constants, read-only |
.data / .bss | rw- | mutable globals, not executable |
| stack / heap | rw- | data only — NX |
You can read these live from /proc/<pid>/maps (the rwxp column) or with a
debugger's vmmap.
Why this matters for exploitation
Before NX, the classic attack was: overflow a buffer, write shellcode onto the stack, and redirect execution into it. W^X kills that directly — the stack is writable but not executable, so the injected bytes fault the moment the CPU tries to run them.
The response was code reuse: instead of injecting new code, chain together fragments of existing executable code.
- ret2libc — return into an existing library function (e.g.
system). - ROP (Return-Oriented Programming) — chain short "gadgets" ending in
ret, driving the flow entirely through values placed on the stack.
These need no writable+executable page, so they sidestep W^X — which is why NX shifted exploitation from shellcode to ROP rather than ending it.
Reverse-engineering & security notes
- A region that is
rwxis a red flag: JITs (JavaScript, .NET, Lua), packers and self-modifying / unpacking malware allocaterwx(or flip permissions withmprotect/VirtualProtect) so they can write code and then run it. A call tomprotect(..., PROT_EXEC)orVirtualProtect(..., PAGE_EXECUTE_READWRITE)is a strong unpacking/codegen signal. - Combined with ASLR and stack canaries, NX is one leg
of the standard mitigation stack;
checksecreports all of them at once. - Permission faults are how you recognise the bug class: jumping to data →
exec fault; writing to
.text/GOT → write fault (a sign RELRO orr-xis doing its job).
See also: PIE & ASLR · GOT & PLT · The stack · CALL / RET.