ROP, JOP, SROP : recycler le code
pour gagner
Index des familles de Code Reuse Attacks : ROP, JOP/TOP, COP, PCOP, COOP, LOP, SOP, SROP et BROP. Un article-sommaire pour situer chaque technique dans la galaxie du code reuse avant d'aller les creuser une par une.
Maxime Jérôme··3 min de lecture
Prérequis
- Compréhension des fichiers ELF (voir Segmentation Mémoire)
- Maniement de GDB
Hello ! o/
Les Code Reuse Attacks (CRA) sont la famille d'attaques qui consiste à réutiliser du code déjà chargé en mémoire pour faire ce qu'on veut, sans jamais injecter de nouveau code. Plutôt que d'écrire un shellcode, on assemble des gadgets : de petites séquences d'instructions qui se terminent par une instruction de transfert de contrôle (ret, jmp, call...) et qu'on enchaîne pour construire un payload.
C'est la réponse technique aux protections comme NX (No eXecute) et DEP (Data Execution Prevention) qui empêchent d'exécuter du code dans des zones de données. Avec les CRA, tout le code utilisé est déjà marqué exécutable par l'OS.
Prérequis commun à toutes ces techniques
RIP, RSP...) avant de chaîner les gadgets. Voir l' introduction à la série PWN si ce n'est pas encore clair.La galaxie des Code Reuse Attacks
Voilà la carte du territoire : chaque famille se distingue par le type de gadget utilisé et l'instruction de transfert de contrôle sur laquelle elle s'appuie.
CODE REUSE ATTACKS
┌──────────────────────────────────────────────────────────────────┐
│ Pivot : RET Pivot : JMP/CALL Pivot : autre │
│ ───────────────── ────────────────────── ────────────── │
│ │
│ ROP JOP / TOP SROP │
│ Return-Oriented Jump/Trampoline- Sigreturn- │
│ Programming Oriented Programming Oriented Prog. │
│ │
│ BROP COP LOP │
│ Blind ROP Call-Oriented Loop-Oriented │
│ (pas d'accès Programming Programming │
│ au binaire) │
│ PCOP SOP │
│ Pure COP String-Oriented │
│ (sans gadgets ret) Programming │
│ │
│ COOP │
│ Counterfeit-Object │
│ Oriented Programming │
│ (C++ vtables) │
└──────────────────────────────────────────────────────────────────┘| Technique | Acronyme expansé | Gadget pivot | Particularité |
|---|---|---|---|
| ROP | Return-Oriented Programming | ret | La technique de référence. Chaîne des gadgets via la pile. |
| JOP / TOP | Jump / Trampoline-Oriented Programming | jmp indirect | Contourne les protections contre ROP (shadow stack, retpoline). Utilise des trampolines pour dispatcher. |
| COP | Call-Oriented Programming | call indirect | Variante de JOP utilisant des gadgets terminés par call. |
| PCOP | Pure Call-Oriented Programming | call uniquement | COP sans aucun gadget ret, vise les binaires avec protections anti-ROP agressives. |
| COOP | Counterfeit-Object Oriented Programming | vtables C++ | Forge de faux objets C++ pour détourner les appels virtuels. Contourne les CFI (Control Flow Integrity) basiques. |
| LOP | Loop-Oriented Programming | boucles (loop, jne...) | Exploite les gadgets de type boucle pour accélérer les payloads ou contourner certains filtres. |
| SOP | String-Oriented Programming | fonctions libc string | Réutilise les effets de bord de fonctions comme strcpy, sprintf pour construire un payload sans gadgets classiques. |
| SROP | Sigreturn-Oriented Programming | sigreturn syscall | Abuse du mécanisme de retour de signal Linux pour charger un contexte CPU arbitraire en un seul gadget. |
| BROP | Blind Return-Oriented Programming | ret (sans source) | ROP sans accès au binaire ni aux symboles. On sonde à l'aveugle via crash / no-crash pour cartographier les gadgets disponibles. |
ROP - Return-Oriented Programming
ROP (Return-Oriented Programming) est la technique fondatrice des Code Reuse Attacks. L'idée : enchaîner des petits bouts de code existants, appelés gadgets, chacun se terminant par un ret. On contrôle la pile pour définir l'ordre d'exécution, et on compose un payload complet sans écrire une seule instruction.
C'est le point d'entrée obligatoire de la série - un article dédié arrive.
JOP/TOP - Jump/Trampoline-Oriented Programming
JOP (Jump-Oriented Programming) remplace les ret par des jmp indirects. Le dispatcher est un gadget central qui lit la prochaine cible dans un registre ou une structure de données. TOP (Trampoline-Oriented Programming) est une variante qui utilise des trampolines pour sauter d'un gadget à l'autre, ce qui contourne les mécanismes qui surveillent les ret (shadow stack, retpoline...).
COP - Call-Oriented Programming
Même principe que JOP mais avec des call indirects comme instruction pivot. Utile quand les gadgets terminés par ret ou jmp sont rares ou filtrés.
PCOP - Pure Call-Oriented Programming
Variante de COP qui s'interdit tout gadget ret. Vise les binaires compilés avec des protections anti-ROP très agressives qui invalident tout retour de fonction anormal.
COOP - Counterfeit-Object Oriented Programming
COOP exploite la mécanique des vtables C++. On forge de faux objets dont les vtables pointent vers des fonctions membres légitimes (les vfgadgets) pour construire un payload. Particulièrement redoutable contre les CFI (Control Flow Integrity) basiques qui autorisent les appels via vtables sans vérifier la légitimité de l'objet.
LOP - Loop-Oriented Programming
LOP tire parti de gadgets contenant des boucles (loop, rep, jne...) pour accélérer des opérations répétitives dans un payload ou pour contourner des filtres qui détectent les gadgets de type ret.
SOP - String-Oriented Programming
SOP réutilise les effets de bord des fonctions de manipulation de chaînes de la libc ( strcpy, memcpy, sprintf...) pour écrire en mémoire ou déclencher des comportements utiles, sans passer par des gadgets assembleur classiques.
SROP - SigReturn-Oriented Programming
SROP est élégant : il abuse du mécanisme de retour de signal Linux. Quand le noyau revient d'un gestionnaire de signal, il restaure le contexte CPU complet depuis la pile via un appel à sigreturn. Si on contrôle la pile, on peut y écrire un faux contexte (sigcontext) avec les valeurs de registres qu'on veut, et déclencher sigreturn pour charger ce contexte d'un coup. Un seul gadget, contrôle total de tous les registres.
Pourquoi SROP est puissant
syscall ; ret ou int 0x80 ; ret pour déclencher sigreturn (syscall 15 sur x86-64). Pas besoin de trouver des dizaines de gadgets - un seul suffit pour fixer tous les registres en une passe.BROP - Blind Return-Oriented Programming
BROP, c'est le ROP sans carte. On n'a pas accès au binaire, pas de symboles, parfois pas même un crash dump. On exploite un service réseau qui crash et redémarre (fork-based server) : en sondant des adresses une par une et en observant le comportement (crash / no-crash / output), on cartographie les gadgets disponibles puis on construit un payload ROP classique.
BROP - sondage blind
Attaquant Serveur (fork-based)
│ │
│ overflow + addr_X │
│─────────────────────────────►│
│ │ crash ? no-crash ?
│◄─────────────────────────────│
│ (timeout = crash) │
│ │
│ overflow + addr_X+1 │
│─────────────────────────────►│
│ │ ...on itère
│◄─────────────────────────────│
│ │
│ addr trouvée = gadget ? │
│ ───────────────────────── │
│ test avec registres connus │
│─────────────────────────────►│
│ │
▼ ▼
carte des gadgets disponibles construiteArticle suivant
NX, ASLR, canary : ce qui rend le pwn dur