[Bug 50208] New: Multiple kernel drivers need NtQuerySystemInformation(SystemModuleInformation) to return correct ImageBaseAddress and ImageSize for modules (Sentinel HASP 'hardlock.sys')

WineHQ Bugzilla wine-bugs at winehq.org
Sat Nov 28 15:54:46 CST 2020


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

            Bug ID: 50208
           Summary: Multiple kernel drivers need
                    NtQuerySystemInformation(SystemModuleInformation) to
                    return correct ImageBaseAddress and ImageSize for
                    modules (Sentinel HASP 'hardlock.sys')
           Product: Wine
           Version: 5.22
          Hardware: x86-64
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ntdll
          Assignee: wine-bugs at winehq.org
          Reporter: focht at gmx.net
      Distribution: ---

Hello folks,

as it says.

Download:

https://web.archive.org/web/20201128131118/http://www.cadshop.ru/drivers/HASPDINST_7.32.exe

NOTE: The logs have patch for bug 50201 applied, hence the non-dynamic/default
load base address for 'ntoskrnl.exe' 0x8XXXXXXX.

--- snip ---
$ WINEDEBUG=+seh,+relay,+loaddll,+ntoskrnl wine net start hardlock
...
The hardlock service is starting.
...
0108:Call driver init 00EB4A24
(obj=0012B7C0,str=L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\hardlock") 
0108:trace:seh:dispatch_exception code=c0000096 flags=0 addr=00EB49B6
ip=00eb49b6 tid=0108
0108:trace:seh:dispatch_exception  eax=00000400 ebx=00eb4a24 ecx=00eb4a24
edx=00eb766b esi=0012b7c0 edi=0012b874
0108:trace:seh:dispatch_exception  ebp=00d0fdd0 esp=00d0fb5c cs=0023 ds=002b
es=002b fs=0063 gs=006b flags=00010206
0108:trace:seh:call_vectored_handlers calling handler at 8200DA00 code=c0000096
flags=0
0108:trace:seh:call_vectored_handlers handler at 8200DA00 returned ffffffff
...
0108:Call ntoskrnl.exe.MmIsAddressValid(82008000) ret=00eb4bd3
0108:trace:ntoskrnl:MmIsAddressValid (82008000)
0108:Call KERNEL32.IsBadReadPtr(82008000,00000001) ret=82012dc6
0108:Ret  KERNEL32.IsBadReadPtr() retval=00000000 ret=82012dc6
0108:Ret  ntoskrnl.exe.MmIsAddressValid() retval=00000001 ret=00eb4bd3
0108:Call ntoskrnl.exe.MmIsAddressValid(82007000) ret=00eb4bd3
0108:trace:ntoskrnl:MmIsAddressValid (82007000)
0108:Call KERNEL32.IsBadReadPtr(82007000,00000001) ret=82012dc6
0108:Ret  KERNEL32.IsBadReadPtr() retval=00000000 ret=82012dc6
0108:Ret  ntoskrnl.exe.MmIsAddressValid() retval=00000001 ret=00eb4bd3
0108:Call ntoskrnl.exe.MmIsAddressValid(82006000) ret=00eb4bd3
0108:trace:ntoskrnl:MmIsAddressValid (82006000)
0108:Call KERNEL32.IsBadReadPtr(82006000,00000001) ret=82012dc6
0108:Ret  KERNEL32.IsBadReadPtr() retval=00000000 ret=82012dc6
0108:Ret  ntoskrnl.exe.MmIsAddressValid() retval=00000001 ret=00eb4bd3
0108:Call ntoskrnl.exe.MmIsAddressValid(82005000) ret=00eb4bd3
0108:trace:ntoskrnl:MmIsAddressValid (82005000)
0108:Call KERNEL32.IsBadReadPtr(82005000,00000001) ret=82012dc6
0108:Ret  KERNEL32.IsBadReadPtr() retval=00000000 ret=82012dc6
0108:Ret  ntoskrnl.exe.MmIsAddressValid() retval=00000001 ret=00eb4bd3 
...
0108:Call
ntoskrnl.exe.ZwQuerySystemInformation(0000000b,00d0f8c4,00000120,00d0f9e8)
ret=00e9dc56
0108:Call ntdll.NtQuerySystemInformation(0000000b,00d0f8c4,00000120,00d0f9e8)
ret=7bc3ab84
0108:Ret  ntdll.NtQuerySystemInformation() retval=c0000004 ret=7bc3ab84
0108:Ret  ntoskrnl.exe.ZwQuerySystemInformation() retval=c0000004 ret=00e9dc56
0108:Call ntoskrnl.exe.ExAllocatePoolWithTag(00000001,00000358,30396b48)
ret=00e9dc67
0108:Call ntdll.RtlAllocateHeap(00a90000,00000000,00000358) ret=82011e8a
0108:Ret  ntdll.RtlAllocateHeap() retval=00a923a0 ret=82011e8a
0108:trace:ntoskrnl:ExAllocatePoolWithTag Call
ntdll.memchr(003cddd4,00000075,00000007) ret=003b5c6a
0108:Ret  ntdll.memchr() retval=003cddd7 ret=003b5c6a
0108:Call ntdll.memchr(003cddd4,00000075,00000007) ret=003b5c6a
0108:Ret  ntdll.memchr() retval=003cddd7 ret=003b5c6a
0108:Ret  ntoskrnl.exe.ExAllocatePoolWithTag() retval=00a923a0 ret=00e9dc67
0108:Call
ntoskrnl.exe.ZwQuerySystemInformation(0000000b,00a923a0,00000358,00d0f9e8)
ret=00e9dc85
0108:Call ntdll.NtQuerySystemInformation(0000000b,00a923a0,00000358,00d0f9e8)
ret=7bc3ab84
0108:Ret  ntdll.NtQuerySystemInformation() retval=00000000 ret=7bc3ab84
0108:Ret  ntoskrnl.exe.ZwQuerySystemInformation() retval=00000000 ret=00e9dc85 
...
0108:trace:ntoskrnl:init_driver init done for L"hardlock" obj 0012B7C0
0108:trace:ntoskrnl:init_driver - DriverInit = 00EB4A24
0108:trace:ntoskrnl:init_driver - DriverStartIo = 00000000
0108:trace:ntoskrnl:init_driver - DriverUnload = 00E3F03E
0108:trace:ntoskrnl:init_driver Call ntdll.memchr(003cddd4,00000064,00000007)
ret=003b5c6a
0108:Ret  ntdll.memchr() retval=003cddd4 ret=003b5c6a
0108:trace:ntoskrnl:init_driver Call ntdll.memchr(003cddd4,00000064,00000007)
ret=003b5c6a
0108:Ret  ntdll.memchr() retval=003cddd4 ret=003b5c6a 
...
0108:Ret  ntoskrnl.exe.ZwLoadDriver() retval=c000009a ret=00401392 
...
failed to create driver
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\hardlock": c000009a 
--- snip ---

The problem can't be seen in trace logs hence debugging of the driver is
needed.

The driver is partially code-flow obfuscated and employs a number of anti-debug
tricks. The relevant piece of disassembly (not obfuscated):

--- snip ---
00E9DC30 | push ebp                                               
00E9DC31 | mov ebp,esp                                            
00E9DC33 | sub esp,128                                            
00E9DC39 | push ebx                                               
00E9DC3A | lea eax,dword ptr ss:[ebp-4]          ; buffer size needed           
00E9DC3D | push esi                                               
00E9DC3E | lea ecx,dword ptr ss:[ebp-128]                         
00E9DC44 | push edi                                               
00E9DC45 | mov esi,dword ptr ds:[<&_NtQuerySystemInformation at 16>] 
00E9DC4B | push eax                                               
00E9DC4C | push 120                                               
00E9DC51 | push ecx                                               
00E9DC52 | push B                                ; SystemModuleInformation
00E9DC54 | call esi                              ; NtQuerySystemInformation()
00E9DC56 | push 30396B48                                          
00E9DC5B | mov ecx,dword ptr ss:[ebp-4]                           
00E9DC5E | push ecx                                               
00E9DC5F | push 1                                                 
00E9DC61 | call dword ptr ds:[<&_ExAllocatePoolWithTag at 12>]       
00E9DC67 | mov ebx,eax                                            
00E9DC69 | test ebx,ebx                                           
00E9DC6B | jne hardlock.E9DC78                                    
00E9DC6D | xor al,al                                              
00E9DC6F | pop edi                                                
00E9DC70 | pop esi                                                
00E9DC71 | pop ebx                                                
00E9DC72 | mov esp,ebp                                            
00E9DC74 | pop ebp                                                
00E9DC75 | ret 8                                                  
00E9DC78 | lea eax,dword ptr ss:[ebp-4]                           
00E9DC7B | mov ecx,dword ptr ss:[ebp-4]                           
00E9DC7E | push eax                                               
00E9DC7F | push ecx                                               
00E9DC80 | push ebx                                               
00E9DC81 | push B                                ; SystemModuleInformation
00E9DC83 | call esi                              ; NtQuerySystemInformation()
00E9DC85 | test eax,eax                                           
00E9DC87 | je hardlock.E9DC9B                                     
00E9DC89 | push ebx                                               
00E9DC8A | call dword ptr ds:[<&_ExFreePool at 4>]                   
00E9DC90 | xor al,al                                              
00E9DC92 | pop edi                                                
00E9DC93 | pop esi                                                
00E9DC94 | pop ebx                                                
00E9DC95 | mov esp,ebp                                            
00E9DC97 | pop ebp                                                
00E9DC98 | ret 8                                                  
00E9DC9B | mov esi,dword ptr ds:[ebx]            ; smi.Count
00E9DC9D | lea eax,dword ptr ds:[ebx+4]          ; smi.Modules[]
00E9DCA0 | xor edx,edx                                            
00E9DCA2 | mov dword ptr ss:[ebp-8],eax                           
00E9DCA5 | test esi,esi                                           
00E9DCA7 | je hardlock.E9DCC6                                     
00E9DCA9 | add eax,8                             ; mod.ImageSize
00E9DCAC | mov ecx,dword ptr ss:[ebp+8]          ; &ExAllocatePoolWithTag at 12
00E9DCAF | cmp dword ptr ds:[eax],ecx            ; mod.ImageBaseAddress
00E9DCB1 | jae hardlock.E9DCBC                                    
00E9DCB3 | mov edi,dword ptr ds:[eax+4]          ; mod.ImageSize
00E9DCB6 | add edi,dword ptr ds:[eax]            ; calc end address of module
00E9DCB8 | cmp edi,ecx                                            
00E9DCBA | ja hardlock.E9DCD8                                     
00E9DCBC | add eax,11C                           ; mod_entry++
00E9DCC1 | inc edx                                                
00E9DCC2 | cmp edx,esi                           ; last mod_entry?
00E9DCC4 | jne hardlock.E9DCAF                                    
00E9DCC6 | push ebx                                               
00E9DCC7 | call dword ptr ds:[<&_ExFreePool at 4>]                   
00E9DCCD | xor al,al                                              
00E9DCCF | pop edi                                                
00E9DCD0 | pop esi                                                
00E9DCD1 | pop ebx                                                
00E9DCD2 | mov esp,ebp                                            
00E9DCD4 | pop ebp                                                
00E9DCD5 | ret 8                                                  
00E9DCD8 | lea ecx,dword ptr ds:[edx*8]                           
00E9DCDF | mov edi,dword ptr ss:[ebp+C]                           
00E9DCE2 | mov eax,dword ptr ss:[ebp-8]                           
00E9DCE5 | lea ecx,dword ptr ds:[ecx+ecx*8]                       
00E9DCE8 | sub ecx,edx                                            
00E9DCEA | push ebx                                               
00E9DCEB | lea esi,dword ptr ds:[eax+ecx*4]                       
00E9DCEE | mov ecx,47                                             
00E9DCF3 | rep movsd                                              
00E9DCF5 | call dword ptr ds:[<&_ExFreePool at 4>]                   
00E9DCFB | mov al,1                                               
00E9DCFD | pop edi                                                
00E9DCFE | pop esi                                                
00E9DCFF | pop ebx                                                
00E9DD00 | mov esp,ebp                                            
00E9DD02 | pop ebp                                                
00E9DD03 | ret 8                                                  
--- snip ---

Caller to show internal error code getting translated to external 0xC000009A:

--- snip ---
...
00E58E9C  | push hardlock.EA1D28                               
00E58EA1  | mov eax,dword ptr ds:[<&_ExAllocatePoolWithTag at 12>]
00E58EA6  | push eax                                           
00E58EA7  | call hardlock.E9DC30           ; determine ntoskrnl load base       
00E58EAC  | xor ecx,ecx                                        
00E58EAE  | mov cl,al                                          
00E58EB0  | test ecx,ecx                                       
00E58EB2  | jne hardlock.E58EC2                                
00E58EB8  | mov eax,C000000D               ; failure                   
00E58EBD  | jmp hardlock.E58FE4                                
00E58EC2  | push 35316B48                                      
00E58EC7  | push 8C                                            
00E58ECC  | push 0                                             
00E58ECE  | call dword ptr ds:[<&_ExAllocatePoolWithTag at 12>]   
...
00E485B9  | push edi                                           
00E485BA  | pop edi                                            
00E485BB  | mov dword ptr ss:[ebp-C],C000009A ; returned to driver entry        
00E485C2  | test ebx,ebx                                       
00E485C4  | jb hardlock.E33E36                                 
--- snip ---

This driver uses another, cleaner method to find ntoskrnl.exe base address as
compared to https://bugs.winehq.org/show_bug.cgi?id=50201#c0 (which doesn't
rely on API / module lists)

It uses the address of 'ntoskrnl.ExAllocatePoolWithTag' API function to find
the module in range.

Load addresses at time of driver debugging:

--- snip ---
Base     Module         Path
00320000 sechost.dll    ...\lib\wine\sechost.dll    
00350000 hal.dll        ...\lib\wine\hal.dll        
00360000 msvcrt.dll     ...\lib\wine\msvcrt.dll     
00400000 winedevice.exe ...\lib\wine\winedevice.exe 
00410000 ucrtbase.dll   ...\lib\wine\ucrtbase.dll   
00BA0000 rpcrt4.dll     ...\lib\wine\rpcrt4.dll     
00E30000 hardlock.sys   C:\windows\system32\drivers\hardlock.sys
10000000 advapi32.dll   ...\lib\wine\advapi32.dll   
7B000000 kernelbase.dll ...\lib\wine\kernelbase.dll 
7B600000 kernel32.dll   ...\lib\wine\kernel32.dll   
7BC00000 ntdll.dll      ...\lib\wine\ntdll.dll      
82000000 ntoskrnl.exe   ...\lib\wine\ntoskrnl.exe   
--- snip ---

The dumped "fake" system modules list the driver sees. It corresponds to the
Wine sources.

--- snip ---
00A923A0  00000003  .... Modules count
00A923A4  00000000  .... Unused
00A923A8  00000000  .... Reserved1/2
00A923AC  10000000  .... ImageBaseAddress
00A923B0  00200000  .. . ImageSize
00A923B4  00000000  .... Flags
00A923B8  00000000  .... Index/Rank
00A923BC  00150001  .... LoadCount/NameOffset
00A923C0  7379535C  \Sys Name
00A923C4  526D6574  temR
00A923C8  5C746F6F  oot\
00A923CC  74737973  syst
00A923D0  32336D65  em32
00A923D4  6F746E5C  \nto
00A923D8  6E726B73  skrn
00A923DC  78652E6C  l.ex
00A923E0  00000065  e...
00A923E4  00000000  ....
...
00A924C0  00000000  .... Unused
00A924C4  00000000  .... Reserved1/2
00A924C8  10200000  .. . ImageBaseAddress
00A924CC  00200000  .. . ImageSize
00A924D0  00000000  .... Flags
00A924D4  00000001  .... Index/Rank
00A924D8  00150001  .... LoadCount/NameOffset
00A924DC  7379535C  \Sys Name
00A924E0  526D6574  temR
00A924E4  5C746F6F  oot\
00A924E8  74737973  syst
00A924EC  32336D65  em32
00A924F0  6C61685C  \hal
00A924F4  6C6C642E  .dll
00A924F8  00000000  ....
00A924FC  00000000  ....
00A92500  00000000  ....
00A92504  00000000  ....
...
00A925DC  00000000  .... Unused
00A925E0  00000000  .... Reserved1/2
00A925E4  10400000  .. at . ImageBaseAddress
00A925E8  00200000  .. . ImageSize
00A925EC  00000000  .... Flags
00A925F0  00000002  .... Index/Rank
00A925F4  001D0001  .... LoadCount/NameOffset
00A925F8  7379535C  \Sys Name
00A925FC  526D6574  temR
00A92600  5C746F6F  oot\
00A92604  74737973  syst
00A92608  32336D65  em32
00A9260C  6972645C  \dri
00A92610  73726576  vers
00A92614  756F6D5C  \mou
00A92618  676D746E  ntmg
00A9261C  79732E72  r.sy
00A92620  00000073  s...
00A92624  00000000  ....
...
--- snip ---

Wine source:

https://source.winehq.org/git/wine.git/blob/cbca9f847f60773b4e7e5408f6a079f4896c5c1e:/dlls/ntdll/unix/system.c#l2326

--- snip ---
2326     case SystemModuleInformation:
2327     {
2328         /* FIXME: return some fake info for now */
2329         static const char *fake_modules[] =
2330         {
2331             "\\SystemRoot\\system32\\ntoskrnl.exe",
2332             "\\SystemRoot\\system32\\hal.dll",
2333             "\\SystemRoot\\system32\\drivers\\mountmgr.sys"
2334         };
2335 
2336         ULONG i;
2337         SYSTEM_MODULE_INFORMATION *smi = info;
2338 
2339         len = offsetof( SYSTEM_MODULE_INFORMATION,
Modules[ARRAY_SIZE(fake_modules)] );
2340         if (len <= size)
2341         {
2342             memset( smi, 0, len );
2343             for (i = 0; i < ARRAY_SIZE(fake_modules); i++)
2344             {
2345                 SYSTEM_MODULE *sm = &smi->Modules[i];
2346                 sm->ImageBaseAddress = (char *)0x10000000 + 0x200000 * i;
2347                 sm->ImageSize = 0x200000;
2348                 sm->LoadOrderIndex = i;
2349                 sm->LoadCount = 1;
2350                 strcpy( (char *)sm->Name, fake_modules[i] );
2351                 sm->NameOffset = strrchr( fake_modules[i], '\\' ) -
fake_modules[i] + 1;
2352             }
2353             smi->ModulesCount = i;
2354         }
2355         else ret = STATUS_INFO_LENGTH_MISMATCH;
2356 
2357         break;
2358     }
2359 
2360     case SystemModuleInformationEx:
2361     {
2362         /* FIXME: return some fake info for now */
2363         static const char *fake_modules[] =
2364         {
2365             "\\SystemRoot\\system32\\ntoskrnl.exe",
2366             "\\SystemRoot\\system32\\hal.dll",
2367             "\\SystemRoot\\system32\\drivers\\mountmgr.sys"
2368         };
2369 
2370         ULONG i;
2371         RTL_PROCESS_MODULE_INFORMATION_EX *module_info = info;
2372 
2373         len = sizeof(*module_info) * ARRAY_SIZE(fake_modules) +
sizeof(module_info->NextOffset);
2374         if (len <= size)
2375         {
2376             memset( info, 0, len );
2377             for (i = 0; i < ARRAY_SIZE(fake_modules); i++)
2378             {
2379                 SYSTEM_MODULE *sm = &module_info[i].BaseInfo;
2380                 sm->ImageBaseAddress = (char *)0x10000000 + 0x200000 * i;
2381                 sm->ImageSize = 0x200000;
2382                 sm->LoadOrderIndex = i;
2383                 sm->LoadCount = 1;
2384                 strcpy( (char *)sm->Name, fake_modules[i] );
2385                 sm->NameOffset = strrchr( fake_modules[i], '\\' ) -
fake_modules[i] + 1;
2386                 module_info[i].NextOffset = sizeof(*module_info);
2387             }
2388             module_info[ARRAY_SIZE(fake_modules)].NextOffset = 0;
2389         }
2390         else ret = STATUS_INFO_LENGTH_MISMATCH;
2391 
2392         break;
2393     }
--- snip ---

$ sha1sum HASPDINST_7.32.exe 
96520c7e2bdc40a232daca01d6edbd7aa3f162ba  HASPDINST_7.32.exe

$ du -sh HASPDINST_7.32.exe 
16M    HASPDINST_7.32.exe

$ wine --version
wine-5.22-196-g2001705a3f0

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