[Bug 49165] VeraCrypt 1.24 filter driver 'veracrypt_x64.sys' crashes in entry point ('IoGetDeviceObjectPointer' must not return a stub device if the device object doesn't exist)

WineHQ Bugzilla wine-bugs at winehq.org
Sun May 17 04:09:47 CDT 2020


https://bugs.winehq.org/show_bug.cgi?id=49165

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |focht at gmx.net
            Summary|Crash when trying to open   |VeraCrypt 1.24 filter
                   |Veracrypt                   |driver 'veracrypt_x64.sys'
                   |                            |crashes in entry point
                   |                            |('IoGetDeviceObjectPointer'
                   |                            |must not return a stub
                   |                            |device if the device object
                   |                            |doesn't exist)
          Component|-unknown                    |ntoskrnl

--- Comment #2 from Anastasius Focht <focht at gmx.net> ---
Hello folks,

confirming.

https://web.archive.org/web/20200319114317/https://launchpadlibrarian.net/468657862/VeraCrypt%20Portable%201.24-Update6.exe

Trace log:

--- snip ---
$ WINEDEBUG=+seh,+relay,+ntoskrnl wine ./VeraCrypt.exe >>log.txt 2>&1
...
00ec:Call driver init 0000000000D57600
(obj=00000000000FBC70,str=L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\veracrypt") 
...
00ec:Call ntoskrnl.exe.MmGetSystemRoutineAddress(00b5f740) ret=00d5718a
...
00ec:fixme:ntoskrnl:MmGetSystemRoutineAddress L"KeQueryActiveProcessorCountEx"
not found
00ec:Ret  ntoskrnl.exe.MmGetSystemRoutineAddress() retval=00000000 ret=00d5718a
00ec:trace:seh:raise_exception code=c0000096 flags=0 addr=0xc8a983 ip=c8a983
tid=00ec
00ec:trace:seh:raise_exception  rax=0000000000b5f6b8 rbx=0000000000d57600
rcx=0000000000d577d0 rdx=0000000000222004
00ec:trace:seh:raise_exception  rsi=0000000000000000 rdi=0000000000d577d0
rbp=0000000000b5f669 rsp=0000000000b5f5b0
00ec:trace:seh:raise_exception   r8=0000000000000000  r9=0000000000000000
r10=0000000000000000 r11=0000000000000000
00ec:trace:seh:raise_exception  r12=0000000000000000 r13=0000000000222004
r14=0000000000000001 r15=0000000000000000
00ec:trace:seh:call_vectored_handlers calling handler at 0x22cf50 code=c0000096
flags=0
00ec:trace:seh:call_vectored_handlers handler at 0x22cf50 returned ffffffff
00ec:Call ntoskrnl.exe.RtlInitUnicodeString(00b5f660,00d577d0
L"\\Device\\VeraCrypt") ret=00c8a9b2
00ec:Call ntdll.RtlInitUnicodeString(00b5f660,00d577d0 L"\\Device\\VeraCrypt")
ret=7bca1eff
00ec:Ret  ntdll.RtlInitUnicodeString() retval=00000024 ret=7bca1eff
00ec:Ret  ntoskrnl.exe.RtlInitUnicodeString() retval=00000024 ret=00c8a9b2
00ec:Call
ntoskrnl.exe.IoGetDeviceObjectPointer(00b5f660,00000080,00b5f600,00b5f608)
ret=00c8a9c9
00ec:Call KERNEL32.IsBadStringPtrW(00d577d0,00000011) ret=00235647
00ec:Ret  KERNEL32.IsBadStringPtrW() retval=00000000 ret=00235647
00ec:fixme:ntoskrnl:IoGetDeviceObjectPointer stub: L"\\Device\\VeraCrypt" 80
0000000000B5F600 0000000000B5F608
00ec:Ret  ntoskrnl.exe.IoGetDeviceObjectPointer() retval=00000000 ret=00c8a9c9
00ec:Call ntoskrnl.exe.KeInitializeEvent(00b5f670,00000000,00000000)
ret=00c8a9e0
00ec:trace:ntoskrnl:KeInitializeEvent event 0000000000B5F670, type 0, state 0.
00ec:Ret  ntoskrnl.exe.KeInitializeEvent() retval=00000029 ret=00c8a9e0
00ec:Call
ntoskrnl.exe.IoBuildDeviceIoControlRequest(00222004,00259578,00000000,00000000,00b5f718,00000004,00000000,00b5f670,00b5f688)
ret=00c8aa1a
00ec:trace:ntoskrnl:IoBuildDeviceIoControlRequest 222004, 0000000000259578,
0000000000000000, 0, 0000000000B5F718, 4, 0, 0000000000B5F670, 0000000000B5F688
00ec:trace:ntoskrnl:IoAllocateIrp -128, 0
00ec:Call ntdll.RtlAllocateHeap(008e0000,00000000,00000310) ret=0022f10d
00ec:Ret  ntdll.RtlAllocateHeap() retval=008e0330 ret=0022f10d
00ec:trace:ntoskrnl:ExAllocatePoolWithTag 784 pool 0 -> 00000000008E0330
00ec:trace:ntoskrnl:IoInitializeIrp 00000000008E0330, 784, -128
00ec:Call msvcrt.memset(008e0330,00000000,00000310) ret=0022f1a7
00ec:Ret  msvcrt.memset() retval=008e0330 ret=0022f1a7
00ec:trace:seh:raise_exception code=c0000005 flags=0 addr=0x22f9b8 ip=22f9b8
tid=00ec
00ec:trace:seh:raise_exception  info[0]=0000000000000001
00ec:trace:seh:raise_exception  info[1]=00000000008ddfb8
00ec:trace:seh:raise_exception  rax=00000000008de000 rbx=0000000000222004
rcx=00007f2d1af1da0e rdx=0000000000000037
00ec:trace:seh:raise_exception  rsi=00000000008e0330 rdi=0000000000000000
rbp=0000000000000000 rsp=0000000000b5f470
00ec:trace:seh:raise_exception   r8=0000000000000000  r9=0000000000b5ec02
r10=0000000000000000 r11=0000000000000000
00ec:trace:seh:raise_exception  r12=0000000000b5f718 r13=0000000000000004
r14=0000000000000000 r15=0000000000b5f688
00ec:trace:seh:call_vectored_handlers calling handler at 0x22cf50 code=c0000005
flags=0
00ec:trace:seh:call_vectored_handlers handler at 0x22cf50 returned 0 
...
--- snip ---

The driver is open source so it's rather boring.

https://www.veracrypt.fr/code/VeraCrypt/tree/src/Driver/Ntdriver.c?h=VeraCrypt_1.24-Update6

--- snip ---
NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING
RegistryPath)
{
    PKEY_VALUE_PARTIAL_INFORMATION startKeyValue;
    LONG version;
    int i;

    Dump ("DriverEntry " TC_APP_NAME " " VERSION_STRING VERSION_STRING_SUFFIX
"\n");

    DetectX86Features ();

    PsGetVersion (&OsMajorVersion, &OsMinorVersion, NULL, NULL);

    Dump ("OsMajorVersion=%d OsMinorVersion=%d\n", OsMajorVersion,
OsMinorVersion);

    // NX pool support is available starting from Windows 8
    if ((OsMajorVersion > 6) || (OsMajorVersion == 6 && OsMinorVersion >= 2))
    {
        ExDefaultNonPagedPoolType = (POOL_TYPE) NonPagedPoolNx;
        ExDefaultMdlProtection = MdlMappingNoExecute;
    }

    // KeAreAllApcsDisabled is available starting from Windows Server 2003
    if ((OsMajorVersion > 5) || (OsMajorVersion == 5 && OsMinorVersion >= 2))
    {
        UNICODE_STRING KeAreAllApcsDisabledFuncName;
        RtlInitUnicodeString(&KeAreAllApcsDisabledFuncName,
L"KeAreAllApcsDisabled");

        KeAreAllApcsDisabledPtr = (KeAreAllApcsDisabledFn)
MmGetSystemRoutineAddress(&KeAreAllApcsDisabledFuncName);
    }

    // KeSaveExtendedProcessorState/KeRestoreExtendedProcessorState are
available starting from Windows 7
    //
KeQueryActiveGroupCount/KeQueryActiveProcessorCountEx/KeSetSystemGroupAffinityThread
are available starting from Windows 7
    if ((OsMajorVersion > 6) || (OsMajorVersion == 6 && OsMinorVersion >= 1))
    {
        UNICODE_STRING saveFuncName, restoreFuncName, groupCountFuncName,
procCountFuncName, setAffinityFuncName;
        RtlInitUnicodeString(&saveFuncName, L"KeSaveExtendedProcessorState");
        RtlInitUnicodeString(&restoreFuncName,
L"KeRestoreExtendedProcessorState");
        RtlInitUnicodeString(&groupCountFuncName, L"KeQueryActiveGroupCount");
        RtlInitUnicodeString(&procCountFuncName,
L"KeQueryActiveProcessorCountEx");
        RtlInitUnicodeString(&setAffinityFuncName,
L"KeSetSystemGroupAffinityThread");
        KeSaveExtendedProcessorStatePtr = (KeSaveExtendedProcessorStateFn)
MmGetSystemRoutineAddress(&saveFuncName);
        KeRestoreExtendedProcessorStatePtr =
(KeRestoreExtendedProcessorStateFn)
MmGetSystemRoutineAddress(&restoreFuncName);
        KeSetSystemGroupAffinityThreadPtr = (KeSetSystemGroupAffinityThreadFn)
MmGetSystemRoutineAddress(&setAffinityFuncName);
        KeQueryActiveGroupCountPtr = (KeQueryActiveGroupCountFn)
MmGetSystemRoutineAddress(&groupCountFuncName);
        KeQueryActiveProcessorCountExPtr = (KeQueryActiveProcessorCountExFn)
MmGetSystemRoutineAddress(&procCountFuncName);
    }

    // ExGetFirmwareEnvironmentVariable is available starting from Windows 8
    if ((OsMajorVersion > 6) || (OsMajorVersion == 6 && OsMinorVersion >= 2))
    {
        UNICODE_STRING funcName;
        RtlInitUnicodeString(&funcName, L"ExGetFirmwareEnvironmentVariable");
        ExGetFirmwareEnvironmentVariablePtr =
(ExGetFirmwareEnvironmentVariableFn) MmGetSystemRoutineAddress(&funcName);
    }

    // Load dump filter if the main driver is already loaded
    if (NT_SUCCESS (TCDeviceIoControl (NT_ROOT_PREFIX,
TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &version, sizeof (version))))
        return DumpFilterEntry ((PFILTER_EXTENSION) DriverObject,
(PFILTER_INITIALIZATION_DATA) RegistryPath);

    TCDriverObject = DriverObject;
    memset (VirtualVolumeDeviceObjects, 0, sizeof
(VirtualVolumeDeviceObjects));
...
--- snip ---

"Load dump filter if the main driver is already loaded". The drivers asks for
it's own driver object '\\Device\\VeraCrypt' which isn't created yet (first
time driver init/entry).

https://www.veracrypt.fr/code/VeraCrypt/tree/src/Driver/Ntdriver.c?h=VeraCrypt_1.24-Update6#n3509

--- snip ---
NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void
*InputBuffer, ULONG InputBufferSize, void *OutputBuffer, ULONG
OutputBufferSize)
{
    IO_STATUS_BLOCK ioStatusBlock;
    NTSTATUS ntStatus;
    PIRP irp;
    PFILE_OBJECT fileObject;
    PDEVICE_OBJECT deviceObject;
    KEVENT event;
    UNICODE_STRING name;

    if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled())
    {
        TCDeviceIoControlWorkItemArgs args;

        PIO_WORKITEM workItem = IoAllocateWorkItem (RootDeviceObject);
        if (!workItem)
            return STATUS_INSUFFICIENT_RESOURCES;

        args.deviceName = deviceName;
        args.IoControlCode = IoControlCode;
        args.InputBuffer = InputBuffer;
        args.InputBufferSize = InputBufferSize;
        args.OutputBuffer = OutputBuffer;
        args.OutputBufferSize = OutputBufferSize;

        KeInitializeEvent (&args.WorkItemCompletedEvent, SynchronizationEvent,
FALSE);
        IoQueueWorkItem (workItem, TCDeviceIoControlWorkItemRoutine,
DelayedWorkQueue, &args);

        KeWaitForSingleObject (&args.WorkItemCompletedEvent, Executive,
KernelMode, FALSE, NULL);
        IoFreeWorkItem (workItem);

        return args.Status;
    }

    RtlInitUnicodeString(&name, deviceName);
    ntStatus = IoGetDeviceObjectPointer (&name, FILE_READ_ATTRIBUTES,
&fileObject, &deviceObject);

    if (!NT_SUCCESS (ntStatus))
        return ntStatus;

    KeInitializeEvent(&event, NotificationEvent, FALSE);
...

--- snip ---

Wine returns a stub driver object in any case which is bad.

https://source.winehq.org/git/wine.git/blob/9e26bc811656ad8eb901bffa5528b9ce25d44bc3:/dlls/ntoskrnl.exe/ntoskrnl.c#l1648

--- snip ---
1648 /***********************************************************************
1649  *           IoGetDeviceObjectPointer   (NTOSKRNL.EXE.@)
1650  */
1651 NTSTATUS  WINAPI IoGetDeviceObjectPointer( UNICODE_STRING *name,
ACCESS_MASK access, PFILE_OBJECT *file, PDEVICE_OBJECT *device )
1652 {
1653     static DEVICE_OBJECT stub_device;
1654     static DRIVER_OBJECT stub_driver;
1655 
1656     FIXME( "stub: %s %x %p %p\n", debugstr_us(name), access, file, device
);
1657 
1658     stub_device.StackSize = 0x80; /* minimum value to appease SecuROM 5.x
*/
1659     stub_device.DriverObject = &stub_driver;
1660 
1661     *file  = NULL;
1662     *device = &stub_device;
1663 
1664     return STATUS_SUCCESS;
1665 }
--- snip ---

The crash is in 'IoBuildDeviceIoControlRequest' -> IoGetNextIrpStackLocation()
-> irpsp access which is the result of earlier misconception.

https://source.winehq.org/git/wine.git/blob/9e26bc811656ad8eb901bffa5528b9ce25d44bc3:/dlls/ntoskrnl.exe/ntoskrnl.c#l1200

--- snip ---
1200 /***********************************************************************
1201  *           IoBuildDeviceIoControlRequest  (NTOSKRNL.EXE.@)
1202  */
1203 PIRP WINAPI IoBuildDeviceIoControlRequest( ULONG code, PDEVICE_OBJECT
device,
1204                                            PVOID in_buff, ULONG in_len,
1205                                            PVOID out_buff, ULONG out_len,
1206                                            BOOLEAN internal, PKEVENT
event,
1207                                            PIO_STATUS_BLOCK iosb )
1208 {
1209     PIRP irp;
1210     PIO_STACK_LOCATION irpsp;
1211     MDL *mdl;
1212 
1213     TRACE( "%x, %p, %p, %u, %p, %u, %u, %p, %p\n",
1214            code, device, in_buff, in_len, out_buff, out_len, internal,
event, iosb );
1215 
1216     if (device == NULL)
1217         return NULL;
1218 
1219     irp = IoAllocateIrp( device->StackSize, FALSE );
1220     if (irp == NULL)
1221         return NULL;
1222 
1223     irpsp = IoGetNextIrpStackLocation( irp );
1224     irpsp->MajorFunction = internal ? IRP_MJ_INTERNAL_DEVICE_CONTROL :
IRP_MJ_DEVICE_CONTROL;
1225     irpsp->Parameters.DeviceIoControl.IoControlCode = code;
1226     irpsp->Parameters.DeviceIoControl.InputBufferLength = in_len;
1227     irpsp->Parameters.DeviceIoControl.OutputBufferLength = out_len;
1228     irpsp->DeviceObject = NULL;
1229     irpsp->CompletionRoutine = NULL;
1230 
--- snip ---

A similar case is bug 27668 ("SecuROM 4.x/5.x: SpellForce won't recognize
original CD during install/play ('IoGetDeviceObjectPointer' needs to return
real device/driver object for '\\Device\\CdRom0')").

In any case, this filter driver relies on layered kernel driver architecture.
Until Wine has a proper design and implementation of a layered kernel driver
concept this can't work.

Even then, due to the nature of this kernel driver this not going to work under
Wine. FYI there is a native Linux port if dm-crypt / LUKS doesn't fit your
requirements.

$ sha1sum VeraCrypt\ Portable\ 1.24-Update6.exe 
489e85916d2f93f1664110d987132d678178d83b  VeraCrypt Portable 1.24-Update6.exe

$ du -sh VeraCrypt\ Portable\ 1.24-Update6.exe 
35M    VeraCrypt Portable 1.24-Update6.exe

$ wine --version
wine-5.8-173-g9e26bc8116

Regards

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.



More information about the wine-bugs mailing list