mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
100 lines
7.1 KiB
Markdown
100 lines
7.1 KiB
Markdown
# Relro
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## 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](https://github.com/pwncollege/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 RELRO | Kawaida primitive | Mbinu zinazowezekana za unyakuzi |
|
||
|-------------------|-------------------|----------------------------------|
|
||
| Hakuna / Sehemu | Kuandika bila mpangilio | 1. Badilisha **.got.plt** kuingia na pivot execution.<br>2. **ret2dlresolve** – tengeneza `Elf64_Rela` & `Elf64_Sym` bandia katika sehemu inayoweza kuandikwa na kuita `_dl_runtime_resolve`.<br>3. Badilisha viashiria vya kazi katika orodha ya **.fini_array** / **atexit()**. |
|
||
| Kamili | GOT ni ya kusoma tu | 1. 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).<br>2. Tumia *relative read* primitives kuvuja libc na kufanya **SROP/ROP ndani ya libc**.<br>3. Ingiza kitu cha pamoja kisicho halali kupitia **DT_RPATH**/`LD_PRELOAD` (ikiwa mazingira yanadhibitiwa na mshambuliaji) au **`ld_audit`**.<br>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
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|