[Bug 28001] ExeCryptor protected apps/games complain with 'Clock manipulation detected!' (World War One Gold demo, Universal Mechanic)

wine-bugs at winehq.org wine-bugs at winehq.org
Wed Jan 25 18:02:06 CST 2012


http://bugs.winehq.org/show_bug.cgi?id=28001

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
                 CC|                            |focht at 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 at 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

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
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