Relro
Reading time: 7 minutes
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
Relro
RELRO signifie Relocation Read-Only et c'est une attĂ©nuation mise en Ćuvre par le linker (ld
) qui rend un sous-ensemble des segments de donnĂ©es ELF lecture seule aprĂšs que toutes les relocations ont Ă©tĂ© appliquĂ©es. L'objectif est d'empĂȘcher un attaquant de remplacer des entrĂ©es dans la GOT (Global Offset Table) ou d'autres tables liĂ©es aux relocations qui sont dĂ©rĂ©fĂ©rencĂ©es pendant l'exĂ©cution du programme (par exemple, __fini_array
).
Les linkers modernes mettent en Ćuvre RELRO en rĂ©organisant la GOT (et quelques autres sections) afin qu'elles se trouvent avant le .bss et â surtout â en crĂ©ant un segment PT_GNU_RELRO
dĂ©diĂ© qui est remappĂ© RâX
juste aprĂšs que le chargeur dynamique ait terminĂ© d'appliquer les relocations. Par consĂ©quent, les dĂ©bordements de tampon typiques dans le .bss ne peuvent plus atteindre la GOT et les primitives d'Ă©criture arbitraire ne peuvent pas ĂȘtre utilisĂ©es pour Ă©craser des pointeurs de fonction qui se trouvent Ă l'intĂ©rieur d'une page protĂ©gĂ©e par RELRO.
Il existe deux niveaux de protection que le linker peut émettre :
Partial RELRO
- Produit avec le drapeau
-Wl,-z,relro
(ou juste-z relro
lors de l'invocation directe deld
). - Seule la partie non-PLT de la GOT (la partie utilisĂ©e pour les relocations de donnĂ©es) est placĂ©e dans le segment en lecture seule. Les sections qui doivent ĂȘtre modifiĂ©es Ă l'exĂ©cution â surtout .got.plt qui prend en charge lazy binding â restent modifiables.
- à cause de cela, une primitive d'écriture arbitraire peut toujours rediriger le flux d'exécution en écrasant une entrée PLT (ou en effectuant ret2dlresolve).
- L'impact sur les performances est négligeable et donc presque toutes les distributions expédient des paquets avec au moins Partial RELRO depuis des années (c'est le défaut de GCC/Binutils depuis 2016).
Full RELRO
- Produit avec les deux drapeaux
-Wl,-z,relro,-z,now
(a.k.a.-z relro -z now
).-z now
force le chargeur dynamique Ă rĂ©soudre tous les symboles Ă l'avance (liaison impatiente) afin que .got.plt n'ait jamais besoin d'ĂȘtre Ă©crit Ă nouveau et puisse ĂȘtre mappĂ© en toute sĂ©curitĂ© en lecture seule. - L'ensemble de la GOT, .got.plt, .fini_array, .init_array, .preinit_array et quelques tables internes supplĂ©mentaires de glibc se retrouvent Ă l'intĂ©rieur d'un segment
PT_GNU_RELRO
en lecture seule. - Ajoute un surcoût de démarrage mesurable (toutes les relocations dynamiques sont traitées au lancement) mais aucun surcoût à l'exécution.
Depuis 2023, plusieurs distributions grand public ont commencĂ© Ă compiler la tool-chain systĂšme (et la plupart des paquets) avec Full RELRO par dĂ©faut â par exemple Debian 12 âbookwormâ (dpkg-buildflags 13.0.0) et Fedora 35+. En tant que pentester, vous devez donc vous attendre Ă rencontrer des binaires oĂč chaque entrĂ©e GOT est en lecture seule.
Comment vérifier le statut RELRO d'un binaire
$ checksec --file ./vuln
[*] '/tmp/vuln'
Arch: amd64-64-little
RELRO: Full
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
checksec
(fait partie de pwntools et de nombreuses distributions) analyse les en-tĂȘtes ELF
et affiche le niveau de protection. Si vous ne pouvez pas utiliser checksec
, comptez sur 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
Si le binaire est en cours d'exécution (par exemple, un helper set-uid root), vous pouvez toujours inspecter l'exécutable via /proc/$PID/exe
:
readelf -l /proc/$(pgrep helper)/exe | grep GNU_RELRO
Activer RELRO lors de la compilation de votre propre code
# 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
fonctionne pour GCC/clang (passé aprÚs -Wl,
) et ld directement. Lorsque vous utilisez CMake 3.18+, vous pouvez demander Full RELRO avec le préréglage intégré :
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")
Techniques de contournement
Niveau RELRO | Primitive typique | Techniques d'exploitation possibles |
---|---|---|
Aucun / Partiel | Ăcriture arbitraire | 1. Ăcraser l'entrĂ©e .got.plt et pivoter l'exĂ©cution. 2. ret2dlresolve â crĂ©er un faux Elf64_Rela & Elf64_Sym dans un segment Ă©crivable et appeler _dl_runtime_resolve .3. Ăcraser les pointeurs de fonction dans .fini_array / liste atexit(). |
Complet | GOT en lecture seule | 1. Rechercher d'autres pointeurs de code écrivable (vtables C++, __malloc_hook < glibc 2.34, __free_hook , rappels dans des sections .data personnalisées, pages JIT).2. Abuser des primitives de lecture relative pour divulguer libc et effectuer SROP/ROP dans libc. 3. Injecter un objet partagé malveillant via DT_RPATH/ LD_PRELOAD (si l'environnement est contrÎlé par l'attaquant) ou ld_audit .4. Exploiter format-string ou écriture partielle de pointeur pour détourner le flux de contrÎle sans toucher le GOT. |
đĄ MĂȘme avec un RELRO Complet, le GOT des bibliothĂšques partagĂ©es chargĂ©es (par exemple, libc elle-mĂȘme) est seulement Partiel RELRO car ces objets sont dĂ©jĂ mappĂ©s lorsque le chargeur applique les relocations. Si vous obtenez une primitive d'Ă©criture arbitraire qui peut cibler les pages d'un autre objet partagĂ©, vous pouvez toujours pivoter l'exĂ©cution en Ă©crasant les entrĂ©es GOT de libc ou la pile
__rtld_global
, une technique réguliÚrement exploitée dans les défis CTF modernes.
Exemple de contournement dans le monde rĂ©el (CTF 2024 â pwn.college âenlightenedâ)
Le défi était livré avec un RELRO Complet. L'exploitation a utilisé un off-by-one pour corrompre la taille d'un morceau de tas, a divulgué libc avec tcache poisoning
, et enfin a écrasé __free_hook
(en dehors du segment RELRO) avec un one-gadget pour obtenir l'exécution de code. Aucune écriture dans le GOT n'était requise.
Recherches récentes & vulnérabilités (2022-2025)
- glibc 2.40 déprécie
__malloc_hook
/__free_hook
(2025) â La plupart des exploits de tas modernes qui abusaient de ces symboles doivent maintenant pivoter vers des vecteurs alternatifs tels quertld_global._dl_load_jump
ou les tables d'exceptions C++. Ătant donnĂ© que les hooks vivent en dehors du RELRO, leur suppression augmente la difficultĂ© des contournements de RELRO Complet. - Correction âmax-page-sizeâ de Binutils 2.41 (2024) â Un bug permettait aux derniers octets du segment RELRO de partager une page avec des donnĂ©es Ă©crivables sur certaines constructions ARM64, laissant un petit Ă©cart RELRO qui pouvait ĂȘtre Ă©crit aprĂšs
mprotect
. En amont,PT_GNU_RELRO
est maintenant aligné sur les limites de page, éliminant ce cas particulier.
Références
- Documentation de Binutils â
-z relro
,-z now
etPT_GNU_RELRO
- âRELRO â Complet, Partiel et Techniques de Contournementâ â article de blog @ wolfslittlered 2023
tip
Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d'abonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.