[Bug 45510] Sentinel HASP Runtime v6.6-7.8 driver installer reports Windows error 1053 when starting the 32-bit hardlock kernel driver service (custom imports resolver fails to locate some ntoskrnl exports)
WineHQ Bugzilla
wine-bugs at winehq.org
Sun Nov 29 04:43:16 CST 2020
https://bugs.winehq.org/show_bug.cgi?id=45510
--- Comment #15 from Anastasius Focht <focht at gmx.net> ---
Hello folks,
addendum just for documentation, how the imports resolver works in a nutshell.
The obfuscated driver uses a technique called API hashing. This technique is
also used by lots of malware to disguise their actions.
Driver IAT dumped from memory with most imports already resolved except the
last few entries to test the algorithm. Initially the table contains only the
32-bit hashes.
--- snip ---
0000000000D77280 0000000000D91850 hal.HalGetBusDataByOffset
0000000000D77288 0000000000000000
0000000000D77290 0000000000332F80 ntoskrnl.RtlRandom
0000000000D77298 000000000032BE70 ntoskrnl.KeWaitForSingleObject
0000000000D772A0 000000000032C8D0 ntoskrnl.KeDelayExecutionThread
0000000000D772A8 000000000032C040 ntoskrnl.KeSetEvent
0000000000D772B0 0000000000323CD0 ntoskrnl.MmIsAddressValid
0000000000D772B8 0000000000321FF0 ntoskrnl.IofCallDriver
0000000000D772C0 000000000032BF10 ntoskrnl.KeInitializeEvent
0000000000D772C8 00000000003244B0 ntoskrnl.ObfDereferenceObject
0000000000D772D0 0000000000313598 ntoskrnl.__wine_stub_KeInsertQueueDpc
0000000000D772D8 000000000032C230 ntoskrnl.KeClearEvent
0000000000D772E0 0000000000324D80 ntoskrnl.KeSetTargetProcessorDpc
0000000000D772E8 0000000000324CD0 ntoskrnl.KeInitializeDpc
0000000000D772F0 0000000000323420 ntoskrnl.KeQueryActiveProcessors
0000000000D772F8 0000000000330DF0 ntoskrnl.__C_specific_handler
0000000000D77300 0000000000323FB0 ntoskrnl.MmUnlockPages
0000000000D77308 0000000000323DD0 ntoskrnl.MmMapLockedPagesSpecifyCache
0000000000D77310 000000000031FD30 ntoskrnl.IoFreeMdl
0000000000D77318 0000000000323F10 ntoskrnl.MmProbeAndLockPages
0000000000D77320 000000000031FE50 ntoskrnl.IoAllocateMdl
0000000000D77328 0000000000331D10 ntoskrnl.NtDeleteValueKey
0000000000D77330 0000000000331C80 ntoskrnl.NtCreateKey
0000000000D77338 0000000000332380 ntoskrnl.NtSetValueKey
0000000000D77340 0000000000331D00 ntoskrnl.NtDeleteKey
0000000000D77348 0000000000331D60 ntoskrnl.NtEnumerateKey
0000000000D77350 0000000000331D70 ntoskrnl.NtEnumerateValueKey
0000000000D77358 00000000003229C0 ntoskrnl.ExAllocatePoolWithTag
0000000000D77360 00000000003320D0 ntoskrnl.NtQueryKey
0000000000D77368 0000000000331EF0 ntoskrnl.NtOpenKey
0000000000D77370 0000000000321950 ntoskrnl.IoDeleteDevice
0000000000D77378 0000000000322540 ntoskrnl.IoUnregisterShutdownNotification
0000000000D77380 0000000000323FF0 ntoskrnl.MmUnmapIoSpace
0000000000D77388 0000000000323D30 ntoskrnl.MmMapIoSpace
0000000000D77390 0000000000322890 ntoskrnl.IofCompleteRequest
0000000000D77398 0000000000311990
ntoskrnl.__wine_stub_ExInterlockedInsertTailList
0000000000D773A0 000000000031F530 ntoskrnl.IoGetCurrentProcess
0000000000D773A8 0000000000312D10
ntoskrnl.__wine_stub_IoRegisterLastChanceShutdownNotification
0000000000D773B0 0000000000322500 ntoskrnl.IoRegisterShutdownNotification
0000000000D773B8 000000000031ED40 ntoskrnl.ObReferenceObjectByHandle
0000000000D773C0 0000000000324600 ntoskrnl.PsCreateSystemThread
0000000000D773C8 0000000000325280 ntoskrnl.KeLeaveCriticalRegion
0000000000D773D0 000000000032EA20 ntoskrnl.ExReleaseResourceLite
0000000000D773D8 000000000032D960 ntoskrnl.ExAcquireResourceSharedLite
0000000000D773E0 0000000000325230 ntoskrnl.KeEnterCriticalRegion
0000000000D773E8 000000000032D550 ntoskrnl.ExAcquireResourceExclusiveLite
0000000000D773F0 000000000032D450 ntoskrnl.ExInitializeResourceLite
0000000000D773F8 000000000032D4C0 ntoskrnl.ExDeleteResourceLite
0000000000D77400 00000000003314C0 ntoskrnl.toupper
0000000000D77408 0000000000323550 ntoskrnl.KeSetPriorityThread
0000000000D77410 000000000032D0F0 ntoskrnl.ExInterlockedRemoveHeadList
0000000000D77418 00000000003292C0 ntoskrnl.IoGetDeviceProperty
0000000000D77420 0000000000325350 ntoskrnl.KeBugCheckEx
0000000000D77428 000000007DC7C8B3 hash1
0000000000D77430 00000000F8BD1FE5 hash2
0000000000D77438 00000000B061FF53 hash3
0000000000D77440 00000000D8F8AA3E hash4
0000000000D77448 0000000000000000
0000000000D77450 0000000000000000
0000000000D77458 0000000000000000
--- snip ---
I won't bother you with the disassembly of the routine because its obfuscated.
If you are interested:
--- snip ---
...
0000000000D803E1 | call aksfridge.D802A2 | calc_hash()
0000000000D803E6 | jmp aksfridge.D803F4 | EAX = 32-bit hash
0000000000D803F4 | cmp eax,esi |
0000000000D803F6 | je aksfridge.D80437 |
--- snip ---
--- 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 ---
The 32-bit and 64-bit driver uses the same algorithm / 32-bit API hashes.
I turned the driver's API hashing function into a piece of Python code.
'aksfridge_hash_api.py':
--- snip ---
#!/usr/bin/env python
import sys
def to_hash(str):
hash_val = 5
for i in range(len(str)):
hash_val = ror(hash_val, 7, 32)
hash_val += ord(str[i])
return hash_val
# Rotate right: 0b1001 --> 0b1100
ror = lambda val, r_bits, max_bits: \
((val & (2**max_bits-1)) >> r_bits%max_bits) | \
(val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))
# check to_hash() working with known correct hashes
test_hash1 = to_hash("CcMdlWriteComplete")
assert test_hash1 == 0x73F2510A
test_hash2 = to_hash("CcPinMappedData")
assert test_hash2 == 0x238B94BB
for api_name in sys.argv[1:]:
hash = to_hash(api_name)
print("{} = 0x{:X}".format(api_name, hash))
--- snip ---
The hashing is lossy, hence there is no "api-name-from-hash" functionality.
That's not a problem - simply hash all known ntoskrnl exports and lookup the
value. That's what the driver essentially does. If Wine's ntoskrnl.exe doesn't
export the API (commented out in .spec file or missing) then the driver would
fail/crash at one point.
Download a reasonable complete/up-to-date 'ntoskrnl.def' from whatever Github
repo:
https://github.com/msys2-contrib/mingw-w64/blob/master/mingw-w64-crt/lib64/ntoskrnl.def
--- snip ---
$ wget
https://raw.githubusercontent.com/msys2-contrib/mingw-w64/master/mingw-w64-crt/lib64/ntoskrnl.def
--- snip ---
Now feed the content of the .def file to the script. Each line of the input
file is converted into a script argument using "$(echo $(cat xxx))". The script
doesn't handle invalid input / non-API functions. It just treats everything as
string for simplicity.
It prints the calculated hashes for each string argument:
--- snip ---
$ ./aksfridge_hash_api.py $(echo $(cat ntoskrnl.def))
...
AlpcGetHeaderSize = 0xB8450BA0
AlpcGetMessageAttribute = 0xEC22F2AA
AlpcInitializeMessageAttribute = 0x69D899AC
CcCanIWrite = 0x318059A6
CcCoherencyFlushAndPurgeCache = 0x5254F917
CcCopyRead = 0xF3787B88
CcCopyWrite = 0x320759AC
...
wcsspn = 0xC30F9EAD
wcsstr = 0xCB0F9EB1
wcstombs = 0x3EB304C2
wcstoul = 0x698227A9
wctomb = 0xBCFFA6A1
--- snip ---
Back in the old days when Wine's 'ntoskrnl.exe' exports were less complete and
one API hash couldn't be found, you'd simply:
--- snip ---
$ ./aksfridge_hash_api.py $(echo $(cat ntoskrnl.def)) | grep 7DC7C8B3
ZwQueryValueKey = 0x7DC7C8B3
--- snip ---
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