Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
schrodingers-toctou — Detecta carregamentos de memória inventados pelo compilador que transformam C seguro em vulnerabilidades TOCTOU. Inclui auditorias automatizadas de código-fonte, análise binária baseada em Unicorn e varreduras de compilador/arquitetura/flags em mais de 100 projetos. | Kitploit
Ferramentas/GitHubGitHub/xoreaxeaxeax/schrodingers-toctou
Análise Dinâmica (Sandboxing)Análise Estática de Código (SAST)Análise de VulnerabilidadesExploraçãoAnálise de BináriosAprendizado e Educação
GitHubxoreaxeaxeax/schrodingers-toctou

schrodingers-toctou

Detecta carregamentos de memória inventados pelo compilador que transformam C seguro em vulnerabilidades TOCTOU. Inclui auditorias automatizadas de código-fonte, análise binária baseada em Unicorn e varreduras de compilador/arquitetura/flags em mais de 100 projetos.

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Ver Repositório
94428há 1 mêsRevisado pelo Kitploit
Compartilhar

Schrödinger's TOCTOU

"...a definição de 'compilador sensato' fica cada vez mais frouxa."

O binário que você executa não é o programa que você escreveu. O otimizador do compilador reescreve seu código-fonte de maneiras que você nunca vê — e algumas dessas mudanças podem silenciosa e legalmente transformar código aparentemente seguro em binários vulneráveis. A mesma linha pode ser segura com um compilador e explorável com outro, sem nada no código-fonte que lhe diga qual delas: uma vulnerabilidade mantida em superposição, colapsada apenas quando você compila. Schrödinger's TOCTOU explora loads inventados pelo compilador e suas amplas implicações para vulnerabilidades do tipo time-of-check to time-of-use (TOCTOU) — encontradas em código aberto: kernels, hipervisores, enclaves, firmware, e bibliotecas. Onde quer que olhemos, código aparentemente seguro fica exposto aos caprichos do compilador. Mas esses são uma amostra, não um limite; os mesmos bugs estão muito provavelmente no seu código também.

Desafio

"Comece com algo fácil."

Quantas vezes esta função carrega *p?```c unsigned int g(unsigned short *p) { short t = p; / copy *p into a local for safekeeping */ return (unsigned short)t - t; }

Dica: a resposta é 1 — o código-fonte carrega `*p` uma única vez em `t`.

Cole-o no [Compiler Explorer](https://godbolt.org/z/c5K9P4dPd) (`arm gcc 14.2.0`,
`-O2`) e conte as cargas de `r0`, que contém `p`:```asm
g:
        ldrh    r2, [r0]     # load *p, once
        ldrsh   r0, [r0]     # load *p, twice
        subs    r0, r2, r0
        bx      lr

Uma carga no código-fonte, duas no binário. A segunda é uma carga inventada — uma leitura que o compilador fabricou e que você nunca escreveu. Ela é legal sob a máquina abstrata de C, que assume que a memória não pode mudar entre duas leituras. Mas quando essa memória é gravável por um atacante, a suposição se torna uma exploração: a carga inventada pode cair depois de uma verificação de segurança, reabrindo silenciosamente uma janela de tempo-de-verificação para tempo-de-uso (TOCTOU) que o programador acreditava ter fechado. O valor que você validou e o valor que você usa não são mais garantidamente os mesmos — mesmo que você nunca tenha escrito código que o lesse novamente.

Um estouro de buffer vindo do nada

O desafio prova que a carga inventada existe; vejamos como isso se transforma em corrupção de memória.

Em uma vulnerabilidade TOCTOU, um programa verifica que um valor é seguro e então usa o valor. No entanto, existe uma janela para exploração se um atacante puder alterar o valor no ínterim entre essas duas leituras – o valor inofensivo passa na verificação enquanto o perigoso é o que é usado:```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

A correção clássica é **tirar um snapshot primeiro**: copie quaisquer dados que o atacante possa
adulterar para uma área local que o atacante não possa alcançar, e então confie apenas
nessa área local. Uma vez que `len` está em uma variável local, ele fica congelado — um atacante disputando a
memória compartilhada não pode mais tocá-lo — portanto, a verificação e a cópia têm garantia
de ver o mesmo valor. É assim que o código em `receive` abaixo corrige o TOCTOU:
ele tira um snapshot da mensagem, valida o snapshot e publica a cópia validada
em `slot` para um consumidor encaminhar:```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? */
}

Pelo código-fonte, isso está correto. len é lido exatamente uma vez — para o snapshot — então o valor que satisfaz a verificação <= 20 é o valor publicado em slot. A janela TOCTOU está fechada e o código está seguro.

Exceto que não está. Sob x86-64 gcc -O2, receive o lê da memória compartilhada original duas vezes: uma como um escalar para controlar a verificação, e novamente como parte de a cópia em massa que é publicada em 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]

A verificação roda na LEITURA #1; o valor que chega a `slot.len` é a LEITURA #2. Um
atacante que altera `len` entre elas passa um valor seguro para a verificação `<= 20`
enquanto um valor superdimensionado é publicado em `slot` — e `forward` então copia
essa quantidade de bytes para `out[20]`, exatamente o estouro que o snapshot deveria evitar,
reintroduzido pelo otimizador.
Baixar ferramenta