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.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
CVE-2026-43805-analysis — Análise de um dia + PoC de sanitização da CVE-2026-43805 (corrida RPC do DriverKit IODMACommand do IOKit, CWE-362) | Kitploit
Ferramentas/GitHubGitHub/wtcyj/cve-2026-43805-analysis
Análise EstáticaForensia de MemóriaAnálise de VulnerabilidadesExploraçãoEngenharia ReversaPapers e PesquisaAprendizado e Educação
GitHubwtcyj/cve-2026-43805-analysis

CVE-2026-43805-analysis

Análise de um dia + PoC de sanitização da CVE-2026-43805 (corrida RPC do DriverKit IODMACommand do IOKit, CWE-362)

Ver Repositório
há 1 mêsAinda não revisado

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 →
Compartilhar

CVE-2026-43805 — corrida de RPC do DriverKit no IODMACommand do IOKit

Uma análise one-day da condição de corrida do IOKit da Apple corrigida no iOS/iPadOS 26.6, macOS Tahoe 26.6, Sequoia 15.7.8, Sonoma 14.8.8 e watchOS 26.6. Não existia proof-of-concept público quando isto foi escrito, portanto o trabalho aqui é: localizar o código corrigido lendo o código-fonte primário do XNU, explicar a causa raiz até o objeto liberado, e reproduzir o defeito como um modelo fiel e verificado por sanitizer.

O aviso da Apple é sucinto:

Uma condição de corrida foi corrigida com melhor tratamento de estado. Um app pode ser capaz de causar encerramento inesperado do sistema ou escrever na memória do kernel.

Classificado como CWE-362 (execução concorrente com sincronização inadequada), CVSS 9.8. Avisos: 128066 · 128067 · 128068 · 128071 · 128072.

Onde está o bug

O IODMACommand é exposto às extensões DriverKit (dexts) via RPC. As implementações no lado do kernel desses pontos de entrada RPC são os métodos _Impl em iokit/Kernel/IOUserServer.cpp. Uma dext conduz um buffer DMA através de três deles:

Método RPClinha (xnu-12377.121.6)mantém fInternalState->fDextLock?
PrepareForDMA_Impl1009sim — IOLockLock @1033, unlock @1078
CompleteDMA_Impl1084sim — IOLockLock @1096, unlock @1118
PerformOperation_Impl1154não — lê fActive e fMemory sem lock

O lock existe. IODMACommand::init o aloca (iokit/Kernel/IODMACommand.cpp linha 342). Dois dos três irmãos o adquirem. O terceiro não — e o terceiro é o que desreferencia o descritor de memória compartilhado. Essa assimetria é a vulnerabilidade.

xnu-12377.121.6 (macOS 26.x, a tag mais recente para a qual a Apple publicou código-fonte) ainda mostra o PerformOperation_Impl sem lock, portanto é a árvore vulnerável; o drop de código-fonte 26.6 que contém a correção ainda não é público. O código-fonte relevante está espelhado em analysis/IOUserServer_excerpt.cpp.

Causa raiz

PerformOperation_Impl faz um time-of-check em fActive, depois usa fMemory:

    if (!fActive) {                        // time-of-check  (no lock held)
        return kIOReturnNotReady;
    }
    ...
    if (length > fMemory->getLength()) {   // time-of-use   (fMemory may be gone)
        return kIOReturnBadArgument;
    }
    ...
    copiedDMA = writeBytes(dmaOffset, buffer.data(), length);   // write into the mapping

CompleteDMA_Impl executa o teardown sob o lock:

    IOLockLock(fInternalState->fDextLock);
    ...
    ret = clearMemoryDescriptor(true);     // see below
    ...
    IOLockUnlock(fInternalState->fDextLock);

e clearMemoryDescriptor(true) (IODMACommand.cpp linha 455) é o que realmente libera a coisa que PerformOperation está prestes a acessar:

    if (fMemory) {
        while (fActive) {
            complete();                    // drains fActive to 0
        }
        ...
        fMemory.reset();                   // releases the IOMemoryDescriptor
    }

Portanto, o entrelaçamento perigoso é:

  1. PerformOperation_Impl passa if (!fActive) enquanto o comando ainda está ativo.
  2. CompleteDMA_Impl adquire o lock, drena fActive e executa fMemory.reset(), liberando o descritor de memória e permitindo que seu backing wired seja liberado/reutilizado.
  3. PerformOperation_Impl, ainda em execução, desreferencia o fMemory agora obsoleto em getLength() e depois em writeBytes().

Como PerformOperation nunca adquiriu o lock, o passo 2 pode ocorrer livremente na lacuna entre os passos 1 e 3. writeBytes copia bytes fornecidos pelo chamador para um mapeamento DMA cujo backing foi liberado — uma vez que essa página seja reutilizada para outra alocação do kernel, trata-se da "escrita em memória do kernel" sobre a qual o advisory alerta. Atinge-o no caminho de leitura e você obtém a leitura use-after-free / encerramento inesperado.

sequenceDiagram
    participant W as dext thread A — PerformOperation_Impl (no lock)
    participant O as dext thread B — CompleteDMA_Impl (holds fDextLock)
    W->>W: if (!fActive) → active, continue
    Note over W: passed the check, about to use fMemory
    O->>O: IOLockLock(fDextLock)
    O->>O: clearMemoryDescriptor(true): fActive=0, fMemory.reset()  ← FREE
    O->>O: IOLockUnlock(fDextLock)
    W->>W: fMemory->getLength() / writeBytes()  ← USE-AFTER-FREE

Reproduzindo sem um macOS vulnerável

Acionar o caminho real exige um dext DriverKit assinado com o entitlement DriverKit da Apple em uma build vulnerável, o que não é acessível a partir de um host Windows. Em vez disso, poc/race_model.cpp reimplementa a lógica exata de estado compartilhado dos três métodos — mesma disciplina de lock, mesma ordem check-then-free-then-use — para que o defeito possa ser observado diretamente:

  • PrepareForDMA e CompleteDMA adquirem o mutex; PerformOperation não (a menos que compilado com -DFIXED, que adiciona o lock que falta).
  • CompleteDMA libera o descritor, espelhando fMemory.reset().
  • Um harness de driver executa PerformOperation em uma thread e CompleteDMA em outra, posicionando o teardown dentro da janela de corrida com um sinal atômico (apenas temporização — nunca é um lock sobre o estado compartilhado).
cd poc
bash run.sh

Build vulnerável:

  • O ThreadSanitizer relata uma data race — operator delete dentro de CompleteDMA competindo com a leitura de getLength() dentro de PerformOperation, com o mutex mantido apenas pelo deleter. Log completo: evidence/tsan_vulnerable.txt.
  • O AddressSanitizer relata um heap-use-after-free: o objeto liberado em CompleteDMA é lido em PerformOperation::getLength, alocado em PrepareForDMA. Log completo: evidence/asan_vulnerable.txt.
==ERROR: AddressSanitizer: heap-use-after-free ... in MemoryDescriptor::getLength()
freed by thread T0 here:   ... IODMACommand::CompleteDMA()  race_model.cpp:70
allocated by thread T0:    ... IODMACommand::PrepareForDMA() race_model.cpp:61

A compilação corrigida (-DFIXED, o lock adicionado a PerformOperation): ambos os sanitizers estão limpos e cada operação é serializada corretamente em relação ao teardown. Logs: evidence/tsan_fixed.txt, evidence/asan_fixed.txt.

Isto prova que a race é real na lógica e que o lock é tanto necessário quanto suficiente. Não é um kernel panic ao vivo — ver o escopo abaixo.

A correção

Baixar ferramenta