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

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

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

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2024-38063 — CVE-2024-38063(tcpip.sys의 RCE)에 대한 PoC | Kitploit
도구/GitHubGitHub/ynwarcs/cve-2024-38063
Vulnerability AnalysisExploitationFuzzingNetwork SecurityPayload DevelopmentBinary Exploitation
GitHubynwarcs/cve-2024-38063

CVE-2024-38063

CVE-2024-38063(tcpip.sys의 RCE)에 대한 PoC

저장소 보기
694123242년 전Kitploit 검토 완료

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

이것은 CVE-2024-38063에 대한 (약간 불안정한) PoC입니다. 이 취약점은 2024년 8월 13일에 패치된 tcpip.sys의 RCE입니다. 저는 이 취약점을 발견하거나 보고하지 않았습니다. 발견하고 보고한 사람은 Wei입니다.

요구 사항

pip3 install scapy

사용법

스크립트의 다음 필드를 수정하세요:

  • iface <- 어댑터가 여러 개인 경우 패킷을 보내는 데 사용할 어댑터를 선택해야 합니다. 예: Linux의 "eth0" 또는 Windows의 "Hyper-V Virtual Ethernet Adapter". 기본 인터페이스를 사용하려면 비워 두세요.
  • ip_addr <- 대상 시스템의 IP 주소 (IPv6)
  • num_tries & num_batches <- 보낼 서로 다른 패킷 배치의 수. 더 많을수록 더 많은 힙 손상이 발생하고 취약점이 트리거될 확률이 높아집니다.
  • mac_addr <- scapy가 MAC 주소를 찾을 수 없다고 불평하지 않는 한 비워 두세요. 아래 문제 해결 섹션을 참조하세요.

스크립트를 실행하세요:

python3 cve-2024-38063.py

취약점을 재현하는 가장 쉬운 방법은 대상 시스템에서 bcdedit /set debug on을 사용하고 머신/VM을 재시작하는 것입니다. 이렇게 하면 기본 네트워크 어댑터 드라이버가 kdnic.sys가 되며, 이 드라이버는 패킷 병합을 매우 잘 수행합니다. 다른 설정에서 취약점을 재현하려면 시스템이 보낸 패킷을 병합할 수 있는 상태가 되도록 해야 합니다. 자세한 내용은 아래의 문제 해결 섹션을 읽어보세요.

데모

cve-2024-38063.webm

대략적인 RCA

기술적 세부 사항에 관심이 있다면 Marcus가 작성한 이 훌륭한 취약점 분석을 읽어보세요. 아래에 작성한 내용은 엄밀한 기술 분석이라기보다는 요약을 위한 것입니다.

  • 특정 상황에서 Windows는 여러 IP 패킷을 함께 병합하여 일괄 처리합니다. 각 패킷의 확장 헤더를 먼저 처리한 다음 각 패킷의 데이터를 처리합니다.
  • 확장 헤더 처리 중에 병합된 패킷들의 패킷 객체는 연결 리스트로 서로 연결됩니다. 각 패킷 객체에는 버퍼링된 패킷 데이터를 포함하는 NET_BUFFER 객체가 들어 있습니다. 오프셋 0x30에는 패킷이 얼마나 파싱되었는지를 나타내는 현재-오프셋 필드도 있습니다. 이 단계에서 오프셋 값은 일반적으로 0x28이며, IPv6 헤더가 파싱되었지만 그 외에는 아무것도 파싱되지 않았음을 나타냅니다.
  • tcpip!Ipv6pReceiveDestinationOptions에서 "destination options" 확장 헤더를 처리할 때 파싱 오류가 발생하면 tcpip!IppSendErrorList가 호출됩니다. 이 함수는 연결 리스트의 각 패킷 객체에 대해 (현재 객체부터 시작하여) tcpip!IppSendError를 호출합니다.
  • 특정 조건(예: 패킷이 유니캐스트인 경우)에서 tcpip!IppSendError는 부작용이 있습니다. 버퍼링된 패킷 데이터를 시작 지점으로 "되돌리고" 현재-오프셋 필드를 0으로 재설정합니다.
  • 그러나 이 전체 이벤트 체인에서 첫 번째 패킷만 오류가 있는 것으로 표시됩니다(오프셋 0x8C). 이는 드라이버가 IppSendError에서 "되돌려진" 다른 패킷들의 확장 헤더를 계속 파싱한다는 것을 의미합니다.
  • 되돌려진 패킷들의 처리는 예상치 못한 데이터로 수행됩니다. 버퍼링된 패킷 데이터는 확장 헤더가 아닌 패킷의 시작 부분(즉, IPv6 헤더)을 가리키고, 오프셋 필드 값은 0x28이 아니라 0입니다.

전략

  • 취약점을 악용하기 위해 Ipv6pReceiveFragment를 사용합니다. 이 함수는 프래그먼트 확장 헤더를 파싱하며, 현재 오프셋 값에서 0x30을 빼서 패킷의 비-헤더 데이터 길이를 계산할 때 패킷의 오프셋 필드가 최소 0x28이라고 가정합니다. 그런 다음 이 값은 단편화된 패킷을 재조립하는 역할을 하는 재조립 객체에 저장됩니다.
  • 우리의 경우 이 함수는 IppSendError에 의해 되돌려진 패킷에 대해 호출됩니다. 오프셋 값은 0이며 Ipv6pReceiveFragment의 앞부분 어딘가에서 8로 증가합니다. 비-헤더 데이터 크기를 계산할 때 값이 언더플로우하여 0xffd8이 됩니다(뺄셈은 16비트로 수행됩니다).
  • 길이 값은 이후 두 곳에서만 사용됩니다.
    • Ipv6pReassembleDatagram에서는 재조립된 패킷의 출력 버퍼 길이를 계산하는 데 사용됩니다. 그러나 모든 계산은 32비트로 수행되며 총 길이가 0xFFFF를 초과하지 않는지 확인하는 검사가 있습니다. 이 경우에는 검사를 통과합니다.
    • Ipv6pReassemblyTimeout에서도 동일한 방식으로 사용됩니다. 그러나 여기서 계산은 16비트로 수행되며 정수 오버플로가 발생합니다. 이로 인해 나중에 데이터를 버퍼로 복사할 때 버퍼 오버플로가 발생합니다.

Ipv6pReassemblyTimeout을 트리거하려면 프래그먼트의 송신자가 1분 동안 비활성 상태여야 합니다. 따라서 우리의 전략은 다음과 같습니다.

  • IppSendError를 트리거하기 위해 잘못된 형태의 destination options를 보낸 다음, 프래그먼트 패킷을 보냅니다.
  • 두 패킷이 병합되고 두 번째 패킷의 객체 데이터와 오프셋이 재설정되기를 기대합니다.
  • Ipv6pReceiveFragment에서 언더플로우를 발생시키고, 높은 16비트 값을 갖는 프래그먼트 데이터 길이로 새 재조립 객체를 만듭니다.
  • 더 이상 패킷을 보내지 않고 1분을 기다려 Ipv6pReassemblyTimeout이 트리거되게 합니다.
  • Ipv6pReassemblyTimeout의 버퍼 크기 계산에서 정수 오버플로를 발생시켜 힙 기반 버퍼 오버플로를 트리거합니다.

스크립트의 패킷은 병합될 확률을 높이기 위해 대량으로 전송됩니다. 주요 페이로드는 매우 간단합니다.

  • 파싱 오류를 트리거하는 잘못된 형식의 options 데이터가 포함된 "destination options" 확장 헤더를 가진 IPv6 패킷
  • 첫 번째 패킷에 연결되기를 기대하는 IPv6 프래그먼트 #1
  • IPv6 프래그먼트 #2(동일한 id)는 처음 두 개에 연결될 수도 있지만, 주요 목적은 두 번째 프래그먼트를 완성하여 정상적인 처리가 발생할 경우 오류가 발생하지 않도록 하는 것입니다.

또한 IPv6 헤더의 hop limit 및 flow label 필드를 수동으로 설정합니다. 취약점 때문에 버퍼링된 패킷 데이터가 재설정된다는 점을 기억하세요. 즉, 프래그먼트 패킷을 처리할 때 IPv6 헤더가 프래그먼트 헤더 데이터로 해석됩니다. IPv6 헤더의 hop limit 필드는 프래그먼트 헤더의 id 필드의 비트 중 하나로 해석됩니다. 이를 변경함으로써 여러 다른 프래그먼트에 대해 취약점을 트리거하고 여러 다른 손상을 일으켜 충돌 확률을 높입니다(어차피 PoC이므로). IP 헤더의 flow label 필드는 프래그먼트 헤더의 오프셋 및 "more indicators" 필드로 해석됩니다. 이 값을 1로 설정하면 이후에 더 많은 헤더가 온다는 것(따라서 나중에 Ipv6pReassemblyTimeout을 트리거할 수 있음)과 오프셋이 0임을 나타냅니다(이 id를 가진 첫 번째 패킷이 도착했기 때문).

참고

  • 위 내용은 취약점을 트리거하여 발생하는 문제를 악용하는 하나의 전략일 뿐입니다. 저는 이 전략이 매우 간단해서 사용했으며, 다른 가능성을 조사하는 데 시간을 낭비하고 싶지 않았습니다. 곧 다른 사람들이 훨씬 더 나은 전략을 내놓아도 놀라지 않을 것입니다.
  • 취약점에 필요한 것:
    • 대상 시스템의 IPv6 지원 및 패킷 수신 능력(방화벽 이전)
    • 대상 시스템이 보낸 패킷을 어느 정도 병합하도록 만드는 능력. 일부 어댑터 + 드라이버 조합은 이를 매우 잘 수행하지만, 다른 조합은 더 주저하는 것 같습니다. 어댑터나 네트워크 상태와 관계없이 Windows RSC가 패킷을 병합하도록 만드는 트릭이나 특수 패킷 체인이 있을 수 있지만, 이에 대한 증거는 없습니다.
  • 취약점에 필요하지 않은 것:
    • 패킷 대량 전송. PoC는 병합 확률을 높이고 여러 손상을 트리거하는 데모를 위해 그렇게 할 뿐입니다.
    • 대상 시스템의 과부하 상황. 병합은 다양한 상황에서 발생할 수 있기 때문입니다.
    • IPv6 활성화 외에 대상 시스템의 특정 설정.
    • (아마도) 1분을 기다려 손상을 트리거하는 것. 저는 이 취약점 악용 전략이 가장 단순해서 사용했을 뿐입니다. 취약점으로 인해 발생하는 문제 상황이 더 직접적인 방식으로 악용될 가능성은 매우 높습니다.
    • (아마도) 유니캐스트 패킷. Ipv6pReassemblyTimeout에서 사용하는 코드 경로가 원래 프래그먼트 패킷이 유니캐스트로 전송되어야 하기 때문에 유니캐스트를 사용합니다.

문제 해결

작동하지 않는 경우 원인은 다음과 같을 수 있습니다.

  • IPv6로 대상 시스템에 도달할 수 없는 경우:
    • Windows 방화벽을 비활성화하세요
    • 호스트 PC에서 ping -6 {ipv6_address} 실행
    • 응답이 오는지 확인하세요
    • 방화벽을 다시 활성화하세요
  • 대상 시스템이 패킷을 수신하지 못하는 경우
    • 대상 시스템에 wireshark를 설치하고 스크립트가 보낸 패킷이 도착하는지 확인하세요
  • scapy가 "Mac address to reach destination not found. Using broadcast."라고 보고하는 경우
    • 대상 머신의 MAC 주소를 찾아야 합니다
    • 위의 ping 명령을 실행하고 wireshark에서 응답(eth 소스 주소 필드)을 확인하면 됩니다
    • scapy를 사용할 수도 있습니다: Ether(raw(sr1(IPv6(dst={your_dest_ip})/ICMPv6EchoRequest()))).src, 하지만 이 방법은 때때로 작동하지 않습니다
    • MAC 주소를 얻으면 스크립트의 mac_addr 필드에 넣고 스크립트를 실행하세요
  • 대상 시스템에서 패킷이 병합되지 않는 경우
    • 어댑터/드라이버에 따라 대상에 DDoS처럼 패킷을 플러딩하지 않고는 Windows가 패킷을 병합하도록 만들기 어려울 수 있습니다.
    • 사용 가능한 설정에 따라 "Packet Coalescing", "Interrupt Moderation", "Interrupt Moderation Mode", "Recv Segment Coalescing" 같은 어댑터 설정을 변경해 볼 수 있습니다. 예를 들어 제 전용 서버에서 "Interrupt Moderation Mode"를 "Extreme"으로 설정하면 취약점을 재현할 수 있습니다.
  • 다른 모든 방법이 실패하면 커널 디버거를 연결하여 몇 가지를 확인할 수 있습니다:
    • tcpip!Ipv6pReceiveDestinationOptions -> tcpip!Ipv6pProcessOptions -> tcpip!IppSendErrorList가 호출되는가?
    • tcpip!Ipv6pProcessOptions에 중단점을 설정하고 [rcx]가 항상 0인지 확인하세요. 그렇다면 어떤 이유로 패킷이 병합되지 않는 것입니다.
    • tcpip!Ipv6pReceiveFragment에 중단점을 설정하고 [rcx+0x30]이 0인지 확인하세요. 그렇지 않다면 어떤 이유로 취약점 트리거에 실패한 것입니다.
도구 다운로드