
Razer Lycosa.sys의 두 가지 커널 취약점(CWE-125 메모리 노출 + CWE-121 스택 오버플로)을 연계한 로컬 권한 상승. Windows 11에서 검증된 조정된 공개 자료.
https://github.com/416rehman/DeepZero 를 통해 발견됨
공급업체: Razer Inc.
구성 요소: Lycosa.sys, Razer Lycosa 키보드 필터 드라이버, x64
SHA-256: a120a6184ab16864e8a5f1dfd0cd178fca541de463b5cef946e18c34b9b6f716
보고자 참조: a120a6184ab16864
상태: 아직 공급업체에 보고되지 않음.
이 디렉터리는 동일한 드라이버의 동일한 루틴에서 발견된 두 개의 서로 다른 결함을 보고합니다. 이들은 각각 별개의 근본 원인과 별개의 수정 사항을 가지므로, 각각 독립적인 폴더를 가지고 있으며 각자의 식별자로 추적 및 할당될 수 있습니다:
| CVE | 결함 | 유형 | 결과 |
|---|---|---|---|
| CVE-01 | 출력 길이가 버퍼에 대해 검사되지 않아 드라이버가 커널 스택 메모리를 반환함 | CWE-125 범위를 벗어난 읽기 | 커널 메모리 노출, 주소 공간 배치 무작위화 무력화 |
| CVE-02 | 입력 길이가 버퍼에 대해 검사되지 않아 드라이버가 자체 반환 주소를 덮어씀 | CWE-121 스택 버퍼 오버플로 | 임의 커널 코드 실행 |
두 결함 모두 로그인하여 프로그램을 실행할 수 있는 모든 계정에서 도달 가능합니다. 관리자 권한도, 권한 상승도, 특별한 권한도 필요하지 않습니다. 두 결함 모두 코드 무결성이 적용되고 테스트 서명이 꺼진 상태의 Windows 11 25H2 (빌드 26200.8875)에서 확인되었습니다.
섹션 3에서는 두 결함을 함께 사용할 때 무엇을 의미하는지 설명합니다. 이것이 두 결함을 동시에 보고하는 이유이며, 연쇄 개념 증명이 이 루트 디렉터리에 있는 이유입니다.
두 결함 모두 RVA 0x1270의 IRP_MJ_DEVICE_CONTROL 핸들러에 있으며, 둘 다 커널 스택의 동일한 0x400바이트 버퍼에 작용합니다. 배포된 바이너리에서 읽은 프롤로그는 두 결함 모두에 대해 구조를 확정합니다:
Lycosa+0x1270 48 89 54 24 10 mov [rsp+10h], rdx ; Irp
Lycosa+0x1275 48 89 4c 24 08 mov [rsp+8], rcx ; DeviceObject
Lycosa+0x127a 48 81 ec 98 04 00 00 sub rsp, 498h ; the frame
Lycosa+0x1291 ba 00 04 00 00 mov edx, 400h ; the buffer size
Lycosa+0x1296 48 8d 8c 24 80 00 00 00 lea rcx, [rsp+80h] ; the buffer
0x498바이트 프레임 내부의 rsp+0x80에 있는 0x400바이트 버퍼이며, 비휘발성 레지스터는 저장되지 않습니다. 버퍼 시작부터 계산하면:
0x000 .. 0x3FF the buffer, which both defects are supposed to stay inside
0x418 the return address of the dispatch routine
0x420 the saved DeviceObject argument
0x428 the saved Irp argument
0x418은 0x498 - 0x80입니다. 노출(CVE-01)은 0x3FF를 넘어 읽고 발견한 것을 반환하며, 오버플로(CVE-02)는 0x3FF를 넘어 쓰고 그것을 대체합니다.
DriverEntry는 보안 설명자 없이 장치를 생성하고 이에 대한 심볼릭 링크를 게시하므로, \\.\Lycosa에서 도달 가능합니다:
IoCreateDevice(param_1, 0x20, L"\\Device\\Lycosa", 0x22, 0, 0, &device);
IoCreateSymbolicLink(L"\\DosDevices\\Lycosa", L"\\Device\\Lycosa");
영향을 받는 모든 컨트롤 코드는 FILE_DEVICE_UNKNOWN, METHOD_BUFFERED, FILE_ANY_ACCESS로 디코딩됩니다. FILE_ANY_ACCESS는 핸들에 특정 액세스 권한이 있어야 함을 의미하지 않으므로, 장치 객체의 보안 설명자가 유일한 관문이며, 이는 모든 사람에게 액세스를 허용합니다.
이 보고서의 모든 결과는 내장 Users 그룹만이 유일한 그룹 멤버십인 표준 사용자 계정에서 생성되었습니다. 해당 계정은 관리자 권한이 없었고, 권한 상승되지 않았으며, 기본값을 넘어서는 어떤 권한도 보유하지 않았습니다.
이 드라이버는 또한 패키지가 유효하게 카탈로그 서명되어 있기 때문에 Razer 하드웨어가 한 번도 연결된 적 없는 머신에서도 로드됩니다. 이것이 바로 취약한 드라이버 직접 가져오기(bring-your-own-vulnerable-driver) 공격에 사용되는 패턴입니다.
별개의 결함이므로 별도로 보고되지만, 이를 분류하는 공급업체는 각 결함이 다른 결함을 악화시킨다는 점을 알아야 합니다.
최신 Windows는 커널을 무작위 주소에 로드합니다. 반환 주소를 덮어쓸 수 있는 공격자라도 무엇으로 덮어쓸지는 알아야 하며, 이것이 일반적으로 장애물입니다. 이 드라이버는 두 질문 모두에 스스로 답합니다:
CVE-01이 무작위화를 제거합니다. 노출은 디스패치 루틴 자체의 반환 주소, 즉 ntoskrnl.exe 내부의 코드 주소를 반환합니다. 이미지 내에서 알려진 오프셋을 빼면 커널이 로드된 베이스를 얻을 수 있고, 거기서부터 커널 내부의 모든 주소를 알 수 있습니다. 이는 아무런 비용도 들지 않고 아무것도 방해하지 않습니다.
CVE-01은 또한 CVE-02가 폴트를 일으키지 않기 위해 필요한 값을 제공합니다. CVE-02 섹션 4.4에 설명된 대로, 드라이버는 나가는 길에 오프셋 0x428에서 Irp를 다시 로드하고 이를 통해 씁니다. 반환 주소에 도달하는 순진한 오버플로는 그 포인터도 파괴하여 루틴이 반환하기 전에 폴트를 일으킵니다. 대신 신뢰할 수 있는 익스플로잇은 복사를 정확히 0x428에서 멈추어 현재 요청의 살아있는 Irp를 그대로 두므로, 드라이버가 정상적으로 완료됩니다.
그런 다음 CVE-02가 실행을 리디렉션합니다, 커널 베이스가 이미 알려진 상태에서.
비권한 계정에서 연쇄 개념 증명은 프레임을 읽고, 커널 베이스와 버퍼 자체의 커널 주소를 계산하고, 반환 지향 체인을 전송합니다:
step 1, read what is above the buffer on the kernel stack:
+0x418 return address 0xFFFFF807D565CABB
+0x498 frame pointer 0xFFFFFD042D313750 (read twice, must match)
step 2, turn those into the two addresses the payload needs:
kernel base = 0xFFFFF807D565CABB - 0x25CABB = 0xFFFFF807D5400000
buffer on stack = 0xFFFFFD042D313750 - 0x500 = 0xFFFFFD042D313250
step 4, overflow with a chain that:
pivots the stack onto the buffer, calls nt!ZwCreateFile, and
resumes nt!IopfCallDriver+0x5b
sending 0x428 bytes
call returned: accepted=true error=0
PROOF: C:\Windows\System32\dz_lycosa_kernel_exec.txt now exists.
이것이 완전한 체인이며, 처음부터 끝까지 검증되었습니다. 비권한 계정은 커널 모드에서 nt!ZwCreateFile을 실행하여, 평소에는 쓰기 액세스가 거부되는 디렉터리인 C:\Windows\System32 아래에 파일을 생성했습니다. accepted=true는 시스템 호출이 정상적으로 반환되었음을 의미합니다: 체인은 드라이버가 반환하려던 정확한 주소(nt!IopfCallDriver+0x5b, 즉 add rsp,0x38 ; ret)를 재개하므로, 스레드가 종료되고 머신은 계속 실행됩니다. 생성된 파일은 관리자 셸에서 독립적으로 확인되었습니다. 전체 기록은 logs/exec_create_file.log에 있으며, 방법은 METHODOLOGY.md에 있습니다.
실질적인 해석은 이 하나의 드라이버가 머신의 모든 사용자에게, 메모리 안전 결함을 커널 코드 실행으로 바꾸는 데 일반적으로 필요한 것의 양쪽 절반, 즉 무작위화를 제거하는 주소 노출과 이를 사용하는 제어 흐름 하이재킹을 모두 제공한다는 것입니다. 이 둘을 함께 사용하면 머신이 계속 실행되는 상태에서 구체적인 권한 있는 작업을 얻을 수 있음이 입증되었습니다.
두 수정 사항은 독립적이며 둘 다 작으며, 각 보고서에 전체가 명시되어 있습니다:
OutputBufferLength를 제한하고, IoStatus.Information을 실제로 생성된 값으로 설정합니다.InputBufferLength를 제한합니다.두 보고서는 또한 IoCreateDeviceSecure와 이를 관리자 및 시스템으로 제한하는 SDDL 문자열로 제어 장치를 생성할 것을 권장합니다. 그것만으로는 어느 결함도 수정되지 않지만, 두 결함에 심각도를 부여하는 비권한 도달을 제거할 것입니다.
중복 보고는 공급업체의 시간을 낭비하므로 작성 전에 확인했습니다:
https://aka.ms/VulnerableDriverBlockList에서 다운로드하여 1,713개의 거부 규칙 전체를 검색. 이 파일은 나타나지 않음. 해당 목록에 있는 유일한 Razer 드라이버는 다른 구성 요소인 Rzpnk.sys입니다.두 결함 모두 이전에 보고되지 않았다고 믿으며 정정을 환영합니다.
동일한 패키지 디렉터리에 포함된 여러 다른 드라이버가 이 드라이버의 전반적인 형태를 공유하며 별도로 조사됩니다. 여기에 있는 어떤 것도 그들에 대한 진술이 아닙니다.
pnputil /add-driver Flter2K.inf /install
sc create lycosa_test type= kernel binPath= C:\path\to\Lycosa.sys start= demand
sc start lycosa_test
각 결함은 해당 폴더에 단일 목적의 개념 증명을 가지고 있으며, 이 루트에는 이를 결합한 연쇄형이 있습니다:
# CVE-01, reads only, safe to run anywhere, quickest confirmation of the report
rustc -O CVE-01-kernel-memory-disclosure/poc/lycosa_disclosure.rs -o disc.exe
disc.exe
# CVE-02, stops the machine by design
rustc -O CVE-02-kernel-stack-overflow/poc/lycosa_overflow.rs -o ovf.exe
ovf.exe --yes-crash-this-machine
# the chain: CVE-01 + CVE-02 into a file created in System32, machine left running
rustc -O poc/lycosa_chain.rs -o chain.exe
chain.exe --exec # default target under System32
chain.exe --exec C:\Users\Public\proof.txt # or any path you choose
모든 것을 표준 사용자 계정에서 실행하십시오. 연쇄 PoC는 의존하는 두 드라이버 상수(FRAME과 BUF_AT)를 소스 상단에 명시하므로, 그 두 숫자를 변경하여 다른 드라이버 빌드를 대상으로 지정할 수 있습니다. --exec 모드가 사용하는 커널 오프셋은 특정 Windows 빌드에 한정됩니다; 프로그램은 런타임에 파생된 커널 베이스를 확인하며, --calibrate 모드는 빌드 간에 변경되는 하나의 값을 보고합니다.
README.md this overview and the chaining analysis
METHODOLOGY.md how both were found and confirmed, in order
poc/lycosa_chain.rs the CHAINED proof of concept (both defects)
evidence/ the binary, its package, decompiled sources, dumps
logs/exec_create_file.log transcript of the chained run in section 3
CVE-01-kernel-memory-disclosure/ standalone disclosure for the out-of-bounds read
README.md, poc/lycosa_disclosure.rs, evidence/, logs/
CVE-02-kernel-stack-overflow/ standalone disclosure for the stack overflow
README.md, poc/lycosa_overflow.rs, evidence/, logs/