Skip to content
KitploitKITPLOIT
OutilsBlog
Log in
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
schrodingers-toctou — Détecte les chargements mémoire inventés par le compilateur qui transforment du C sécurisé en vulnérabilités TOCTOU. Comprend des audits automatisés de code source, une analyse binaire basée sur Unicorn et des balayages compilateur/arch/flags sur plus de 100 projets. | Kitploit
Outils/GitHubGitHub/xoreaxeaxeax/schrodingers-toctou
Analyse Dynamique (Sandboxing)Analyse Statique de Code (SAST)Analyse des VulnérabilitésExploitationAnalyse de BinairesApprentissage et Éducation
GitHubxoreaxeaxeax/schrodingers-toctou

schrodingers-toctou

Détecte les chargements mémoire inventés par le compilateur qui transforment du C sécurisé en vulnérabilités TOCTOU. Comprend des audits automatisés de code source, une analyse binaire basée sur Unicorn et des balayages compilateur/arch/flags sur plus de 100 projets.

Voir le dépôt
94428il y a 1 moisVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Le TOCTOU de Schrödinger

"...la définition d'un 'compilateur sain d'esprit' ne cesse de s'assouplir."

Le binaire que vous exécutez n'est pas le programme que vous avez écrit. L'optimiseur du compilateur réécrit votre source de manières que vous ne voyez jamais — et certains de ces changements peuvent silencieusement et légitimement transformer un code d'apparence sécurisée en binaires vulnérables. La même ligne peut être sûre avec un compilateur et exploitable avec un autre, sans que rien dans la source ne vous indique laquelle : une vulnérabilité maintenue en superposition, qui ne se matérialise qu'à la compilation. Schrödinger's TOCTOU explore les chargements inventés par le compilateur et leurs implications étendues pour les vulnérabilités de type temps de vérification / temps d'utilisation (TOCTOU) — découvertes dans des noyaux open source, hyperviseurs, enclaves, firmware, et bibliothèques. Partout où nous regardons, un code d'apparence sécurisée reste exposé aux caprices du compilateur. Mais ce ne sont que des exemples, pas une limite ; les mêmes bugs se trouvent très probablement dans votre code aussi.

Challenge

Commençons par quelque chose de facile.

Combien de fois cette fonction charge-t-elle *p ?```c unsigned int g(unsigned short *p) { short t = p; / copy *p into a local for safekeeping */ return (unsigned short)t - t; }

Indice : la réponse est 1 — la source charge `*p` une seule fois dans `t`.

Collez-le dans [Compiler Explorer](https://godbolt.org/z/c5K9P4dPd) (`arm gcc 14.2.0`,
`-O2`) et comptez les chargements depuis `r0`, qui contient `p` :```asm
g:
        ldrh    r2, [r0]     # load *p, once
        ldrsh   r0, [r0]     # load *p, twice
        subs    r0, r2, r0
        bx      lr

Une lecture dans la source, deux dans le binaire. La seconde est une lecture inventée — une lecture que le compilateur a fabriquée et que vous n'avez jamais écrite. Elle est légale selon la machine abstraite du C, qui suppose que la mémoire ne peut pas changer entre deux lectures. Mais lorsque cette mémoire est modifiable par un attaquant, l'hypothèse devient un vecteur d'exploitation : la lecture inventée peut survenir après un contrôle de sécurité, rouvrant silencieusement une fenêtre de type time-of-check to time-of-use (TOCTOU) que le programmeur croyait avoir fermée. La valeur que vous avez validée et celle que vous utilisez ne sont plus garanties d'être identiques — même si vous n'avez jamais écrit de code qui la relise.

Un débordement de tampon sorti de nulle part

Le défi prouve que la lecture inventée existe ; voyons comment cela se transforme en corruption de la mémoire.

Dans une vulnérabilité TOCTOU, un programme vérifie qu'une valeur est sûre, puis utilise la valeur. Cependant, une fenêtre d'exploitation existe si un attaquant peut modifier la valeur dans l'infime intervalle de temps entre ces deux lectures – la valeur inoffensive passe le contrôle tandis que la valeur dangereuse est celle qui est utilisée :```c if (shared->len <= 20) // CHECK reads shared->len // ** attacker modifies shared->len ** memcpy(out, shared->data, shared->len); // USE reads it again: buffer overflow

La correction classique consiste à **faire d'abord un instantané** : copier toutes les données que l'attaquant pourrait modifier dans une zone locale à laquelle l'attaquant ne peut pas accéder, puis ne faire confiance qu'à cette zone locale. Une fois `len` dans une variable locale, il est figé — un attaquant en course avec la mémoire partagée ne peut plus le toucher — si bien que la vérification et la copie sont garanties de voir la même valeur. C'est ainsi que le code dans `receive` ci-dessous corrige la faille TOCTOU : il prend un instantané du message, valide l'instantané, puis publie la copie validée dans `slot` pour qu'un consommateur la transmette :```c
#include <string.h>

struct message {
    int  len;          /* payload length */
    char data[20];     /* payload        */
};

struct message slot;   /* the most recently validated message */
char out[20];          /* fixed 20-byte destination           */

void receive(struct message *shared) {
    struct message local = *shared;    /* 1. snapshot untrusted input   */
    if (local.len <= 20)               /* 2. validate the snapshot      */
        slot = local;                  /* 3. publish the validated copy */
}

void forward(void) {                   /* the time of use, later        */
    memcpy(out, slot.data, slot.len);  /* slot.len was checked <= 20 ... right? */
}

D'après le code source, cela est correct. len est lu exactement une fois — dans l'instantané — donc la valeur qui satisfait la condition <= 20 est celle publiée dans slot. La fenêtre TOCTOU est fermée et le code est sûr.

Sauf que non. Sous x86-64 gcc -O2, receive le lit depuis la mémoire partagée originale deux fois : une fois comme scalaire pour contrôler le test, et une autre fois dans le cadre de la copie en bloc qui est publiée dans slot :```nasm receive: cmp DWORD PTR [rdi], 20 ; READ #1: the CHECK reads shared->len directly movdqu xmm0, XMMWORD PTR [rdi] ; READ #2: the bulk copy re-reads it (len is byte 0) mov rax, QWORD PTR [rdi+16] ; (the bulk copy's tail: struct bytes 16-23) jg .L1 ; len > 20? skip the publish mov QWORD PTR slot[rip+16], rax ; (publish that tail) movaps XMMWORD PTR slot[rip], xmm0 ; and publish the TOCTOU-vulnerable snapshot .L1: ret forward: movsx rdx, DWORD PTR slot[rip] ; copy size = slot.len, the unchecked READ #2 value mov esi, OFFSET FLAT:slot+4 ; src = slot.data mov edi, OFFSET FLAT:out ; dst = out[20] jmp memcpy ; copies slot.len bytes into out[20]

Le contrôle s'appuie sur la lecture n°1 ; la valeur qui aboutit dans `slot.len` est la lecture n°2. Un
attaquant qui fait basculer `len` entre les deux fait passer une valeur sûre au contrôle `<= 20`
tandis qu'une valeur surdimensionnée est publiée dans `slot` — et `forward` copie alors autant
d'octets dans `out[20]`, exactement le débordement que l'instantané était censé empêcher,
réintroduit par l'optimiseur.
Télécharger l’outil