Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-43805-analysis — CVE-2026-43805(IOKit IODMACommand DriverKit RPC 경쟁 조건, CWE-362)에 대한 하루 만의 분석 + 새니타이저 PoC | Kitploit
도구/GitHubGitHub/wtcyj/cve-2026-43805-analysis
Static AnalysisMemory ForensicsVulnerability AnalysisExploitationReverse EngineeringPapers & ResearchLearning & Education
GitHubwtcyj/cve-2026-43805-analysis

CVE-2026-43805-analysis

CVE-2026-43805(IOKit IODMACommand DriverKit RPC 경쟁 조건, CWE-362)에 대한 하루 만의 분석 + 새니타이저 PoC

저장소 보기
1개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2026-43805 — IOKit IODMACommand DriverKit RPC 경쟁 조건

iOS/iPadOS 26.6, macOS Tahoe 26.6, Sequoia 15.7.8, Sonoma 14.8.8 및 watchOS 26.6에서 수정된 Apple IOKit 경쟁 조건에 대한 one-day 분석입니다. 이 글을 작성할 당시 공개된 proof-of-concept은 존재하지 않았으므로, 여기서의 작업은 다음과 같습니다: 기본 XNU 소스를 읽어 패치된 코드를 찾아내고, 해제된 객체에 이르기까지 근본 원인을 설명하며, 결함을 충실하고 sanitizer로 검증된 모델로 재현하는 것입니다.

Apple의 권고문은 간결합니다:

경쟁 조건이 개선된 상태 처리로 해결되었습니다. 앱이 예기치 않은 시스템 종료를 일으키거나 커널 메모리에 쓸 수 있습니다.

CWE-362(부적절한 동기화를 동반한 동시 실행)로 분류되며, CVSS 9.8입니다. 권고문: 128066 · 128067 · 128068 · 128071 · 128072.

버그가 존재하는 위치

IODMACommand는 RPC를 통해 DriverKit 확장(dext)에 노출됩니다. 해당 RPC 진입점의 커널 측 구현은 iokit/Kernel/IOUserServer.cpp의 _Impl 메서드입니다. dext는 그중 세 가지를 통해 DMA 버퍼를 구동합니다:

RPC 메서드줄 (xnu-12377.121.6)fInternalState->fDextLock을 보유하는가?
PrepareForDMA_Impl1009예 — IOLockLock @1033, unlock @1078
CompleteDMA_Impl1084예 — IOLockLock @1096, unlock @1118
PerformOperation_Impl1154아니오 — fActive와 fMemory를 잠금 없이 읽음

락은 존재합니다. IODMACommand::init이 이를 할당합니다 (iokit/Kernel/IODMACommand.cpp 342번째 줄). 세 형제 중 두 개는 이 락을 획득합니다. 세 번째는 획득하지 않으며 — 그리고 세 번째가 바로 공유 메모리 디스크립터를 역참조하는 쪽입니다. 이러한 비대칭이 취약점입니다.

xnu-12377.121.6(macOS 26.x, Apple이 소스를 공개한 최신 태그)은 여전히 잠금 없는 PerformOperation_Impl을 보여주므로 취약한 트리입니다. 수정 사항을 담은 26.6 소스 배포본은 아직 공개되지 않았습니다. 관련 소스는 analysis/IOUserServer_excerpt.cpp에 미러링되어 있습니다.

근본 원인

PerformOperation_Impl은 fActive에 대해 검사 시점(time-of-check)을 수행한 다음, 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은 락을 보유한 상태에서 해제(teardown)를 실행합니다:

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

clearMemoryDescriptor(true)(IODMACommand.cpp 455행)는 PerformOperation이 곧 접근하려는 대상을 실제로 해제하는 부분입니다:

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

따라서 위험한 인터리빙은 다음과 같다:

  1. PerformOperation_Impl이 명령이 여전히 활성 상태인 동안 if (!fActive)를 통과한다.
  2. CompleteDMA_Impl이 락을 획득하고, fActive를 소진한 뒤 fMemory.reset()을 수행하여 메모리 디스크립터를 해제하고, 그 와이어드 백킹이 해제/재사용되도록 한다.
  3. 여전히 실행 중인 PerformOperation_Impl이 getLength()에서 이제는 오래된 fMemory를 역참조한 다음 writeBytes()를 호출한다.

PerformOperation이 락을 전혀 획득하지 않았기 때문에, 2단계는 1단계와 3단계 사이의 틈에 끼어들 수 있다. writeBytes는 호출자가 제공한 바이트를 백킹이 이미 해제된 DMA 매핑에 복사한다 — 해당 페이지가 다른 커널 할당에 재사용되면, 이것이 바로 권고문이 경고하는 "커널 메모리 쓰기"이다. 대신 읽기 경로에서 이 상황이 발생하면 use-after-free 읽기 / 예기치 않은 종료가 발생한다.

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

취약한 macOS 없이 재현하기

실제 경로를 트리거하려면 취약한 빌드에서 Apple의 DriverKit entitlement가 적용된 서명된 DriverKit dext가 필요하며, 이는 Windows 호스트에서는 접근할 수 없습니다. 대신 poc/race_model.cpp는 세 메서드의 정확한 공유 상태 로직을 재구현합니다 — 동일한 잠금 규율, 동일한 check-then-free-then-use 순서 — 따라서 결함을 직접 관찰할 수 있습니다:

  • PrepareForDMA와 CompleteDMA는 뮤텍스를 획득하지만, PerformOperation은 획득하지 않습니다 (-DFIXED로 빌드하지 않는 한, 이 경우 누락된 잠금 하나가 추가됩니다).
  • CompleteDMA는 디스크립터를 해제하며, 이는 fMemory.reset()을 그대로 반영합니다.
  • 드라이버 하네스는 한 스레드에서 PerformOperation을, 다른 스레드에서 CompleteDMA를 실행하여, 원자적 신호(타이밍 전용 — 공유 상태에 대한 잠금이 아님)를 통해 teardown을 경쟁 윈도우 내부에 배치합니다.
cd poc
bash run.sh

취약한 빌드:

  • ThreadSanitizer가 데이터 레이스를 보고합니다 — CompleteDMA 내부의 operator delete가 PerformOperation 내부의 getLength() 읽기와 경쟁하며, 뮤텍스는 삭제자만 보유합니다. 전체 로그: evidence/tsan_vulnerable.txt.
  • AddressSanitizer가 힙 사용 후 해제(heap-use-after-free)를 보고합니다: CompleteDMA에서 해제된 객체가 PerformOperation::getLength에서 읽히며, PrepareForDMA에서 할당됩니다. 전체 로그: 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

고정 빌드(-DFIXED, PerformOperation에 추가된 잠금): 두 새니타이저 모두 깨끗하며 모든 작업이 teardown에 대해 올바르게 직렬화됩니다. 로그: evidence/tsan_fixed.txt, evidence/asan_fixed.txt.

이는 경쟁 조건이 로직상 실제로 존재하며 잠금이 필요충분 조건임을 입증합니다. 실제 커널 패닉은 아닙니다 — 아래 범위를 참조하세요.

수정

PerformOperation_Impl이 두 형제 함수가 이미 그러하듯 fActive 검사와 모든 fMemory 접근에 걸쳐 fInternalState->fDextLock을 보유하도록 만드세요. Apple의 26.6 소스는 아직 공개되지 않았으므로, analysis/patch.reconstructed.diff 는 권고문 텍스트와 형제 함수의 대칭성으로부터 재구성한 수정입니다. 공식 소스가 공개되면 IOUserServer.cpp를 xnu-12377.121.6과 diff하여 이를 확인(또는 교정)할 수 있습니다.

범위와 정직성

  • 패치된 XNU 소스는 작성 시점에 공개되어 있지 않습니다. diff는 현재 취약한 트리와 재구성된 수정 사이의 것이며, 권고문과 교차 검증되었습니다. 두 릴리스 태그 간의 소스 대 소스 diff가 아닙니다.
  • 재현은 새니타이저 환경에서의 충실한 로직 모델이며 익스플로잇이 아닙니다. 실제 커널 패닉 / 제어 가능한 쓰기는 취약한 Apple 빌드, DriverKit 엔타이틀먼트, 그리고 세 RPC와 경쟁하는 dext가 필요합니다 — 여기 사용된 호스트에서는 불가능합니다.
  • 하네스의 원자적 신호는 타이밍을 실제 경쟁 윈도우로 유도할 뿐입니다. 이를 제거해도 동일한 경쟁 조건은 여전히 존재하며, 단지 더 드물게 발생할 뿐입니다.

레이아웃

README.md                           this writeup
analysis/IOUserServer_excerpt.cpp   the three real methods (xnu-12377.121.6)
analysis/patch.reconstructed.diff   the inferred one-lock fix
poc/race_model.cpp                  faithful shared-state model (vuln + -DFIXED)
poc/Makefile  poc/run.sh            TSan/ASan build + A/B runner
evidence/*.txt                      captured sanitizer output

참고 자료

  • Apple 보안 릴리스: 128066, 128068
  • XNU 소스: apple-oss-distributions/xnu, 태그 xnu-12377.121.6
  • CWE-362
도구 다운로드