Full RELRO
- •
What it is
- •
Full RELRO resolves external function addresses at startup and makes the GOT read-only, preventing ordinary GOT-slot overwrites during program execution.
- •
- •
How it works
- •
Partial RELRO protects a relocation region, but typically leaves lazy-binding PLT/GOT slots writable. Do not assume every GOT entry is writable.
- •
Full RELRO forces all symbols to resolve eagerly during startup, before
main()ever runs, then callsmprotectto flip the GOT page's permission from writable to read-only. - •
Partial RELRO → some relocation data protected; lazy PLT slots usually writable Full RELRO → eager binding, then GOT protected read-only
- •
- •
When to use it
- •
checksecshowsFull RELRO→ GOT-overwrite is off the table entirely as an exploitation path; a write primitive needs a different target (stack return address, a function pointer elsewhere,.dataglobals, heap metadata, etc.). - •
With Partial or No RELRO, inspect the relevant slot before considering a Global Offset Table (GOT-PLT) overwrite.
- •
- •
Examples
- •
A write to a protected
putsGOT slot faults under Full RELRO. A writable function-pointer slot elsewhere would be a separate target.
- •
- •
pwntools
- •
elf = ELF('./vuln') print(elf.relro) # None, 'Partial', or 'Full'
- •
- •
Debugging
- •
checksec vmmap # confirm GOT page shows r-- (not rw-) once past startup, under Full RELRO
- •
- •
- •
Cards
- •
What's the practical difference between Partial and Full RELRO?
- •
Partial RELRO protects some relocation data but commonly leaves lazy-binding slots writable. Full RELRO adds eager binding and protects the GOT.
- •
- •
Why does eager resolution have to happen before the GOT can be made read-only?
- •
Every entry needs its real address filled in during startup, since no further writes (including legitimate resolver writes) are possible once the page permission flips to read-only.
- •
- •