[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