- Keyhole은 CLiP의 라이선스 검증 흐름을 우회해 Microsoft Store 앱과 최신 Windows 에디션용 라이선스를 만들 수 있게 했던 DRM 우회 버그임
- CLiP는 서명된 XML 라이선스를
clipsvc.dll에서 검증한 뒤SPLicenseBlock을clipsp.sys로 넘겨 커널에서 다시 확인하는 신뢰 체인을 사용함 clipup.exe에 XML 라이선스 서명용 ECDSA 키가 난독화 없이 들어 있어, 임의로 서명한 XML 라이선스를 ClipSvc가 받아들일 수 있었음- 실제 취약점은 라이선스 블록의 서명 블록 뒤 데이터가 검증되지 않는데도 같은 타입의 앞선 블록을 덮어쓸 수 있다는 점이며, device-locked Windows 라이선스에는 device-locked 앱 라이선스가 필요했음
- Cisco TALOS가 같은 버그를 2024년 4월 8일 Microsoft에 보고했고, 수정 후 파서는 서명 블록을 만나면 즉시 종료해 뒤따르는 블록을 처리하지 않음
Keyhole의 성격과 공개 배경
- Keyhole은 Windows 라이선스 검사 우회 작업 중 발견된 버그로, Microsoft Store 앱 또는 최신 Windows 에디션에 라이선스를 부여할 수 있게 했던 DRM 우회 방법임
- 일부 버그는 향후 활성화 방법이나 테스트 도구로 보존하기 위해 비공개로 유지됐지만, CVE-2024-38184가 Cisco TALOS를 통해 공개되면서 Keyhole 내용도 공개됨
- 이 버그는 Microsoft에 보고된 시기와 비슷한 때 독립적으로 발견됨
CLiP의 라이선스 처리 구조
- CLiP(Client Licensing Platform)는 Windows 10에서 도입된 시스템으로, 주로 Microsoft Store 앱 DRM을 구현하고 Windows 활성화와도 통합됨
- Windows 내 주요 구성요소는 다음과 같음
clipup.exe: Windows 8 Store 라이선스, 정품 티켓, 제품 키를 디지털 라이선스로 마이그레이션함clipsvc.dll: 앱 라이선스를 관리하는 사용자 모드 서비스clipc.dll: 애플리케이션이 CLiP와 상호작용하는 APIclipwinrt.dll: Windows Runtime을 쓰는 UWP 애플리케이션용 APIclipsp.sys: 라이선스를 검증하는 커널 모드 드라이버
- CLiP 라이선스 앱이 설치되면 서명된 XML 라이선스가
clipsvc.dll로 전달되고, XML 서명 검증 후 데이터가%PROGRAMDATA%\Microsoft\Windows\ClipSVC\tokens.dat에 저장됨 - 이후
SPLicenseBlock태그에서 서명된 라이선스 블록이 추출되어clipsp.sys로 전달되고, 검증을 거쳐 CLiP 라이선스 저장소HKLM\SYSTEM\CurrentControlSet\Control\{7746D80F-97E0-4E26-9543-26B41FC22F79}에 저장됨 - 이 저장소는 기본적으로 보이지 않도록 보호되지만, 권한을 바꾸면 접근할 수 있음
clipup.exe에 남아 있던 서명 키
clipup.exe에는 XML 라이선스 서명에 사용할 수 있는 유효한 ECDSA 키가 난독화 없이 저장돼 있었음- 이 키는 원래 Microsoft Store에 임시 라이선스를 보내 디지털 라이선스를 받는 용도로 쓰이지만, ClipSvc는 앱 라이선스에도 같은 키를 받아들였음
- 그 결과 임의의 XML 라이선스를 서명하거나 재서명할 수 있었고, ClipSvc의 사용자 모드 검사를 우회해 원하는 라이선스 블록을
clipsp.sys로 직접 넘길 수 있었음 - 이 단계에서 사용자 모드 수준의 신뢰 체인은 무력화되고, 남은 쟁점은 ClipSp를 속일 수 있는지였음
ClipSp 분석과 Warbird 난독화 해제
- ClipSp의 많은 코드는 Microsoft의 독자 난독화 도구인 Warbird로 숨겨져 있었음
- ClipSp는 난독화된 코드 호출을 복호화 함수와 암호화 함수로 감싸며, 사용자 모드 프로그램에서 Warbird가 동작하는 방식과 유사함
- Microsoft 서버에 있던
clipsp.sys심볼이 분석에 도움이 됐고, KiFilterFiberContext의 방법을 바탕으로 복호화 함수를 수동 실행해 숨겨진 코드를 확인할 수 있었음 - Warbird의 사용자 모드 동작은 warbird-docs에서 참고할 수 있음
라이선스 블록 형식과 Keyhole 버그
- CLiP에서 중요한 라이선스 정보는 라이선스 블록에 들어 있으며, 형식은 CikExtractor에 문서화돼 있음
- 라이선스 블록은 TLV(tag-length-value) 형식을 사용함
- 각 하위 블록은 데이터 타입, 데이터 길이, 실제 데이터를 가짐
- 예를 들어 타입
0xC9는 License Information, 길이0xA는 10바이트 데이터를 뜻함
- 라이선스 블록 끝에는 항상 타입
0xCC의 서명 블록이 있으며, 이 블록은 앞의 모든 데이터 서명과 서명에 사용된 키 정보를 담음 - 실험 결과 서명 블록 뒤에 붙은 데이터는 검증되지 않았고, 같은 타입의 블록이 여러 개 있으면 마지막 블록이 앞선 블록을 덮어썼음
- 따라서 서명 블록 뒤에 새 라이선스 데이터를 붙이면 기존 라이선스 정보를 바꿀 수 있었고, 이 방식이 Keyhole로 명명됨
가능한 범위와 제약
- 이 방법은 Microsoft Store에서 판매되는 항목의 라이선스를 다른 Microsoft Store 라이선스에서 만들 수 있게 했음
- 무료 앱에도 라이선스가 많기 때문에 원하는 항목용 라이선스를 다수 만들 수 있는 상태였음
- 단, device-locked 라이선스는 device-unlocked 라이선스에서 만들 수 없었음
- Windows 디지털 라이선스는 device-locked이므로, Windows 라이선스를 만들려면 Roblox 같은 device-locked 앱 라이선스가 필요했음
- 이를 통해 Enterprise LTSC를 디지털 라이선스로 활성화하거나, generic key로 정상 KMS 서버를 활성화하는 등 이전에는 불가능했던 작업도 가능했음
공개된 재현 흐름과 수정 방식
- Windows 라이선스를 만드는 흐름은 device-locked 앱 설치,
https://licensing.mp.microsoft.com/v7.0/licenses/content에서 오는 라이선스 가로채기, 라이선스 디코딩과 블록 추출, 새 데이터 추가, XML 패키징과 서명,C:\ProgramData\Microsoft\Windows\ClipSVC\Install\Migration에 복사, ClipSvc 재시작 또는clipup -p실행으로 이어짐 - Cisco TALOS의 TALOS-2024-1964는 같은 버그를 Microsoft에 2024년 4월 8일 보고했음
- 이 버그는 단순 DRM 문제처럼 보일 수 있지만, Keyhole이 ClipSp의 더 심각한 버그로 들어가는 진입점이 될 수 있어 TALOS 공개 범위에 포함됨
- 수정된 라이선스 블록 파서는 서명 블록을 만나면 즉시 종료해 서명 뒤 블록을 처리하지 않으며, 이 변경으로 Keyhole이 막힘
공개 자료와 Xbox One과의 관계
- Keyhole 공개 후 Keyhole 라이선스 생성 코드와 분석을 돕기 위한 심볼 포함 CLiP 바이너리 모음이 공개됨
- ClipSp의 코드 상당 부분은 Xbox One DRM 시스템에서 복사된 것으로 파악됨
- Xbox One에는 최신 PC의 TPM에 기반한 SP, 즉 secure processor 칩이 있으며, 주요 역할은 코드 서명 강제와 라이선스 검증임
- CLiP의 XML 라이선스 형식과 TLV 기반 라이선스 블록 대부분은 Xbox One DRM 시스템에서 가져온 형태임
- Xbox SP에도 ClipSp와 같은 파싱 버그가 있지만, 데이터 블록과 서명 관련 블록을 따로 파싱하기 때문에 Keyhole은 Xbox에서 동작하지 않음