Aller au contenu principal
own2pwn
pwn/pwn-cra.tsx

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

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
Toutes les Code Reuse Attacks s'appuient d'abord sur une Control Flow Attack pour lancer la machine : un stack overflow, un use-after-free, etc. permettent de prendre la main sur un registre de contrôle (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.

cra-map.txt
  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)                              │
  └──────────────────────────────────────────────────────────────────┘
Les 9 familles de Code Reuse Attacks, classées par instruction pivot.
TechniqueAcronyme expanséGadget pivotParticularité
ROPReturn-Oriented ProgrammingretLa technique de référence. Chaîne des gadgets via la pile.
JOP / TOPJump / Trampoline-Oriented Programmingjmp indirectContourne les protections contre ROP (shadow stack, retpoline). Utilise des trampolines pour dispatcher.
COPCall-Oriented Programmingcall indirectVariante de JOP utilisant des gadgets terminés par call.
PCOPPure Call-Oriented Programmingcall uniquementCOP sans aucun gadget ret, vise les binaires avec protections anti-ROP agressives.
COOPCounterfeit-Object Oriented Programmingvtables C++Forge de faux objets C++ pour détourner les appels virtuels. Contourne les CFI (Control Flow Integrity) basiques.
LOPLoop-Oriented Programmingboucles (loop, jne...)Exploite les gadgets de type boucle pour accélérer les payloads ou contourner certains filtres.
SOPString-Oriented Programmingfonctions libc stringRéutilise les effets de bord de fonctions comme strcpy, sprintf pour construire un payload sans gadgets classiques.
SROPSigreturn-Oriented Programmingsigreturn syscallAbuse du mécanisme de retour de signal Linux pour charger un contexte CPU arbitraire en un seul gadget.
BROPBlind Return-Oriented Programmingret (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
Il suffit d'un gadget 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-probe.txt
  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 construite
BROP : on sonde à l'aveugle pour trouver les gadgets disponibles.