KASLR, KPTI et défenses modernes du noyau
Randomisation d'adresses, isolation des tables de pages et options de configuration qui durcissent un noyau Linux : ce que chacune arrête et comment l'activer.
Security engineer writing about memory safety, exploit mitigations, sanitizers and fuzzing, from the secure-coder's side of the fence.
Randomisation d'adresses, isolation des tables de pages et options de configuration qui durcissent un noyau Linux : ce que chacune arrête et comment l'activer.
Un bug mémoire du noyau vise le privilège, pas un shell : modèle de credentials, charge commit_creds(prepare_kernel_cred(0)), retour propre en userspace.
Le noyau faisait confiance à la mémoire userspace. SMEP et SMAP y ont mis fin — et voici comment le ROP noyau les contourne.
Chaque exploit suit les mêmes étapes : bug, corruption, détournement, exécution, escalade. Quelle mitigation les arrête, sous Linux, ARM, Windows, noyau.
DEP rend le shellcode sur la pile inexécutable ; une chaîne ROP appelle VirtualProtect pour rendre la région exécutable, puis y saute.
Comment SafeSEH, SEHOP, ASLR, CFG et le CET matériel ferment chacun une technique d'exploitation Windows : vérifications, activation et limites.
Windows garde une liste chaînée de gestionnaires d'exceptions sur la pile. Débordez-y, pointez vers un pop-pop-ret, et le contrôle est à vous.
Sur AArch64 l'adresse de retour vit dans un registre, pas sur la pile — jusqu'à ce qu'une fonction non-feuille la sauvegarde. Construisez le ret2win ARM.
L'authentification de pointeur signe les adresses de retour ; une falsification fait fauter le processus. BTI contraint les branchements indirects.
Les gadgets AArch64 finissent par ret, qui branche vers x30 : la chaîne s'enfile dans le registre de lien via des gadgets ldp. Puis PAC et BTI la brisent.
Parfois vous ne contrôlez qu'un pointeur. Un one-gadget est une seule adresse libc qui appelle execve("/bin/sh") si ses contraintes tiennent.
Sans fuite libc : forgez la relocation que lit l'éditeur de liens dynamique pour lui faire résoudre et appeler system. Et pourquoi Full RELRO y met fin.
Une politique seccomp qui bannit execve retire le shell du jeu ; les attaquants pivotent : ouvrir le flag, le lire, le renvoyer. La chaîne ORW.
Les hooks partis, l'objet FILE devient la cible : un appel stdio passe par un pointeur de vtable inscriptible — corrompez-le et le prochain fwrite tombe.
Les exploits modernes sont fuiter-puis-agir. Construisez une lecture hors limites, puis servez-vous-en pour retrouver un canari de pile, la base PIE et la base libc.
Pas de gadget pop rdx ? Le code de démarrage du runtime C a une séquence universelle qui charge plusieurs registres et fait un appel contrôlé. Construisez-la avec pwntools.
Quand les gadgets sont rares, forgez un cadre de signal. Un appel sigreturn restaure tous les registres depuis la pile d'un coup — construisez-en un avec pwntools pour appeler execve.
Quand le débordement dépasse à peine l'adresse de retour, déplacez rsp vers un tampon maîtrisé et exécutez-y la vraie chaîne. Tutoriel pwntools.
Un printf(entrée_utilisateur) est une primitive de lecture/écriture complète. Fuitez avec %p, écrasez avec %n via pwntools, puis regardez -Wformat=2 et FORTIFY_SOURCE le neutraliser.
La liaison paresseuse laisse la GOT inscriptible : une écriture arbitraire sur une entrée transforme puts() en system() — jusqu'à ce que Full RELRO la fige.
Les métadonnées du tas sont la primitive d'écriture. Un use-after-free empoisonne le tcache de la glibc pour allouer un chunk à une adresse choisie.
Tutoriel de labo : écraser une adresse de retour sauvegardée avec pwntools pour rediriger l'exécution, puis voir chaque mitigation casser l'exploit.
NX est actif et le binaire est minuscule, mais la libc est mappée et pleine de code utile. Fuitez sa base malgré l'ASLR, puis retournez dans system("/bin/sh").
Avec NX, le shellcode injecté est mort : on réutilise le code existant. Trouver des gadgets, bâtir une chaîne execve avec pwntools, puis voir CET et CFI la casser.
Un parcours légal et progressif du C et de l'assembleur aux défis pwn de CTF : quoi apprendre et dans quel ordre, plateformes de pratique, règles de labo.
Pourquoi les langages sûrs pour la mémoire éliminent des classes de bugs, ce que garantit la propriété de Rust, et où unsafe et le FFI restent risqués.
Écrire un harnais de fuzzing, le compiler avec des sanitizers, lancer libFuzzer et AFL++, gérer corpus et dictionnaires, et fuzzer en continu en CI.
Trier les crashs natifs en défenseur : sens de SIGSEGV et SIGABRT, messages d'abort de glibc, gdb et core dumps, rapports ASan, WinDbg, et priorisation.
Comment fonctionnent ASan, UBSan, MSan, TSan et HWASan, quels flags et options utiliser, comment lire un rapport ASan ligne par ligne, et les lancer en CI.
L'intégrité du flot de contrôle sur les arêtes avant et arrière, de Clang CFI à Intel CET et l'authentification de pointeur Arm, et ses limites.
Ce que protège chaque mitigation classique, les drapeaux GCC et Clang qui l'activent, son coût, et comment vérifier un binaire avec checksec et readelf.
Comment débordement d'entier, troncature et erreurs de signe mènent à la corruption mémoire, et pourquoi les chaînes de format contrôlées sont risquées.
Comment les bugs mémoire du tas corrompent l'allocateur et l'état des objets, pourquoi le use-after-free est si dangereux, et les défenses qui les arrêtent.
Pourquoi écrire au-delà d'un tampon de pile est dangereux, les schémas C qui le causent, comment les compilateurs et sanitizers le détectent, et les corrections et mitigations qui le contiennent.
Visite guidée pour défenseur de l'espace d'adressage d'un processus Linux : segments ELF, pile et conventions d'appel, tas, mmap, et le rôle des permissions.