Relro

Reading time: 7 minutes

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Relro

RELRO inamaanisha Relocation Read-Only na ni hatua ya kupunguza hatari iliyotekelezwa na linker (ld) ambayo inafanya sehemu fulani za data za ELF kuwa read-only baada ya mabadiliko yote kutumika. Lengo ni kuzuia mshambuliaji kuandika upya entries katika GOT (Global Offset Table) au meza nyingine zinazohusiana na mabadiliko ambazo zinarejelea wakati wa utekelezaji wa programu (mfano __fini_array).

Linker za kisasa zinafanya RELRO kwa ku–panga upya GOT (na sehemu chache nyingine) ili ziwe kabla ya .bss na – muhimu zaidi – kwa kuunda sehemu maalum ya PT_GNU_RELRO ambayo inarudiwa R–X mara tu loader ya dynamic inapoisha kutekeleza mabadiliko. Kwa hivyo, overflow za kawaida za buffer katika .bss haziwezi tena kufikia GOT na primitives za kuandika zisizo na mipaka cannot be used to overwrite function pointers ambazo ziko ndani ya ukurasa uliohifadhiwa na RELRO.

Kuna viwango viwili vya ulinzi ambavyo linker inaweza kutoa:

Partial RELRO

  • Inazalishwa kwa bendera -Wl,-z,relro (au tu -z relro unapoitisha ld moja kwa moja).
  • Sehemu tu ya non-PLT ya GOT (sehemu inayotumika kwa mabadiliko ya data) inawekwa katika sehemu isiyo na maandiko. Sehemu ambazo zinahitaji kubadilishwa wakati wa utekelezaji – muhimu zaidi .got.plt ambayo inasaidia lazy binding – zinabaki kuwa na uwezo wa kuandikwa.
  • Kwa sababu hiyo, primitive ya kuandika bila mipaka bado inaweza kuelekeza mtiririko wa utekelezaji kwa kuandika upya PLT entry (au kwa kufanya ret2dlresolve).
  • Athari za utendaji ni ndogo na kwa hivyo karibu kila usambazaji umekuwa ukisafirisha pakiti zikiwa na angalau Partial RELRO kwa miaka (ni chaguo la msingi la GCC/Binutils tangu 2016).

Full RELRO

  • Inazalishwa kwa bendera zote -Wl,-z,relro,-z,now (pia inajulikana kama -z relro -z now). -z now inalazimisha loader ya dynamic kutatua mifano yote mapema (eager binding) ili .got.plt isihitaji kuandikwa tena na inaweza kuandikwa kwa usalama kama read-only.
  • GOT nzima, .got.plt, .fini_array, .init_array, .preinit_array na meza chache za ndani za glibc zinaishia ndani ya sehemu isiyo na maandiko ya PT_GNU_RELRO.
  • Inaleta ongezeko la gharama za kuanzisha zinazoweza kupimwa (mabadiliko yote ya dynamic yanashughulikiwa wakati wa uzinduzi) lakini hakuna gharama za wakati wa utekelezaji.

Tangu mwaka 2023 usambazaji kadhaa maarufu umepita katika kuunda system tool-chain (na pakiti nyingi) kwa Full RELRO kama chaguo la msingi – mfano Debian 12 “bookworm” (dpkg-buildflags 13.0.0) na Fedora 35+. Kama pentester unapaswa hivyo kutarajia kukutana na binaries ambapo kila GOT entry ni read-only.


Jinsi ya Kuangalia hali ya RELRO ya binary

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

checksec (sehemu ya pwntools na usambazaji mwingi) inachambua vichwa vya ELF na kuchapisha kiwango cha ulinzi. Ikiwa huwezi kutumia checksec, tegemea readelf:

bash
# 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
bash
# Full RELRO → PT_GNU_RELRO *and* the DF_BIND_NOW flag
$ readelf -d ./vuln | grep BIND_NOW
0x0000000000000010 (FLAGS)              FLAGS: BIND_NOW

Ikiwa binary inafanya kazi (kwa mfano, msaidizi wa set-uid root), bado unaweza kuchunguza executable via /proc/$PID/exe:

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

Kuwezesha RELRO unapokuwa unakusanya msimbo wako mwenyewe

bash
# 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 inafanya kazi kwa GCC/clang (iliyopita baada ya -Wl,) na ld moja kwa moja. Wakati wa kutumia CMake 3.18+ unaweza kuomba Full RELRO kwa preset iliyojengwa ndani:

cmake
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")

Mbinu za Kuepuka

Kiwango cha RELROKawaida primitiveMbinu zinazowezekana za unyakuzi
Hakuna / SehemuKuandika bila mpangilio1. Badilisha .got.plt kuingia na pivot execution.
2. ret2dlresolve – tengeneza Elf64_Rela & Elf64_Sym bandia katika sehemu inayoweza kuandikwa na kuita _dl_runtime_resolve.
3. Badilisha viashiria vya kazi katika orodha ya .fini_array / atexit().
KamiliGOT ni ya kusoma tu1. Tafuta viashiria vingine vya kazi vinavyoweza kuandikwa (C++ vtables, __malloc_hook < glibc 2.34, __free_hook, callbacks katika sehemu za desturi .data, kurasa za JIT).
2. Tumia relative read primitives kuvuja libc na kufanya SROP/ROP ndani ya libc.
3. Ingiza kitu cha pamoja kisicho halali kupitia DT_RPATH/LD_PRELOAD (ikiwa mazingira yanadhibitiwa na mshambuliaji) au ld_audit.
4. Fanya unyakuzi wa format-string au kuandika sehemu ya kiashiria ili kuelekeza mtiririko wa udhibiti bila kugusa GOT.

💡 Hata na Full RELRO, GOT ya maktaba za pamoja zilizoloadiwa (k.m. libc yenyewe) ni sehemu tu ya RELRO kwa sababu vitu hivyo tayari vimepangwa wakati mzigo unapotumia uhamasishaji. Ikiwa unapata primitive ya kuandika bila mpangilio inayoweza kulenga kurasa za kitu kingine cha pamoja, bado unaweza pivot execution kwa kubadilisha entries za GOT za libc au stack ya __rtld_global, mbinu inayotumiwa mara kwa mara katika changamoto za kisasa za CTF.

Mfano wa kuepuka wa kweli (2024 CTF – pwn.college “enlightened”)

Changamoto ililetwa na Full RELRO. Unyakuzi ulitumia off-by-one kuharibu ukubwa wa kipande cha heap, ukavuja libc kwa tcache poisoning, na hatimaye ukabadili __free_hook (nje ya sehemu ya RELRO) kwa gadget moja ili kupata utekelezaji wa msimbo. Hakuna kuandika GOT kulihitajika.


Utafiti wa hivi karibuni & udhaifu (2022-2025)

  • glibc 2.40 inafuta __malloc_hook / __free_hook (2025) – Unyakuzi wa kisasa wa heap ambao ulitumia alama hizi sasa lazima uhamie kwenye njia mbadala kama rtld_global._dl_load_jump au meza za kutengwa za C++. Kwa sababu hooks ziko nje ya RELRO, kuondolewa kwao kunafanya iwe vigumu zaidi kuepuka Full-RELRO.
  • Binutils 2.41 “max-page-size” fix (2024) – Kosa liliruhusu bytes chache za mwisho za sehemu ya RELRO kushiriki ukurasa na data inayoweza kuandikwa kwenye baadhi ya ujenzi wa ARM64, ikiacha RELRO gap ndogo ambayo inaweza kuandikwa baada ya mprotect. Upstream sasa inalinganisha PT_GNU_RELRO na mipaka ya ukurasa, ikiondoa hali hiyo ya ukingo.

Marejeleo

  • Hati za Binutils – -z relro, -z now na PT_GNU_RELRO
  • “RELRO – Kamili, Sehemu na Mbinu za Kuepuka” – chapisho la blog @ wolfslittlered 2023

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks