[Bug 50201] New: Sentinel HASP 'aksfridge.sys' kernel driver fails to load, returns error 0xc000007a ('ntoskrnl.exe' needs fixed load address to prevent mapping into low memory range)

WineHQ Bugzilla wine-bugs at winehq.org
Fri Nov 27 17:24:45 CST 2020


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

            Bug ID: 50201
           Summary: Sentinel HASP 'aksfridge.sys' kernel driver fails to
                    load, returns error 0xc000007a ('ntoskrnl.exe' needs
                    fixed load address to prevent mapping into low memory
                    range)
           Product: Wine
           Version: 5.22
          Hardware: x86-64
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ntoskrnl
          Assignee: wine-bugs at winehq.org
          Reporter: focht at gmx.net
      Distribution: ---

Hello folks,

while checking some Sentinel HASP Runtime driver bugs (bug 45510), I've
encountered another problem.

Using SafeNET's Sentinel HASP Runtime v6.6 from bug 45510 and bug 50189 as
example.

Stable download:

https://web.archive.org/web/20201125113604/http://www.argusone.com/pub/Add_PC_Files/Sentinel_HASP_Run-time_setup/HASPUserSetup.exe

The 'hardlock.sys' driver now loads successfully thanks due to bug 50189 fixed.
'aksfridge.sys' which is an ancillary function driver doesn't load. It returns
failure from entry point.

--- snip ---
$ WINEDEBUG=+seh,+loaddll,+ntoskrnl wine net start aksfridge

0108:Call driver init 0000000000D7FE5E
(obj=00000000000431F0,str=L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\aksfridge")
0108:trace:seh:dispatch_exception code=c0000096 flags=0 addr=0000000000D7FD46
ip=d7fd46 tid=0108
0108:trace:seh:dispatch_exception  rax=0000000000000400 rbx=0000000000d80c0f
rcx=0000000000d7fe5e rdx=0000000000d805b5
0108:trace:seh:dispatch_exception  rsi=0000000000d805b5 rdi=0000000000d7fe5e
rbp=0000000000c3f890 rsp=0000000000c3f760
0108:trace:seh:dispatch_exception   r8=000000000000065a  r9=0000000000d7fe5e
r10=0000000000000018 r11=0000000000000000
0108:trace:seh:dispatch_exception  r12=00000000000431f0 r13=0000000000043358
r14=00000000000418f8 r15=0000000000000000
0108:trace:seh:call_vectored_handlers calling handler at 000000000031D2F0
code=c0000096 flags=0
0108:trace:seh:call_vectored_handlers handler at 000000000031D2F0 returned
ffffffff
0108:trace:seh:dispatch_exception code=c0000096 flags=0 addr=0000000000D7FE3D
ip=d7fe3d tid=0108
0108:trace:seh:dispatch_exception  rax=0000000000000400 rbx=0000000000d805be
rcx=0000000000000000 rdx=0000000000000000
0108:trace:seh:dispatch_exception  rsi=0000000000d805b5 rdi=0000000000d7fe66
rbp=0000000000d80c0f rsp=0000000000c3f760
0108:trace:seh:dispatch_exception   r8=000000000000065a  r9=0000000000d7fe5e
r10=0000000000000018 r11=0000000000000000
0108:trace:seh:dispatch_exception  r12=00000000000431f0 r13=0000000000043358
r14=00000000000418f8 r15=0000000000000000
0108:trace:seh:call_vectored_handlers calling handler at 000000000031D2F0
code=c0000096 flags=0
0108:trace:seh:call_vectored_handlers handler at 000000000031D2F0 returned
ffffffff 
...
0108:Call KERNEL32.IsBadReadPtr(00310000,00000001) ret=00323d1d
0108:Ret  KERNEL32.IsBadReadPtr() retval=00000000 ret=00323d1d
0108:Ret  ntoskrnl.exe.MmIsAddressValid() retval=00000001 ret=00d80047
0108:Call ntoskrnl.exe.MmIsAddressValid(00310078) ret=00d800ab
0108:trace:ntoskrnl:MmIsAddressValid (0000000000310078)
0108:Call KERNEL32.IsBadReadPtr(00310078,00000001) ret=00323d1d
0108:Ret  KERNEL32.IsBadReadPtr() retval=00000000 ret=00323d1d
0108:Ret  ntoskrnl.exe.MmIsAddressValid() retval=00000001 ret=00d800ab
0108:trace:seh:dispatch_exception code=c0000096 flags=0 addr=0000000000D80100
ip=d80100 tid=0108
0108:trace:seh:dispatch_exception  rax=0000000000000400 rbx=0000000000d7fe5e
rcx=0000000000310078 rdx=0000000000004550
0108:trace:seh:dispatch_exception  rsi=000000007b6038a8 rdi=00000000000430c0
rbp=0000000000c3f890 rsp=0000000000c3f798
0108:trace:seh:dispatch_exception   r8=0000000000000000  r9=0000000000000000
r10=0000000000c3f2f2 r11=0000000000000000
0108:trace:seh:dispatch_exception  r12=00000000000431f0 r13=0000000000043358
r14=0000000000d7fcbc r15=0000000000310000
0108:trace:seh:call_vectored_handlers calling handler at 000000000031D2F0
code=c0000096 flags=0
0108:trace:seh:call_vectored_handlers handler at 000000000031D2F0 returned
ffffffff 
...
0108:Call ntoskrnl.exe.RtlRandom(00c3f6f0) ret=00d6167a
0108:Call ntdll.RtlRandom(00c3f6f0) ret=7bc4428f
0108:Ret  ntdll.RtlRandom() retval=1ec10b9b ret=7bc4428f
0108:Ret  ntoskrnl.exe.RtlRandom() retval=1ec10b9b ret=00d6167a
0108:trace:seh:dispatch_exception code=c0000096 flags=0 addr=0000000000D6BF71
ip=d6bf71 tid=0108
0108:trace:seh:dispatch_exception  rax=000000001ec10b9b rbx=0000000000315e58
rcx=0000000000315e58 rdx=0000000000000000
0108:trace:seh:dispatch_exception  rsi=0000000000000000 rdi=0000000000310000
rbp=0000000000c3f890 rsp=0000000000c3f690
0108:trace:seh:dispatch_exception   r8=0000000000000000  r9=0000000000000000
r10=0000000000c3f20b r11=0000000000000000
0108:trace:seh:dispatch_exception  r12=00000000000431f0 r13=0000000000043358
r14=00000000000418f8 r15=0000000000310000
0108:trace:seh:call_vectored_handlers calling handler at 000000000031D2F0
code=c0000096 flags=0
0108:trace:seh:call_vectored_handlers handler at 000000000031D2F0 returned
ffffffff
0108:Call ntoskrnl.exe.MmIsAddressValid(00315000) ret=00d6bfa5
0108:trace:ntoskrnl:MmIsAddressValid (0000000000315000)
0108:Call KERNEL32.IsBadReadPtr(00315000,00000001) ret=00323d1d
0108:Ret  KERNEL32.IsBadReadPtr() retval=00000000 ret=00323d1d
0108:Ret  ntoskrnl.exe.MmIsAddressValid() retval=00000001 ret=00d6bfa5
0108:Call KERNEL32.IsBadStringPtrW(00041890,ffffffffffffffff) ret=003277c8
0108:Ret  KERNEL32.IsBadStringPtrW() retval=00000000 ret=003277c8
0108:Call ntdll.memchr(003d13c0,00000078,00000007) ret=003bafe9
0108:Ret  ntdll.memchr() retval=003d13c4 ret=003bafe9
0108:Call KERNEL32.IsBadStringPtrW(000418f8,ffffffffffffffff) ret=003277c8
0108:Ret  KERNEL32.IsBadStringPtrW() retval=00000000 ret=003277c8
Ret  driver init 0000000000D7FE5E
(obj=00000000000431F0,str=L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\aksfridge")
retval=c000007a
0108:trace:ntoskrnl:init_driver init done for L"aksfridge" obj 00000000000431F0
0108:trace:ntoskrnl:init_driver - DriverInit = 0000000000D7FE5E
0108:trace:ntoskrnl:init_driver - DriverStartIo = 0000000000000000
0108:trace:ntoskrnl:init_driver - DriverUnload = 0000000000000000
...
0108:trace:ntoskrnl:IoDeleteDriver (00000000000431F0)
0108:trace:ntoskrnl:ObDereferenceObject
0108:err:ntoskrnl:ZwLoadDriver failed to create driver
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\aksfridge":
c000007a
0108:Ret  ntoskrnl.exe.ZwLoadDriver() retval=c000007a ret=14000135b
0108:Call ntoskrnl.exe.RtlNtStatusToDosError(c000007a) ret=1400013ec
0108:Call ntdll.RtlNtStatusToDosError(c000007a) ret=7bc4428f
0108:Ret  ntdll.RtlNtStatusToDosError() retval=0000007f ret=7bc4428f
0108:Ret  ntoskrnl.exe.RtlNtStatusToDosError() retval=0000007f ret=1400013ec
...
0024:Call KERNEL32.WideCharToMultiByte(000001b5,00000000,0015a2a0 L"Procedure
not found.\r\n",00000016,00000000,00000000,00000000,00000000) ret=00401ad1
--- snip ---

The error is misleading at best. Although there are still issues with another
flavour of a custom imports resolver I can maybe explain in different bug (uses
pre-computed API hashes for lookup), the root cause here is different.

Relay trace is not useful. One has to debug the kernel driver. The driver uses
a rather fancy method to locate 'ntoskrnl.exe' load base address.

Relevant disassembly:

--- snip ---
0000000000D7ED70 | push rbx                                        |
0000000000D7ED72 | sub rsp,20                                      |
0000000000D7ED76 | mov rbx,rcx                                     |
0000000000D7ED79 | call aksfridge.D6C486                           |
0000000000D7ED7E | mov rcx,rax                                     |
0000000000D7ED81 | call aksfridge.D61584                           |
0000000000D7ED86 | call aksfridge.D61648                           |
0000000000D7ED8B | mov rcx,qword ptr ds:[<&ExAllocatePoolWithTag>] |
0000000000D7ED92 | mov qword ptr ds:[D7C020],rax                   |
0000000000D7ED99 | call aksfridge.D6BF64                           |
0000000000D7ED9E | test rax,rax                                    | load base
0000000000D7EDA1 | mov qword ptr ds:[D799E0],rax                   |
0000000000D7EDA8 | jne aksfridge.D7EDB1                            |
0000000000D7EDAA | mov eax,C000007A                                | fail
0000000000D7EDAF | jmp aksfridge.D7EDD4                            |
0000000000D7EDB1 | call aksfridge.D626A4                           |
0000000000D7EDB6 | test eax,eax                                    |
0000000000D7EDB8 | js aksfridge.D7EDD4                             |
0000000000D7EDBA | call aksfridge.D6C02C                           |
0000000000D7EDBF | mov rcx,rbx                                     |
0000000000D7EDC2 | call aksfridge.D7E4B4                           |
0000000000D7EDC7 | test eax,eax                                    |
0000000000D7EDC9 | mov ebx,eax                                     |
0000000000D7EDCB | js aksfridge.D7EDD4                             |
0000000000D7EDCD | call aksfridge.D62E74                           |
0000000000D7EDD2 | mov eax,ebx                                     |
0000000000D7EDD4 | add rsp,20                                      |
0000000000D7EDD8 | pop rbx                                         |
0000000000D7EDD9 | ret                                             |
--- snip ---

RCX = &ntoskrnl.ExAllocatePoolWithTag = search start

--- snip ---
00D6BF64 | push rbx                                |
00D6BF66 | push rsi                                |
00D6BF67 | push rdi                                |
00D6BF68 | push r12                                |
00D6BF6A | sub rsp,38                              |
00D6BF6E | mov rbx,rcx                             |
00D6BF71 | mov rax,cr8                             | get current IRQL
00D6BF75 | xor esi,esi                             |
00D6BF77 | cmp al,sil                              | PASSIVE_LEVEL?
00D6BF7A | je aksfridge.D6BF83                     |
00D6BF7C | xor eax,eax                             | fail
00D6BF7E | jmp aksfridge.D6C022                    |
00D6BF83 | cmp word ptr ds:[rcx],25FF              | 0x25FF abs/ind far jmp
00D6BF88 | je aksfridge.D6BF91                     |
00D6BF8A | cmp word ptr ds:[rcx],15FF              | 0x15FF abs/ind far call
00D6BF8F | jne aksfridge.D6BF95                    |
00D6BF91 | mov rbx,qword ptr ds:[rcx+2]            | call/jump dest addr
00D6BF95 | and rbx,FFFFFFFFFFFFF000                | round to page start
00D6BF9C | mov rcx,rbx                             |
00D6BF9F | call qword ptr ds:[<&MmIsAddressValid>] |
00D6BFA5 | cmp al,sil                              |
00D6BFA8 | jne aksfridge.D6BFAE                    |
00D6BFAA | xor eax,eax                             | fail
00D6BFAC | jmp aksfridge.D6C022                    |
00D6BFAE | mov rdi,rbx                             | RBX = current page
00D6BFB1 | mov qword ptr ss:[rsp+20],rbx           |
00D6BFB6 | sub rbx,8000000                         | downsearch range (128 Mb)
00D6BFBD | cmp rdi,rbx                             | 
00D6BFC0 | jbe aksfridge.D6C008                    | end of down search?
00D6BFC2 | mov rcx,rdi                             |
00D6BFC5 | call qword ptr ds:[<&MmIsAddressValid>] |
00D6BFCB | cmp al,sil                              |
00D6BFCE | jne aksfridge.D6BFD2                    |
00D6BFD0 | jmp aksfridge.D6BFFA                    |
00D6BFD2 | cmp word ptr ds:[rdi],5A4D              | "MZ" DOS sig found?
00D6BFD7 | je aksfridge.D6BFDB                     |
00D6BFD9 | jmp aksfridge.D6BFFA                    |
00D6BFDB | movsxd r12,dword ptr ds:[rdi+3C]        |
00D6BFDF | add r12,rdi                             |
00D6BFE2 | mov rcx,r12                             |
00D6BFE5 | call qword ptr ds:[<&MmIsAddressValid>] |
00D6BFEB | cmp al,sil                              |
00D6BFEE | je aksfridge.D6BFFA                     |
00D6BFF0 | cmp dword ptr ds:[r12],4550             | "PE" header sig found?
00D6BFF8 | je aksfridge.D6C008                     |
00D6BFFA | sub rdi,1000                            | down one page
00D6C001 | mov qword ptr ss:[rsp+20],rdi           |
00D6C006 | jmp aksfridge.D6BFBD                    | loop down search
00D6C008 | cmp rbx,rdi                             |
00D6C00B | sbb rsi,rsi                             | 0 or -1
00D6C00E | and rsi,rdi                             | mask addr
00D6C011 | mov qword ptr ss:[rsp+20],rsi           |
00D6C016 | jmp aksfridge.D6C01F                    |
00D6C018 | xor esi,esi                             | fail
00D6C01A | mov qword ptr ss:[rsp+20],rsi           |
00D6C01F | mov rax,rsi                             | RAX = load base
00D6C022 | add rsp,38                              |
00D6C026 | pop r12                                 |
00D6C028 | pop rdi                                 |
00D6C029 | pop rsi                                 |
00D6C02A | pop rbx                                 |
00D6C02B | ret                                     |
--- snip ---

<ntoskrnl.ExAllocatePoolWithTag>:

--- snip ---
00000000003229C0  | 55           | push rbp      |
00000000003229C1  | 56           | push rsi      |
00000000003229C2  | 57           | push rdi      |
00000000003229C3  | 53           | push rbx      |
00000000003229C4  | 48:83EC 38   | sub rsp,38    |
...
--- snip ---

Start search with 'ntoskrnl.ExAllocatePoolWithTag' API function address.

* IRQL == PASSIVE_LEVEL -> fail
* check if first instruction of API entry point is indirect far jump or far
call
* if yes, read the destination address, otherwise use current opcode address
* round to current page start
* check page access -> fail if no access
* check if down search range 0x8000000 (128 MB) exceeded -> fail
* check if page start contains "MZ" DOS signature -> no -> continue down search 
* check page access at PE signature -> fail if no access
* check for PE signature -> yes, found base address, no -> continue search one
page down

The problem is the current low address mapping of 'ntoskrnl.exe'. Unlike
certain core dlls it has no preferred load address and it's a PE module,
causing it to be mapped into low address space range:

--- snip ---
Base             Module         Path
0000000000220000 sechost.dll    ...lib64\wine\sechost.dll
0000000000250000 ucrtbase.dll   ...lib64\wine\ucrtbase.dll
0000000000310000 ntoskrnl.exe   ...lib64\wine\ntoskrnl.exe
0000000000360000 msvcrt.dll     ...lib64\wine\msvcrt.dll
0000000000AD0000 rpcrt4.dll     ...lib64\wine\rpcrt4.dll
0000000000D60000 aksfridge.sys  C:\windows\system32\drivers\aksfridge.sys
0000000000D90000 hal.dll        ...lib64\wine\hal.dll
000000007B000000 kernelbase.dll ...lib64\wine\kernelbase.dll
000000007B600000 kernel32.dll   ...lib64\wine\kernel32.dll
000000007BC00000 ntdll.dll      ...lib64\wine\ntdll.dll
0000000140000000 winedevice.exe ...lib64\wine\winedevice.exe
0000000180000000 advapi32.dll   ...lib64\wine\advapi32.dll
--- snip ---

Load base: 0x310000
API entry rounded: 0x302000
0x302000 <= 0x8000000 (range)

For testing I gave it a predefined load address at 0x82000000 and it fixed the
problem. It mimicks Windows kernel address space 0x8XXXXXXX but it's kinda
pointless with Wine. It doesn't necessarily need to be there unless a kernel
driver checks high address bits. For this driver it just needs to be > 128MB
address range.

--- snip ---
$ WINEDEBUG=+seh,+loaddll,+ntoskrnl wine net start aksfridge
...
The aksfridge service is starting.
...
00d0:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\ntdll.dll" at
000000007BC00000: builtin
00d0:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\kernelbase.dll"
at 000000007B000000: builtin
00d0:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\kernel32.dll"
at 000000007B600000: builtin
00d0:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\winedevice.exe"
at 0000000140000000: builtin
00d0:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\ucrtbase.dll"
at 0000000000250000: builtin
00d0:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\sechost.dll" at
0000000000220000: builtin
00d0:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\advapi32.dll"
at 0000000180000000: builtin
00d0:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\msvcrt.dll" at
0000000000310000: builtin
00d0:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\ntoskrnl.exe"
at 0000000082000000: builtin
00d0:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\rpcrt4.dll" at
0000000000A80000: builtin 
...
00dc:trace:ntoskrnl:open_driver opened service for driver
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\aksfridge"
00dc:trace:ntoskrnl:IoCreateDriver (L"\\Driver\\aksfridge", 0000000082015BE0)
00dc:trace:ntoskrnl:load_driver loading driver
L"C:\\windows\\system32\\drivers\\aksfridge.sys"
00dc:trace:loaddll:build_module Loaded L"C:\\windows\\system32\\HAL.dll" at
0000000000D40000: builtin
00dc:trace:loaddll:build_module Loaded
L"C:\\windows\\system32\\drivers\\aksfridge.sys" at 0000000000D10000: native
00dc:trace:ntoskrnl:ldr_notify_callback loading L"HAL.dll"
00dc:trace:ntoskrnl:ldr_notify_callback loading L"aksfridge.sys"
...
00dc:trace:ntoskrnl:MmIsAddressValid (0000000082000000)
00dc:trace:ntoskrnl:MmIsAddressValid (0000000082000078)
00dc:trace:ntoskrnl:MmIsAddressValid (0000000082000FFC)
00dc:trace:ntoskrnl:MmIsAddressValid (0000000082000FF8)
00dc:trace:ntoskrnl:MmIsAddressValid (0000000082000FF4)
00dc:trace:ntoskrnl:MmIsAddressValid (0000000082000FF0)
00dc:trace:ntoskrnl:MmIsAddressValid (0000000082000FEC)
...
00dc:trace:ntoskrnl:MmIsAddressValid (00000000820002C4)
00dc:trace:ntoskrnl:MmIsAddressValid (00000000820002C0)
00dc:trace:ntoskrnl:MmIsAddressValid (00000000820002BC)
00dc:trace:ntoskrnl:ExAllocatePoolWithTag 2968 pool 0 -> 0000000000970380
...
00dc:fixme:ntoskrnl:IoGetDeviceObjectPointer stub: L"\\Device\\HarddiskVolume1"
80 0000000000BEF488 0000000000BEF478
00dc:trace:seh:dispatch_exception code=c0000096 flags=0 addr=0000000000D1BE2A
ip=d1be2a tid=00dc
00dc:trace:seh:dispatch_exception  rax=0000000000bef570 rbx=0000000000000000
rcx=0000000000000000 rdx=000000000524baa8
00dc:trace:seh:dispatch_exception  rsi=0000000000000000 rdi=0000000000bef478
rbp=0000000000bef488 rsp=0000000000bef310
00dc:trace:seh:dispatch_exception   r8=0000000000000000  r9=0000000000000000
r10=0000000000beeb18 r11=000000008203d5c8
00dc:trace:seh:dispatch_exception  r12=0000000000000200 r13=000000000524baa8
r14=00000000000183b8 r15=0000000000000000
00dc:trace:seh:call_vectored_handlers calling handler at 000000008200D2F0
code=c0000096 flags=0
00dc:trace:seh:call_vectored_handlers handler at 000000008200D2F0 returned
ffffffff
00dc:trace:ntoskrnl:MmIsAddressValid (0000000000000010)
00dc:trace:seh:dispatch_exception code=c0000005 flags=0 addr=000000007B62C17E
ip=7b62c17e tid=00dc
00dc:trace:seh:dispatch_exception  info[0]=0000000000000000
00dc:trace:seh:dispatch_exception  info[1]=0000000000000010
00dc:trace:seh:dispatch_exception  rax=0000000000001000 rbx=0000000000bef1e0
rcx=0000000000001000 rdx=0000000000bef1e0
00dc:trace:seh:dispatch_exception  rsi=0000000000000010 rdi=0000000000000001
rbp=0000000000bef230 rsp=0000000000bef1b0
00dc:trace:seh:dispatch_exception   r8=00000000ffd80000  r9=0000000000000013
r10=0000000000beeb88 r11=0000000000000000
00dc:trace:seh:dispatch_exception  r12=0000000000200020 r13=0000000000000000
r14=0000000000000000 r15=0000000000000001
...
wine: Call from 000000007B012B22 to unimplemented function
ntoskrnl.exe.IoGetLowerDeviceObject, aborting
--- snip ---

After the unimplemented stub (another bug) it runs into bug 49165

$ sha1sum HASPUserSetup.exe 
fa5f85d8dfbef3188087f1b6fb0ec81a16e6a26d  HASPUserSetup.exe

$ du -sh HASPUserSetup.exe 
14M    HASPUserSetup.exe

$ wine --version
wine-5.22-153-g9faa5eeddd2

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