| Titolo | Thermalright TR-VISION HOME Software V2.0.5 Incorrect Default Permissions |
|---|
| Descrizione | Title:
Thermalright TR-VISION HOME WFanManager.sys sub_11504 IOCTL 0x9C406104 privilege escalation
Vendor:thermalright
Website:https://www.thermalright.com/
Product:TR-VISION HOME Software
Latest Version: V2.0.5
Download URL:https://download.thermalright.com/software/TR-VISION%20HOME%20V2.0.5-CHS.zip
Vulnerable Component Driver:WFanManager.sys
sha256:11bd2c9f9e2397c9a16e0990e4ed2cf0679498fe0fd418a3dfdac60b5c160ee5
version:x.x.x.x
Vulnerability Type:
CWE-1244: Internal Asset Exposed to Unsafe IOCTL in Kernel Mode
CWE-276: Incorrect Default Permissions
Description:
The kernel-mode driver WFanManager.sys shipped with TR-VISION HOME Software is a modified version of the well-known vulnerable WinRing0 driver.
The driver creates the device object `\\.\WinRing0_1_2_0` using `IoCreateDevice` without implementing any access control or permission checks on the requesting process. Any local user (including low-privileged users) can open a handle to this device and issue DeviceIoControl requests.
The driver exposes the IOCTL code `0x9C406104`, which implements an arbitrary physical memory read primitive. The handler (`sub_11504`) accepts a 16-byte input structure and maps the specified physical address range via `MmMapIoSpace` (MmNonCached), then copies the data back to user mode. Although a limited address-range check is performed (PhysicalAddress ≥ 0xC0000 and PhysicalAddress + size − 1 ≤ 0xFFFFF), this restriction is insufficient to prevent exploitation.
An attacker can leverage this unrestricted physical memory read capability to:
- Escalate privileges from a low-privileged user to SYSTEM
- Dump sensitive process memory (e.g., LSASS) to extract credentials
- Perform further kernel memory manipulation leading to full system compromise
Impact:
Local Privilege Escalation (LPE) to SYSTEM and credential dumping.
BinaryNinja Analysis:
```c++
000110d8 uint64_t sub_110d8(PDEVICE_OBJECT DeviceObject, IRP* Irp)
000110f3 char* CurrentStackLocation = Irp->Tail.Overlay...CurrentStackLocation
000110fa Irp->IoStatus.Information = 0
00011101 int32_t rbx = -0x3ffffffe
00011101
00011106 if (*CurrentStackLocation == 0)
000113e1 int32_t rax_19 = data_13110
000113e1
000113ec if (rax_19 == 0xffffffff)
000113f7 rbx = 0
000113ec else
000113f1 data_13110 = rax_19 + 1
000113f7 rbx = 0
00011106 else if (*CurrentStackLocation == 2)
000113d0 int32_t rax_17 = data_13110
000113d0
000113db if (rax_17 == 0xffffffff)
000113f7 rbx = 0
000113db else
000113f1 data_13110 = rax_17 - 1
000113f7 rbx = 0
0001110f else if (*CurrentStackLocation == 0xe)
0001111e int32_t IoctrlCode = *(CurrentStackLocation + 0x18)
0001112a int64_t rflags
0001112a
0001112a if (IoctrlCode u> 0x9c4060d4)
0001124e // 0x9C406104 : Read Physical Memory By MmMapIoSpace
0001124e if (IoctrlCode == 0x9c406104)
000113b4 void* SystemBuffer = Irp->AssociatedIrp.SystemBuffer
000113cc rbx = sub_11504(InputBuffer: SystemBuffer,
000113cc InputBufferLength: *(CurrentStackLocation + 0x10),
000113cc OutputBuffer: SystemBuffer,
000113cc OutputBufferLength: *(CurrentStackLocation + 8),
000113cc &Irp->IoStatus.Information)
...
00011504 int64_t sub_11504(int64_t* InputBuffer, int32_t InputBufferLength, int64_t OutputBuffer, int32_t OutputBufferLength, int32_t* arg5)
00011529 if (InputBufferLength == 0x10)
00011532 uint64_t rax_2 = zx.q(*(InputBuffer + 0xc) * InputBuffer[1].d)
00011532
00011538 if (OutputBufferLength u>= rax_2.d)
0001153e int64_t PhysicalAddress = *InputBuffer
0001153e
00011548 if (PhysicalAddress s>= 0xc0000)
0001154a uint64_t NumberOfBytes = zx.q(rax_2.d)
0001154a
00011557 if (PhysicalAddress + rax_2 - 1 s<= 0xfffff)
0001155f int64_t pMapping = MmMapIoSpace(PhysicalAddress, NumberOfBytes,
0001155f CacheType: MmNonCached)
00011565 int32_t AlignNumer = InputBuffer[1].d
00011568 int64_t r12
00011568 r12.b = 0 // Read
00011568
0001156e if (AlignNumer == 1)
000115a3 __builtin_memcpy(dest: OutputBuffer, src: pMapping,
000115a3 count: zx.q(*(InputBuffer + 0xc)))
0001156e else if (AlignNumer == 2)
00011595 __builtin_memcpy(dest: OutputBuffer, src: pMapping,
00011595 count: zx.q(*(InputBuffer + 0xc)) << 1)
00011573 else if (AlignNumer == 4)
00011588 __builtin_memcpy(dest: OutputBuffer, src: pMapping,
00011588 count: zx.q(*(InputBuffer + 0xc)) << 2)
00011578 else
0001157a r12.b = 1
0001157a
000115ab MmUnmapIoSpace(BaseAddress: pMapping, NumberOfBytes)
000115ab
000115b4 if (r12.b == 0)
000115bb *arg5 = OutputBufferLength
000115bd return 0
000115bd
000115c1 return 0xc000000d
```
|
|---|
| Utente | Element2023H (UID 99757) |
|---|
| Sottomissione | 17/10/2026 07:15 (26 giorni fa) |
|---|
| Moderazione | 11/11/2026 20:16 (26 days later) |
|---|
| Stato | Accettato |
|---|
| Voce VulDB | 435969 [rmalright TR-VISION HOME 2.0.5 IOCTL WFanManager.sys sub_11504 escalationi di privilegi] |
|---|
| Punti | 17 |
|---|