http://bugs.winehq.org/show_bug.cgi?id=28001
Summary: World War One Gold demo fails to start: 'Clock manipulation detected!' [Exe Cryptor protection] Product: Wine Version: 1.3.26 Platform: x86 URL: http://www.fileplanet.com/212341/210000/fileinfo/World -War-One:-Gold-Edition-Demo OS/Version: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown AssignedTo: wine-bugs@winehq.org ReportedBy: gyebro69@gmail.com
After starting the trial version of the game I'm getting the following error message: 'Clock manipulation detected!' Afterwards the game simply quits. Not a single line appears in the terminal during the game execution.
Normally (under Windows), a trial reminder should appear, showing something like 'You have xx days left'.
The problem is probably due to the fact that the game executable is protected by ExeCryptor. Protection Id tells us the facts:
Scanning -> C:\Program Files\World War One Gold\WW1.exe File Type : 32-Bit Exe (Subsystem : Win GUI / 2), Size : 9533952 (0917A00h) Byte(s) [File Heuristics] -> Flag : 00000000000000011100000000100011 (0x0001C023) [!] EXE Cryptor v2.20 - v2.40 detected ! [!] Possible CD/DVD-Key or Serial Check -> trial period [CompilerDetect] -> Visual C++ 8.0 (Visual Studio 2005) - Scan Took : 1.459 Second(s)
Note: the size of the demo for WWI Gold is huge (1.4 GB). One can easily reproduce the reported problem by starting the trial version of Universal Mechanic (uses the same protection method, only 88 MB): http://www.umlab.ru/download/60/eng/um60.exe (after installation launch either UMInput.exe or UmSimul.exe to get the same error message).
Fedora 15 x86
http://bugs.winehq.org/show_bug.cgi?id=28001
GyB gyebro69@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download, obfuscation
--- Comment #1 from GyB gyebro69@gmail.com 2011-08-06 10:11:10 CDT --- Added some keywords.
http://bugs.winehq.org/show_bug.cgi?id=28001
Bruno Jesus 00cpxxx@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |00cpxxx@gmail.com
--- Comment #2 from Bruno Jesus 00cpxxx@gmail.com 2011-08-06 18:05:33 CDT --- I tested the Universal Mechanic and could reproduce the bug but it seems to be closely related to timing because when I tried a WINEDEBUG=+all redirecting the output to a file the application started correctly. I guess it was due to the delays introduced by the file writing (?).
http://bugs.winehq.org/show_bug.cgi?id=28001
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW CC| |focht@gmx.net Component|-unknown |wineserver Summary|World War One Gold demo |ExeCryptor protected |fails to start: 'Clock |apps/games complain with |manipulation detected!' |'Clock manipulation |[Exe Cryptor protection] |detected!' (World War One | |Gold demo, Universal | |Mechanic) Ever Confirmed|0 |1
--- Comment #3 from Anastasius Focht focht@gmx.net 2012-01-25 18:02:06 CST --- Hello,
lots of anti-debugging trickery. It seems the author of the protection really hates Ollydbg ;-)
The protection stores the trial/license data encrypted in registry (location depends on packaged app).
"bad" case = wineserver NOT running, everything gets bootstrapped through app start (services/winemenubuilder).
"good" case = wineserver and services already running, winemenubuilder process(es) exited.
--- snip --- ... 0039:Call TLS callback (proc=0x11b729f,module=0x400000,reason=THREAD_ATTACH,reserved=0) 0039:Ret TLS callback (proc=0x11b729f,module=0x400000,reason=THREAD_ATTACH,reserved=0) 0039:Starting thread proc 0xa0a450 (arg=0x32fc3c) 0039:Call KERNEL32.GetTickCount() ret=009f13a6 0039:Ret KERNEL32.GetTickCount() retval=00001022 ret=009f13a6 0039:Call KERNEL32.GetCurrentProcess() ret=009d50bc 0039:Ret KERNEL32.GetCurrentProcess() retval=ffffffff ret=009d50bc 0039:Call KERNEL32.GetProcessTimes(ffffffff,0032fca0,0032fc98,0032fc98,0032fc98) ret=009d50c2 0039:Ret KERNEL32.GetProcessTimes() retval=00000001 ret=009d50c2 0039:Call TLS callback (proc=0x11b729f,module=0x400000,reason=THREAD_DETACH,reserved=0) 0039:Ret TLS callback (proc=0x11b729f,module=0x400000,reason=THREAD_DETACH,reserved=0) ... 0024:Ret KERNEL32.WaitForSingleObject() retval=00000000 ret=009d8d2b 0024:Call KERNEL32.CloseHandle(00000050) ret=009d8d30 0024:Ret KERNEL32.CloseHandle() retval=00000001 ret=009d8d30 0024:Call KERNEL32.CreateThread(00000000,00000000,00a0a450,0032fc3c,00000000,0032fc38) ret=00df27fe 0024:Ret KERNEL32.CreateThread() retval=00000050 ret=00df27fe 0024:Call KERNEL32.WaitForSingleObject(00000050,ffffffff) ret=009d8d2b ... 003a:Call TLS callback (proc=0x11b729f,module=0x400000,reason=THREAD_ATTACH,reserved=0) 003a:Ret TLS callback (proc=0x11b729f,module=0x400000,reason=THREAD_ATTACH,reserved=0) 003a:Starting thread proc 0xa0a450 (arg=0x32fc3c) 003a:Call KERNEL32.FileTimeToLocalFileTime(0032fc8c,0032fc8c) ret=00df51ac 003a:Ret KERNEL32.FileTimeToLocalFileTime() retval=00000001 ret=00df51ac 003a:Call KERNEL32.FileTimeToDosDateTime(0032fc8c,0032fc76,0032fc74) ret=009d7b4b 003a:Ret KERNEL32.FileTimeToDosDateTime() retval=00000001 ret=009d7b4b 003a:Call TLS callback (proc=0x11b729f,module=0x400000,reason=THREAD_DETACH,reserved=0) 003a:Ret TLS callback (proc=0x11b729f,module=0x400000,reason=THREAD_DETACH,reserved=0) ... 0024:Call advapi32.RegOpenKeyExA(80000001,0032fb90 "SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved\{0AACAEAC-62E8-F4E5-C80B-4E70445C5704}",00000000,00000001,0032fca0) ret=00a03492 0024:Ret advapi32.RegOpenKeyExA() retval=00000000 ret=00a03492 0024:Call advapi32.RegQueryValueExA(00000050,0032fa90 "iaababkngnelnefogn",00000000,0032fc94,00000000,0032fc98) ret=009c776a 0024:Ret advapi32.RegQueryValueExA() retval=00000000 ret=009c776a 0024:Call advapi32.RegQueryValueExA(00000050,0032fa90 "iaababkngnelnefogn",00000000,0032fc94,0032f548,0032fc98) ret=009e222b 0024:Ret advapi32.RegQueryValueExA() retval=00000000 ret=009e222b ... 0024:Call advapi32.RegCreateKeyExA(80000001,0032fb98 "SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved\{0AACAEAC-62E8-F4E5-C80B-4E70445C5704}",00000000,00000000,00000000,00000002,00000000,0032fc9c,0032f520) ret=009e981b 0024:Ret advapi32.RegCreateKeyExA() retval=00000000 ret=009e981b 0024:Call advapi32.RegSetValueExA(00000050,0032fa98 "hacpgngcfdkfdnmm",00000000,00000003,0032f950,00000015) ret=009e3e55 0024:Ret advapi32.RegSetValueExA() retval=00000000 ret=009e3e55 --- snip ---
There are lots of threads created which execute short snippets of code (anti-debugging tricks/date/timing checks, etc.) These might not even call any Windows API (through obfuscated thunks).
Most likely the author wanted to prevent easy use of hardware breakpoints (per thread context). If the debugger supports break-on-thread-create event (halt in new thread entry) one can of course circumvent this technique easily (hooking Create(Remote)Thread and bpx on entry address parameter also works).
The culprit actually lies in the GetProcessTimes() API call, executed in one of these thread snippets.
I made a +server trace for both cases which gives better info:
"good" (wineserver prestarted):
--- snip --- ... 0039: init_thread( unix_pid=18227, unix_tid=18250, debug_level=1, teb=7ffd4000, entry=00a0a450, reply_fd=23, wait_fd=25, cpu=x86 ) 0039: init_thread() = 0 { pid=0023, tid=0039, server_start=1ccdbb19a715bb0 (-11.0328730), info_size=0, version=430, all_cpus=00000001 } 0024: select( flags=4, cookie=0032f99c, signal=0000, prev_apc=0000, timeout=infinite, result={}, handles={0050} ) 0024: select() = PENDING { timeout=infinite, call={APC_NONE}, apc_handle=0000 } 0039: get_process_info( handle=ffffffff ) 0039: get_process_info() = 0 { pid=0023, ppid=0000, affinity=0000000f, peb=7ffdf000, start_time=1ccdbb1a0bab52a (-0.4873940), end_time=0, exit_code=259, priority=2, cpu=x86, debugger_present=0 } ... 0039: *killed* exit_code=0 --- snip ---
"bad" (no wineserver prior, full bootstrap with app):
Even in this small snippet I had to filter out interleaving messages from different threads/processes due to parallel start of services/winemenubuilder.
--- snip --- ... 0037:Call KERNEL32.GetProcessTimes(ffffffff,0032fca0,0032fc98,0032fc98,0032fc98) ret=009d50c2 0037: get_process_info( handle=ffffffff ) 0037: get_process_info() = 0 { pid=0008, ppid=0000, affinity=0000000f, peb=7ffdf000, start_time=1ccdbb1f4271956 (-0.8753710), end_time=0, exit_code=259, priority=2, cpu=x86, debugger_present=0 } 0037:Ret KERNEL32.GetProcessTimes() retval=00000001 ret=009d50c2 0037:Call TLS callback (proc=0x11b729f,module=0x400000,reason=THREAD_DETACH,reserved=0) 0037:Ret TLS callback (proc=0x11b729f,module=0x400000,reason=THREAD_DETACH,reserved=0) ... 0037: *killed* exit_code=0 --- snip ---
The culprit is the process' "start_time" field: -0.4873940 vs. -0.8753710 Basically the time between recorded "birth" in wineserver and reaching that code snippet that retrieves the process start time is too long when fully bootstrapping (no wineserver running prior).
For testing purpose I moved the "process->start_time" field initialization (current_time) to "init_process_done" in wineserver (when the process is fully initialized). This helped. Even full bootstrap now displays the registration dialog.
--- snip --- 0037: get_process_info( handle=ffffffff ) 0037: get_process_info() = 0 { pid=0008, ppid=0000, affinity=0000000f, peb=7ffdf000, start_time=1ccdbb9cd1207a6 (-0.3414070), end_time=0, exit_code=259, priority=2, cpu=x86, debugger_present=0 } --- snip ---
-> -0.3414070
Maybe Alexandre can comment if such a change, that is setting "birth" time a bit later in wineserver might be feasible. This is all Wine internal process initialization hence the child doesn't really know what happened during "birth" and how long, before the first code in entry/tls callback is executed.
Otherwise this bug is basically a WONTFIX.
Workaround: start wineserver through other apps prior running the app/game to get a faster startup phase.
$ sha1sum um60.exe 245ee74f099671b25cdf4d50321d51cc63bea4e4 um60.exe
$ wine --version wine-1.3.37-413-g5f42f7d
Regards
http://bugs.winehq.org/show_bug.cgi?id=28001
--- Comment #4 from Anastasius Focht focht@gmx.net --- Hello folks,
revisiting, still present.
--- snip --- $ pwd /home/focht/.wine/drive_c/Program Files/UM Software Lab/UM 6.0.0/bin
$ wineserver -k ; WINEDEBUG=+msgbox wine ./UMInput.exe trace:msgbox:MSGBOX_OnInit L"Clock manipulation detected!" --- snip ---
Setting process start time in 'init_process_done' still fixes this (as proposed in my previous comment #3).
Source: http://source.winehq.org/git/wine.git/blob/1e78c99388c61d353cf60787eac641532...
$ sha1sum um60.exe e39442618f0d8afc7289ff455ecdd939d4c01bcd um60.exe
$ du -sh um60.exe 87M um60.exe
$ wine --version wine-1.7.8-248-g8dd9c61
Regards
http://bugs.winehq.org/show_bug.cgi?id=28001
Saulius K. saulius2@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |saulius2@gmail.com
http://bugs.winehq.org/show_bug.cgi?id=28001
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |d506e59dabc985be0a24c471121 | |02af409a25b39 Status|NEW |RESOLVED Resolution|--- |FIXED
--- Comment #5 from Anastasius Focht focht@gmx.net --- Hello folks,
this is fixed by commit http://source.winehq.org/git/wine.git/commitdiff/d506e59dabc985be0a24c471121...
Thanks Austin
Regards
https://bugs.winehq.org/show_bug.cgi?id=28001
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #6 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 1.7.9.