[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