[Bug 47052] New: MRAC Anti-Cheat (My.Com Warface) fails to start game process, 'ntoskrnl.exe.ObReferenceObjectByHandle' fails to lookup event handles created by MRAC service process

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Apr 20 07:43:53 CDT 2019


https://bugs.winehq.org/show_bug.cgi?id=47052

            Bug ID: 47052
           Summary: MRAC Anti-Cheat (My.Com Warface) fails to start game
                    process, 'ntoskrnl.exe.ObReferenceObjectByHandle'
                    fails to lookup event handles created by MRAC service
                    process
           Product: Wine
           Version: 4.6
          Hardware: x86-64
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: wineserver
          Assignee: wine-bugs at winehq.org
          Reporter: focht at gmx.net
      Distribution: ---

Hello folks,

as it says. Continuation of bug 47044 , bug 47047 , bug 37355 ...

--- snip ---
$ pwd
/home/focht/.wine/drive_c/users/focht/Local Settings/Application
Data/GameCenter

$ WINEDEBUG=+seh,+loaddll,+process,+ntoskrnl,+ntdll,+relay,+server wine
./GameCenter.exe >>log.txt 2>&1
...
0009:Call KERNEL32.CreateProcessW(00000000,0a0a782c L"\"C:\\users\\focht\\Local
Settings\\Application Data\\GameCenter\\GameCenter.exe\" -job=2_8
-job_pipe=GameCenterV5_AAE21A18E0399D09F3AAF4874C40186E
-job_hint=GCJobGameLaunch",00000000,00000000,00000000,01000000,00000000,00000000,0033f0b8,0033f0a8)
ret=00435f19 
...
0009:trace:process:CreateProcessInternalW starting L"C:\\users\\focht\\Local
Settings\\Application Data\\GameCenter\\GameCenter.exe" as Win32 binary
(400000-da1000, x86) 
...
0009:trace:process:CreateProcessInternalW started process pid 00c8 tid 00c9
...
--- snip ---

MRAC service start:

--- snip ---
...
00cd:Call KERNEL32.CreateProcessW(00000000,00022e50
L"C:\\windows\\System32\\mracsvc.exe",00000000,00000000,00000000,00000400,00340000,00000000,00aaf130,00aaf000)
ret=7fe720baedc6 

00cd:trace:process:CreateProcessInternalW starting
L"C:\\windows\\System32\\mracsvc.exe" as Win64 binary (140000000-14106f000,
x86_64)
00cd: *fd* 39 <- 714
00cd: new_process( inherit_all=0, create_flags=00000400, socket_fd=39,
exe_file=0178, access=001fffff, cpu=x86_64, info_size=616,
objattr={rootdir=0000,attributes=00000000,sd={},name=L""}, info={... )
00cd: new_process() = 0 { info=017c, pid=00ce, handle=0180 }
00cd: new_thread( process=0180, access=001fffff, suspend=0, request_fd=-1,
objattr={rootdir=0000,attributes=00000000,sd={},name=L""} )
00cd: *fd* 0244 -> 716
...
00d7: init_thread( unix_pid=30363, unix_tid=30371, debug_level=1,
teb=7fffffe8c000, entry=7bcbd070, reply_fd=36, wait_fd=38, cpu=x86_64 )
00d7: init_thread() = 0 { pid=00ce, tid=00d7, server_start=1d4f7628a8ec3a2
(-43.8978330), info_size=0, version=580, all_cpus=00000003, suspend=0 } 
...
--- snip ---

MRAC service opening MRAC Anti-Cheat kernel service/driver:

NOTE: I've rearranged the log output in sequential request order to be more
readable. Trace messages from follow-up IOCTL issued by service process
overlapped/interleaved with kernel driver still processing IRP_MJ_CREATE.

--- snip ---
...
00d7:Call KERNEL32.CreateFileW(1400718a0
L"\\\\.\\mracdrv",00000000,00000003,00000000,00000003,00000000,00000000)
ret=14000b3f3
00d7:trace:ntdll:FILE_CreateFile handle=0x98e868 access=00100080
name=L"\\??\\mracdrv" objattr=00000040 root=(nil) sec=(nil) io=0x98e880
alloc_size=(nil) attr=00000000 sharing=00000003 disp=1 options=00000060
ea=(nil).0x00000000
00d7: open_file_object( access=00100080, attributes=00000040, rootdir=0000,
sharing=00000003, options=00000060, filename=L"\\??\\mracdrv" )
00dd: *wakeup* signaled=1
00d7: open_file_object() = 0 { handle=00a4 }
00dd:Ret  KERNEL32.WaitForMultipleObjectsEx() retval=00000001 ret=7f489a8c8c46
00d7:Ret  KERNEL32.CreateFileW() retval=000000a4 ret=14000b3f3
00dd: get_next_device_request( manager=0030, prev=0000, status=00000103 )
00dd: get_next_device_request() = 0 {
params={major=CREATE,access=00100080,sharing=00000003,options=00000060,device=00031e00},
next=0044, client_tid=0000, client_thread=00000000, in_size=0, out_size=0,
next_data={} }
...
00dd:trace:ntoskrnl:dispatch_create device 0x31e00 -> file 0x31f70
...
00dd:trace:ntoskrnl:IoAllocateIrp 1, 0
...
00dd:trace:ntoskrnl:IoInitializeIrp 0x32040, 280, 1
00dd:Call driver dispatch 0x1400291d4 (device=0x31e00,irp=0x32040)
...
00dd:Call ntoskrnl.exe.IofCompleteRequest(00032040,00000000) ret=140011ce1
...
00dd:trace:ntoskrnl:IofCompleteRequest 0x32040 0
00dd:trace:ntoskrnl:IoCompleteRequest 0x32040 0
00dd:trace:ntoskrnl:IoCompleteRequest calling 0x7f489a8c6330( 0x31e00, 0x32040,
0x44 )
00dd: set_irp_result( handle=0044, status=00000000, size=0, file_ptr=00031f70,
data={} )
00dd: set_irp_result() = 0
00dd:trace:ntoskrnl:IoCompleteRequest CompletionRoutine returned 0
00dd:trace:ntoskrnl:IoFreeIrp 0x32040
...
00dd:Ret  ntoskrnl.exe.IofCompleteRequest() retval=00000001 ret=140011ce1
...
00dd:Ret  driver dispatch 0x1400291d4 (device=0x31e00,irp=0x32040)
retval=00000000
...
--- snip ---

MRAC service creates an event and passes the handle to the MRAC Anti-Cheat
kernel service/driver via private IOCTL:

--- snip ----
...
00d7:Call KERNEL32.CreateEventW(00000000,00000001,00000000,00000000)
ret=14000b42c
00d7:Call ntdll.NtCreateEvent(0098e998,001f0003,0098e9b0,00000000,00000000)
ret=7b4a76e3
00d7: create_event( access=001f0003, manual_reset=1, initial_state=0,
objattr={rootdir=0000,attributes=00000080,sd={},name=L""} )
00d7: create_event() = 0 { handle=00a8 }
00d7:Ret  ntdll.NtCreateEvent() retval=00000000 ret=7b4a76e3
00d7:Ret  KERNEL32.CreateEventW() retval=000000a8 ret=14000b42c
...
00d7:Call rpcrt4.RpcImpersonateClient(00000000) ret=14000b450
...
00d7:Call advapi32.ImpersonateNamedPipeClient(00000078) ret=7fee32a7e672
...
00d7:trace:ntdll:NtFsControlFile
(0x78,(nil),(nil),(nil),0x98e880,0x0011001c,(nil),0x00000000,(nil),0x00000000)
...
00d7:fixme:ntdll:NtFsControlFile FSCTL_PIPE_IMPERSONATE: impersonating self
00d7:trace:ntdll:RtlImpersonateSelf (00000002)
00d7:trace:ntdll:NtOpenProcessTokenEx
(0xffffffffffffffff,0x00000002,0x00000000,0x98e5b0)
...
00d7: open_token( handle=ffffffff, access=00000002, attributes=00000000,
flags=00000000 )
00d7: open_token() = 0 { token=00ac }
...
00d7:trace:ntdll:NtDuplicateToken (0xac,0x00000004,{name=<null>,
attr=0x00000000, hRoot=(nil), sd=(nil)}
,0x00000002,0x00000002,0x98e5b8)
...
00d7: duplicate_token( handle=00ac, access=00000004, primary=0,
impersonation_level=2,
objattr={rootdir=0000,attributes=00000000,sd={},name=L""} )
...
00d7: duplicate_token() = 0 { new_handle=00b0 }
...
00d7: set_thread_info( handle=fffffffe, mask=4, priority=0, affinity=00000000,
entry_point=00000000, token=00b0 )
00d7: set_thread_info() = 0
...
00d7: close_handle( handle=00b0 )
00d7: close_handle() = 0
...
00d7: close_handle( handle=00ac )
00d7: close_handle() = 0
00d7:Ret  advapi32.ImpersonateNamedPipeClient() retval=00000001
ret=7fee32a7e672
00d7:Ret  rpcrt4.RpcImpersonateClient() retval=00000000 ret=14000b450
...
00d7:Call
KERNEL32.DeviceIoControl(000000a4,81002200,0006d250,00000096,0098eba0,00000004,0098ec28,00000000)
ret=14000b5b4
...
00d7:trace:ntdll:NtDeviceIoControlFile
(0xa4,(nil),(nil),(nil),0x98e9d0,0x81002200,0x6d250,0x00000096,0x98eba0,0x00000004)
...
00d7: ioctl( code=81002200,
async={handle=00a4,event=0000,iosb=0098e9d0,user=0006c120,apc=00000000,apc_context=00000000},
in_data={66,00,00,00,00,00,00,00,a8,00,00,00,00,00,00,00,5c,00,3f,00,3f,00,5c,00,43,00,3a,00,5c,00,4d,00,79,00,47,00,61,00,6d,00,65,00,73,00,5c,00,57,00,61,00,72,00,66,00,61,00,63,00,65,00,20,00,4d,00,79,00,2e,00,43,00,6f,00,6d,00,5c,00,42,00,69,00,6e,00,33,00,32,00,52,00,65,00,6c,00,65,00,61,00,73,00,65,00,5c,00,47,00,61,00,6d,00,65,00,2e,00,65,00,78,00,65,00,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00}
)
00d7: ioctl() = PENDING { wait=00ac, options=00000060, out_data={} }
...
00d7: select( flags=2, cookie=0098e3dc, timeout=infinite, prev_apc=0000,
result={}, data={WAIT_ALL,handles={00ac}} )
00d7: select() = PENDING { timeout=infinite, call={APC_NONE}, apc_handle=0000 }
...
--- snip ---

MRAC Anti-Cheat kernel service/driver processes the IOCTL which contains the
sync event and the process name to be started as unicode string.

66,00,00,00,00,00,00,00 -> buflen
a8,00,00,00,00,00,00,00 -> handle
00,5c,00,3f ...         -> \??\C:\MyGames\Warface My.Com\Bin32Release\Game.exe

--- snip ---
...
00dd: get_next_device_request( manager=0030, prev=0000, status=00000000 )
00dd: get_next_device_request() = 0 {
params={major=DEVICE_CONTROL,code=81002200,file=00031f70}, next=0044,
client_tid=00d7, client_thread=00000000, in_size=150, out_size=4,
next_data={66,00,00,00,00,00,00,00,a8,00,00,00,00,00,00,00,5c,00,3f,00,3f,00,5c,00,43,00,3a,00,5c,00,4d,00,79,00,47,00,61,00,6d,00,65,00,73,00,5c,00,57,00,61,00,72,00,66,00,61,00,63,00,65,00,20,00,4d,00,79,00,2e,00,43,00,6f,00,6d,00,5c,00,42,00,69,00,6e,00,33,00,32,00,52,00,65,00,6c,00,65,00,61,00,73,00,65,00,5c,00,47,00,61,00,6d,00,65,00,2e,00,65,00,78,00,65,00,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00}
}
00dd:trace:ntoskrnl:dispatch_ioctl ioctl 81002200 device 0x31e00 file 0x31f70
in_size 150 out_size 4
00dd:trace:ntoskrnl:IoBuildDeviceIoControlRequest 81002200, 0x31e00, 0x26740,
150, 0x26740, 150, 0, (nil), (nil)
00dd:trace:ntoskrnl:IoAllocateIrp 1, 0
...
00dd:trace:ntoskrnl:IoInitializeIrp 0x32040, 280, 1
...
00dd:Call driver dispatch 0x1400291d4 (device=0x31e00,irp=0x32040)
...
00dd:Call
ntoskrnl.exe.ObReferenceObjectByHandle(000000a8,00000002,7f489a919330,00000000,0043f5e0,00000000)
ret=1400125d4
00dd:trace:ntoskrnl:ObReferenceObjectByHandle 0xa8 2 0x7f489a919330 0 0x43f5e0
(nil)
00dd: get_kernel_object_ptr( manager=0030, handle=00a8 )
00dd: get_kernel_object_ptr() = INVALID_HANDLE { user_ptr=00000000 }
00dd:Ret  ntoskrnl.exe.ObReferenceObjectByHandle() retval=c0000008
ret=1400125d4
00dd:Call ntoskrnl.exe.IofCompleteRequest(00032040,00000000) ret=140012665
00dd:trace:ntoskrnl:IofCompleteRequest 0x32040 0
00dd:trace:ntoskrnl:IoCompleteRequest 0x32040 0
00dd:trace:ntoskrnl:IoCompleteRequest calling 0x7f489a8c6330( 0x31e00, 0x32040,
0x44 )
00dd: set_irp_result( handle=0044, status=c0000008, size=0, file_ptr=00031f70,
data={} )
00d7: *wakeup* signaled=192
00dd: set_irp_result() = 0
00dd:trace:ntoskrnl:IoCompleteRequest CompletionRoutine returned 0
00d7: select( flags=2, cookie=0098e3dc, timeout=infinite, prev_apc=0000,
result={}, data={WAIT_ALL,handles={00ac}} )
...
00d7: select() = USER_APC { timeout=infinite,
call={APC_ASYNC_IO,user=0006c120,sb=0098e9d0,status=INVALID_HANDLE},
apc_handle=00b0 }
...
00dd:trace:ntoskrnl:IoFreeIrp 0x32040
...
00dd:Ret  ntoskrnl.exe.IofCompleteRequest() retval=00000001 ret=140012665
...
00d7: select( flags=2, cookie=0098e3dc, timeout=infinite, prev_apc=00b0,
result={APC_ASYNC_IO,status=INVALID_HANDLE,total=0},
data={WAIT_ALL,handles={00ac}} )
...
00d7: select() = 0 { timeout=infinite, call={APC_NONE}, apc_handle=0000 }
...
00d7:Ret  KERNEL32.DeviceIoControl() retval=00000000 ret=14000b5b4
...
00d7:Call KERNEL32.GetLastError() ret=14000b5cb
...
00d7:Ret  KERNEL32.GetLastError() retval=00000006 ret=14000b5cb
...
00d7:Call rpcrt4.RpcRevertToSelfEx(00000000) ret=14000b5e4
...
00d7:Call advapi32.RevertToSelf() ret=7fee32a7e74d
00dd:Ret  driver dispatch 0x1400291d4 (device=0x31e00,irp=0x32040)
retval=c0000008 
...
00c9:Call KERNEL32.WideCharToMultiByte(0000fde9,00000000,00e4825c L"Message:
20.04.2019 12:20:14.415 200.201 [TJobClient] GameLaunch: CreateProcess
ErrorCode=0x00000006 ProcessHandle=0x00000000
ProcessId=0\r\n",0000008b,09bcfdac,000001a2,00000000,00000000) ret=0040c31c 
--- snip ---

This obviously can't work since the requestor (winedevice hosting process for
the MRAC kernel driver) is not the process which created the handle (MRAC
service process).

The methodology to pass usermode process created handles to drivers is pretty
much text book. For reference, one of the Microsoft Windows driver examples
which essentially does the same thing:

https://github.com/Microsoft/Windows-driver-samples/tree/master/general/event

Specifically:

https://github.com/Microsoft/Windows-driver-samples/blob/master/general/event/wdm/event.c

--- quote ---
...
    The purpose of this sample is to demonstrate how a kernel-mode driver can
notify
    an user-app about a device event.  There are several different techniques.
This sample
    will demonstrate two very commonly used techniques.
    1) Using an event:
        The application creates an event object using CreateEvent().
        The app passes the event handle to the driver in a private IOCTL.
        The driver is running in the app's thread context during the IOCTL so
        there is a valid user-mode handle at that time.
        The driver dereferences the user-mode handle into system space & saves
        the event object pointer for later use.
        The driver signals the event via KeSetEvent() at IRQL <=
DISPATCH_LEVEL.
        The driver deletes the references to the event object.
--- snip ---

$ sha1sum WarfaceMycomLoader_805e0da40d16630c2fe73ed12399cb48_.exe 
b07e87a029d6697ad823dc03fdbf297c406a91b9 
WarfaceMycomLoader_805e0da40d16630c2fe73ed12399cb48_.exe

$ du -sh WarfaceMycomLoader_805e0da40d16630c2fe73ed12399cb48_.exe 
6.8M    WarfaceMycomLoader_805e0da40d16630c2fe73ed12399cb48_.exe

$ wine --version
wine-4.6-61-g085e58878f

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