https://bugs.winehq.org/show_bug.cgi?id=44817
Bug ID: 44817 Summary: Some software protection schemes need ntdll.NtSetLdtEntries implementation Product: Wine Version: 3.4 Hardware: x86-64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: ntdll Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
to track https://github.com/wine-staging/wine-staging/tree/master/patches/ntdll-NtSet...
The stub was added with bug 26268 ("Multiple applications need ntdll.ZwSetLdtEntries stub (kwiksupport.me, Ragnarok Online patcher)").
Unfortunately there is no further information/details *which* copy-protection scheme needs and actual implementation. No applications/games are mentioned.
--- quote --- 1. Some copy protections call NtSetLdtEntries(0x000f) and then with 'retf' instruction jump to that selector expecting that it works (the tests show that NtSetLdtEntries(0x000f,0x001f) should succeed). In order to make this work a limitation to set only selectors > LDT_FIRST_ENTRY (512) in wine_ldt_set_entry() was removed.
2. wine_ldt_set_entry() was made to always mark modified selector entries as WINE_LDT_FLAGS_ALLOCATED, otherwise get_selector_entry() server call returns entries without that flag set and NtQueryInformationThread(ThreadDescriptorTableEntry) fails. --- quote ---
$ wine --version wine-3.4
Regards
https://bugs.winehq.org/show_bug.cgi?id=44817
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |STAGED Keywords| |obfuscation, patch Staged patchset| |https://github.com/wine-sta | |ging/wine-staging/tree/mast | |er/patches/ntdll-NtSetLdtEn | |tries
https://bugs.winehq.org/show_bug.cgi?id=44817
tokktokk fdsfgs@krutt.org changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |fdsfgs@krutt.org
https://bugs.winehq.org/show_bug.cgi?id=44817
--- Comment #1 from Anastasius Focht focht@gmx.net --- Created attachment 71582 --> https://bugs.winehq.org/attachment.cgi?id=71582 VMWare detection test app 'vmgpftest-x86.exe' with source
Hello folks,
revisiting. I've found some real-world code snippet that mimics the sequence described by Michael. It's probably used in application virtualization / sand-boxing schemes and malware that employ virtualization detection.
https://web.archive.org/web/20070108201905/https://eeyeresearch.typepad.com/...
--- quote --- September 19, 2006 Another VMWare Detection
Derek Soeder, uber researcher and code ninja extraordinaire posted this over at Rootkit.Com without the code so we thought we would add it here.
We stumbled on another way of detecting VMware in emulation mode while writing that PiXiE network boot virus, not very elegant but it works...
Basically, VMware emulates near execution transfers outside the CS: limit incorrectly, in that it completes the transfer (changes EIP and modifies the stack when applicable) before raising the General Protection Fault. Physical processors raise the fault before actually doing anything.
To test this in Windows user-mode, create a < 4GB code segment (ZwSetLdtEntries), then transfer into it (change CS), and with an exception handler in place, try doing e.g. a near RET out of it (like PUSH -1 / RET). If you're running natively (or in accelerated mode in VMware), then EIP will still be within the CS: limits and ESP will remain unchanged; if you're running in emulation mode (ring-0 or with acceleration disabled), EIP will be above the CS: limit and the return address will have been popped.
(Far execution transfers are emulated faithfully, so that's why you want to do the near transfer from within the short code segment. Trying to do a CALL FAR seg:ofs to outside the short segment, from within the default flat ring-3 code segment, would raise a GPF with CS:EIP and ESP unmodified, the same between native execution and emulation.)
If you use a technique like this in combination with Joanna's SIDT trick, that should give you comprehensive detection. BTW haven't tested this on anything except VMware.
We ran into this quirk because we were trying to make OSLOADER raise a GPF, so yeah, it's not just a feature, it's a bug =] I wonder if it would interfere with any of the execution protection software that relies upon a short CS and a high-addressed stack?
This trick only works if VMware's running in emulation mode, which is the case if the code is running privileged, or if acceleration is disabled (VM -> Settings -> Options, Advanced: Disable acceleration). Joanna's SIDT technique only works if VMware is not running in emulation mode, so if you combine these two, you should get "comprehensive" VMware detection.
I figure that VMware would consider any form of unfaithful emulation as a "bug", so this might be fixed in some current or future version of VMware. --- quote ---
Another copy of it which includes more checks:
https://web.archive.org/web/20220109171838/https://www.aldeid.com/wiki/Scoop...
The attached tarball contains the original source code with the following modifications:
(1) replaced the code to retrieve the highest user mode address with a constant since Wine doesn't set KSHARED_USER_DATA+0x2B4
--- snip --- #define EndUserModeAddress (*(UINT_PTR*)0x7FFE02B4) --- snip ---
(2) handled native API failure
(3) improved diagnostic output (print addresses)
The tarball also contains a prebuilt 32-bit x86 executable for testing. Built with debug info under Wine using:
https://github.com/mstorsjo/msvc-wine
--- snip --- $ tar tvf vmgpftest-bug44817.tar
drwxrwxr-x focht/focht 0 2022-01-09 18:35 vmgpftest-bug44817/ -rw-rw-r-- focht/focht 1636 2022-01-09 18:35 vmgpftest-bug44817/vmgpftest.c -rwxrwxr-x focht/focht 24576 2022-01-09 18:35 vmgpftest-bug44817/vmgpftest-x86.exe -rw-rw-r-- focht/focht 708608 2022-01-09 18:35 vmgpftest-bug44817/vmgpftest-x86.pdb --- snip ---
$ sha1sum vmgpftest-x86.exe cd0b3bfd15075462ea90d9ebbf341af8df7c506a vmgpftest-x86.exe
Some Virus scanners detect the executable as malware which is kinda expected because of the unusual occurrence of native API 'ntdll.NtSetLdtEntries':
https://www.virustotal.com/gui/file/7d3abb621177f6d905cc9931dad012c48137b784...
You can always rebuild from source if you are scared ;-)
With current Wine:
--- snip --- $ wine ./vmgpftest-x86.exe ZwSetLdtEntries() failed: c000011a --- snip ---
With Wine-Staging patch(es):
--- snip --- $ WINEDEBUG=+seh,+relay wine ./vmgpftest-x86.exe >>log.txt 2>&1 ... 0024:Call KERNEL32.GetProcAddress(7bc00000,0040602c "ZwSetLdtEntries") ret=00401491 0024:Ret KERNEL32.GetProcAddress() retval=7bc09a10 ret=00401491 0024:Call ntdll.ZwSetLdtEntries(0000000f,c7fa000000ffef,00000000,000000000) ret=004014d2 0024:Ret ntdll.ZwSetLdtEntries() retval=00000000 ret=004014d2 0024:trace:seh:dispatch_exception code=c0000005 flags=0 addr=00401502 ip=00401502 tid=0024 0024:trace:seh:dispatch_exception info[0]=00000000 0024:trace:seh:dispatch_exception info[1]=ffffffff 0024:warn:seh:dispatch_exception EXCEPTION_ACCESS_VIOLATION exception (code=c0000005) raised 0024:trace:seh:dispatch_exception eax=ffffffff ebx=7ffd1000 ecx=00000004 edx=00000000 esi=0041aa50 edi=004297f0 0024:trace:seh:dispatch_exception ebp=0032fec0 esp=0032fe88 cs=000f ss=002b ds=002b es=002b fs=0063 gs=006b flags=00010286 0024:trace:seh:call_stack_handlers calling handler at 00401649 code=c0000005 flags=0 0024:Call ucrtbase._except_handler4_common(00406080,004010b4,0032fce8,0032feb0,0032fa04,0032f9cc) ret=00401672 0024:trace:seh:_except_handler4_common exception c0000005 flags=0 at 00401502 handler=00401649 0032FA04 0032F9CC cookie=2f7ee785 scope table=00405618 cookies=-2/0,-56/0 0024:trace:seh:_except_handler4_common level 0 prev -2 filter 0040150D 0024:trace:seh:_except_handler4_common filter returned EXECUTE_HANDLER 0024:trace:seh:__DestructExceptionObject (0032FCE8) 0024:trace:seh:_global_unwind2 (0032FEB0) 0024:trace:seh:__regs_RtlUnwind code=c0000027 flags=2 0024:trace:seh:__regs_RtlUnwind eax=00000000 ebx=0032feb0 ecx=7bc0be1c edx=0000002a esi=0032feb0 edi=00000000 0024:trace:seh:__regs_RtlUnwind ebp=0032f740 esp=0032f73c eip=00371b23 cs=0023 ds=002b fs=0063 gs=006b flags=00000206 0024:trace:seh:__regs_RtlUnwind calling handler at 7BC48370 code=c0000027 flags=2 0024:trace:seh:__regs_RtlUnwind handler at 7BC48370 returned 1 0024:trace:seh:msvcrt_local_unwind4 (0032FEB0,0,0) 0024:trace:seh:msvcrt_local_unwind4 unwound OK 0024:trace:seh:_except_handler4_common __finally block 0040151A 0024:Call KERNEL32.GetModuleHandleW(00000000) ret=00402159 0024:Ret KERNEL32.GetModuleHandleW() retval=00400000 ret=00402159 0024:Call ucrtbase.exit(00000000) ret=004018fd ... --- snip ---
$ wine --version wine-7.0-rc5
Regards
https://bugs.winehq.org/show_bug.cgi?id=44817
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|Some software protection |Some software protection |schemes need |schemes need |ntdll.NtSetLdtEntries |ntdll.NtSetLdtEntries to |implementation |modify reserved LDT entries