Relro
Reading time: 6 minutes
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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Relro
RELRO označava Relocation Read-Only i to je mitigacija koju implementira linker (ld
) koja pretvara podskup ELF-ovih segmenata podataka u samo za čitanje nakon što su sve relokacije primenjene. Cilj je sprečiti napadača da prepisuje unose u GOT (Global Offset Table) ili druge tabele povezane sa relokacijom koje se dereferenciraju tokom izvršavanja programa (npr. __fini_array
).
Moderni linkeri implementiraju RELRO tako što preuređuju GOT (i nekoliko drugih sekcija) tako da se nalaze pre .bss i – što je najvažnije – kreiraju posvećen PT_GNU_RELRO
segment koji se premapira R–X
odmah nakon što dinamički učitač završi sa primenom relokacija. Kao rezultat, tipični preljevi bafera u .bss više ne mogu da dođu do GOT-a i primitivne operacije za proizvoljno pisanje ne mogu se koristiti za prepisivanje pokazivača funkcija koji se nalaze unutar stranice zaštićene RELRO-om.
Postoje dva nivoa zaštite koje linker može da generiše:
Partial RELRO
- Proizvedeno sa flagom
-Wl,-z,relro
(ili samo-z relro
kada se direktno pozivald
). - Samo ne-PLT deo GOT-a (deo koji se koristi za relokacije podataka) se stavlja u segment samo za čitanje. Sekcije koje treba da se modifikuju u vreme izvršavanja – najvažnije .got.plt koja podržava lazy binding – ostaju zapisive.
- Zbog toga, primitivna operacija za proizvoljno pisanje još uvek može preusmeriti tok izvršavanja prepisivanjem PLT unosa (ili izvođenjem ret2dlresolve).
- Uticaj na performanse je zanemarljiv i stoga skoro svaka distribucija već godinama isporučuje pakete sa barem Partial RELRO (to je podrazumevano u GCC/Binutils od 2016).
Full RELRO
- Proizvedeno sa oba flaga
-Wl,-z,relro,-z,now
(poznato i kao-z relro -z now
).-z now
prisiljava dinamički učitač da reši sve simbole unapred (eager binding) tako da .got.plt nikada ne mora ponovo da se piše i može sigurno da se mapira kao samo za čitanje. - Ceo GOT, .got.plt, .fini_array, .init_array, .preinit_array i nekoliko dodatnih internih glibc tabela završavaju unutar segmenta samo za čitanje
PT_GNU_RELRO
. - Dodaje merljiv početni prekorak (sve dinamičke relokacije se obrađuju pri pokretanju) ali nema prekoraka u vreme izvršavanja.
Od 2023. godine nekoliko mainstream distribucija prešlo je na kompajliranje sistemskog alata (i većine paketa) sa Full RELRO podrazumevano – npr. Debian 12 “bookworm” (dpkg-buildflags 13.0.0) i Fedora 35+. Kao pentester, stoga treba da očekujete da se susretnete sa binarnim datotekama gde je svaki GOT unos samo za čitanje.
Kako proveriti RELRO status binarne datoteke
$ 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) analizira ELF
zaglavlja i prikazuje nivo zaštite. Ako ne možete koristiti 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 se binarni program izvršava (npr. set-uid root pomoćnik), još uvek možete pregledati izvršni fajl putem /proc/$PID/exe
:
readelf -l /proc/$(pgrep helper)/exe | grep GNU_RELRO
Omogućavanje RELRO prilikom kompajliranja vlastitog 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
ради за оба GCC/clang (prolazi nakon -Wl,
) i ld direktno. Kada koristite CMake 3.18+ možete zatražiti Full RELRO sa ugrađenim presetom:
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 nivo | Tipična primitivna | Moguće tehnike eksploatacije |
---|---|---|
Nema / Delimična | Arbitrarna pisanja | 1. Prepisivanje .got.plt unosa i preusmeravanje izvršenja. 2. ret2dlresolve – kreirati lažni Elf64_Rela & Elf64_Sym u segmentu koji se može pisati i pozvati _dl_runtime_resolve .3. Prepisivanje pokazivača funkcija u .fini_array / atexit() listi. |
Potpuna | GOT je samo za čitanje | 1. Potražiti druge pokazivače na kod koji se može pisati (C++ vtables, __malloc_hook < glibc 2.34, __free_hook , povratni pozivi u prilagođenim .data sekcijama, JIT stranice).2. Zloupotreba relativnih čitanja primitiva za curenje libc i izvođenje SROP/ROP u libc. 3. Umetanje zlonamerne deljene biblioteke putem DT_RPATH/ LD_PRELOAD (ako je okruženje pod kontrolom napadača) ili ld_audit .4. Eksploatacija format-string ili delimično prepisivanje pokazivača za preusmeravanje toka kontrole bez dodirivanja GOT-a. |
💡 Čak i sa Potpunim RELRO, GOT učitanih deljenih biblioteka (npr. libc sama) je samo Delimični RELRO jer su ti objekti već mapirani kada učitavač primeni relokacije. Ako dobijete arbitrarnu pisanje primitivu koja može ciljati stranice druge deljene biblioteke, još uvek možete preusmeriti izvršenje prepisivanjem libc-ovih GOT unosa ili
__rtld_global
steka, tehnika koja se redovno koristi u modernim CTF izazovima.
Primer zaobilaženja iz stvarnog sveta (2024 CTF – pwn.college “enlightened”)
Izazov je isporučen sa Potpunim RELRO. Eksploit je koristio off-by-one za korupciju veličine heap chunk-a, iscurio libc sa tcache poisoning
, i konačno prepisao __free_hook
(van RELRO segmenta) sa jednim gadgetom za dobijanje izvršenja koda. Nije bilo potrebno pisanje u GOT.
Nedavna istraživanja i ranjivosti (2022-2025)
- glibc 2.40 deprecira
__malloc_hook
/__free_hook
(2025) – Većina modernih heap eksploata koji su zloupotrebljavali ove simbole sada mora preći na alternativne vektore kao što surtld_global._dl_load_jump
ili C++ tabele izuzetaka. Zbog toga što hook-ovi žive van RELRO, njihovo uklanjanje povećava težinu zaobilaženja Potpunog RELRO-a. - Binutils 2.41 “max-page-size” ispravka (2024) – Greška je omogućila poslednjih nekoliko bajtova RELRO segmenta da dele stranicu sa podacima koji se mogu pisati na nekim ARM64 verzijama, ostavljajući mali RELRO razmak koji se mogao pisati nakon
mprotect
. Upstream sada usklađujePT_GNU_RELRO
sa granicama stranica, eliminišući taj ivični slučaj.
Reference
- Dokumentacija za Binutils –
-z relro
,-z now
iPT_GNU_RELRO
- “RELRO – Potpuni, Delimični i Tehnike zaobilaženja” – blog post @ wolfslittlered 2023
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
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.