Relro

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Relro

RELRO stands for Relocation Read-Only and it is a mitigation implemented by the linker (ld) that turns a subset of the ELF’s data segments read-only after all relocations have been applied. The goal is to stop an attacker from overwriting entries in the GOT (Global Offset Table) or other relocation-related tables that are dereferenced during program execution (e.g. __fini_array).

Modern linkers implement RELRO by re–ordering the GOT (and a few other sections) so they live before the .bss and – most importantly – by creating a dedicated PT_GNU_RELRO segment that is remapped R–X right after the dynamic loader finishes applying relocations. Consequently, typical buffer overflows in the .bss can no longer reach the GOT and arbitrary‐write primitives cannot be used to overwrite function pointers that sit inside a RELRO-protected page.

There are two levels of protection that the linker can emit:

Partial RELRO

  • Produced with the flag -Wl,-z,relro (or just -z relro when invoking ld directly).
  • Only the non-PLT part of the GOT (the part used for data relocations) is put into the read-only segment. Sections that need to be modified at run-time – most importantly .got.plt which supports lazy binding – remain writable.
  • Because of that, an arbitrary write primitive can still redirect execution flow by overwriting a PLT entry (or by performing ret2dlresolve).
  • The performance impact is negligible and therefore almost every distribution has been shipping packages with at least Partial RELRO for years (it is the GCC/Binutils default as of 2016).

Full RELRO

  • Produced with both flags -Wl,-z,relro,-z,now (a.k.a. -z relro -z now). -z now forces the dynamic loader to resolve all symbols up-front (eager binding) so that .got.plt never needs to be written again and can safely be mapped read-only.
  • The entire GOT, .got.plt, .fini_array, .init_array, .preinit_array and a few additional internal glibc tables end up inside a read-only PT_GNU_RELRO segment.
  • Adds measurable start-up overhead (all dynamic relocations are processed at launch) but no run-time overhead.

Since 2023 several mainstream distributions have switched to compiling the system tool-chain (and most packages) with Full RELRO by default – e.g. Debian 12 “bookworm” (dpkg-buildflags 13.0.0) and Fedora 35+. As a pentester you should therefore expect to encounter binaries where every GOT entry is read-only.


Kako proveriti RELRO status binarnog fajla

$ checksec --file ./vuln
[*] '/tmp/vuln'
Arch:     amd64-64-little
RELRO:    Full
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

checksec (deo pwntools i mnogih distribucija) parsira ELF zaglavlja i prikazuje nivo zaštite. Ako ne možete da koristite checksec, oslonite se na readelf:

# Partial RELRO → PT_GNU_RELRO is present but BIND_NOW is *absent*
$ readelf -l ./vuln | grep -E "GNU_RELRO|BIND_NOW"
GNU_RELRO      0x0000000000600e20 0x0000000000600e20
# Full RELRO → PT_GNU_RELRO *and* the DF_BIND_NOW flag
$ readelf -d ./vuln | grep BIND_NOW
0x0000000000000010 (FLAGS)              FLAGS: BIND_NOW

Ako je binary pokrenut (npr. set-uid root helper), i dalje možete da pregledate executable putem /proc/$PID/exe:

readelf -l /proc/$(pgrep helper)/exe | grep GNU_RELRO

Omogućavanje RELRO prilikom kompajliranja sopstvenog koda

# GCC example – create a PIE with Full RELRO and other common hardenings
$ gcc -fPIE -pie -z relro -z now -Wl,--as-needed -D_FORTIFY_SOURCE=2 main.c -o secure

-z relro -z now radi za oba GCC/clang (prosleđeno nakon -Wl,) i ld direktno. Kada koristite CMake 3.18+ možete zatražiti Full RELRO pomoću ugrađenog preseta:

set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) # LTO
set(CMAKE_ENABLE_EXPORTS OFF)
set(CMAKE_BUILD_RPATH_USE_ORIGIN ON)
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,relro,-z,now")

Tehnike zaobilaženja

RELRO levelTypical primitivePossible exploitation techniques
None / PartialArbitrary write1. Overwrite .got.plt entry and pivot execution.
2. ret2dlresolve – craft fake Elf64_Rela & Elf64_Sym in a writable segment and call _dl_runtime_resolve.
3. Overwrite function pointers in .fini_array / atexit() list.
FullGOT is read-only1. Look for other writable code pointers (C++ vtables, __malloc_hook < glibc 2.34, __free_hook, callbacks in custom .data sections, JIT pages).
2. Abuse relative read primitives to leak libc and perform SROP/ROP into libc.
3. Inject a rogue shared object via DT_RPATH/LD_PRELOAD (if environment is attacker-controlled) or ld_audit.
4. Exploit format-string or partial pointer overwrite to divert control-flow without touching the GOT.

💡 Čak i sa Full RELRO, GOT of loaded shared libraries (e.g. libc itself) je only Partial RELRO zato što su ti objekti već mapirani kada loader primeni relokacije. Ako dobijete arbitrary write primitiv koji može da cilja stranice drugog shared objekta, i dalje možete preusmeriti izvršavanje tako što ćete prepisati libc-ove GOT unose ili __rtld_global stack, tehnika koja se često iskorišćava u modernim CTF izazovima.

Primer iz stvarnog sveta zaobilaženja (CTF 2024 – pwn.college “enlightened”)

Izazov je isporučen sa Full RELRO. Exploit je iskoristio off-by-one da korumpira veličinu heap chunk-a, leak-ovao libc pomoću tcache poisoning, i na kraju prepisao __free_hook (izvan RELRO segmenta) jednim one-gadget-om da bi dobio izvršavanje koda. Nije bilo potrebe za pisanjem u GOT.


Nedavna istraživanja i ranjivosti (2022-2025)

  • glibc hook removal (2.34 → present) – malloc/free hooks su izvučeni iz glavnog libc-a u opcionu libc_malloc_debug.so, eliminišući uobičajen Full‑RELRO bypass primitiv; modern exploits moraju ciljati druge zapisive pokazivače.
  • GNU ld RELRO page‑alignment fix (binutils 2.39+/2.41) – linker bug 30612 je izazvao da poslednji bajtovi PT_GNU_RELRO dele zapisivu stranicu na sistemima sa 64 KiB stranicama; aktuelni binutils poravnava RELRO na max-page-size, zatvarajući taj “RELRO gap”.

References

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks