[Bug 37272] New: CheatEngine 6.4 fails after remote process 'breakin', reporting 'Debugger Crash:Access violation (Last location:41)'

wine-bugs at winehq.org wine-bugs at winehq.org
Sun Sep 14 17:37:06 CDT 2014


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

            Bug ID: 37272
           Summary: CheatEngine 6.4 fails after remote process 'breakin',
                    reporting 'Debugger Crash:Access violation (Last
                    location:41)'
           Product: Wine
           Version: 1.7.26
          Hardware: x86
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: dbghelp
          Assignee: wine-bugs at winehq.org
          Reporter: focht at gmx.net

Hello folks,

as the summary says.

The app works well in general - except when breaking into remote process for
debugging (to single step).

The app is pretty verbose about its doings, using 'OutputDebugString' API.

--- snip ---
$ pwd
/home/focht/.wine/drive_c/Program Files/Cheat Engine 6.4
...
$ WINEDEBUG=+tid,+seh,+loaddll,+process,+debugstr wine ./Cheat\ Engine.exe
>>log.txt 2>&1
...
0023:warn:debugstr:OutputDebugStringA "setThreadContext(28, 110, 07E9710C).
dr0=0 dr1=0 dr2=0 dr3=0 dr7=400"
...
002b:warn:debugstr:OutputDebugStringA "HandleExceptionDebugEvent:80000004"
...
002b:warn:debugstr:OutputDebugStringA "EXCEPTION_SINGLE_STEP. Dr6=00004000"
...
002b:warn:debugstr:OutputDebugStringA "Handling as a single step event"
...
002b:warn:debugstr:OutputDebugStringA "HandleBreak()"
...
0023:trace:seh:raise_exception code=c0000005 flags=0 addr=0x410464 ip=00410464
tid=0023
0023:trace:seh:raise_exception  info[0]=00000001
0023:trace:seh:raise_exception  info[1]=d000db06
0023:trace:seh:raise_exception  eax=0000000b ebx=044bbc78 ecx=d000dafe
edx=001c9071 esi=044bbc74 edi=001c9071
0023:trace:seh:raise_exception  ebp=01b8ea5c esp=01b8e9f0 cs=0023 ds=002b
es=002b fs=0063 gs=006b flags=00210282
0023:trace:seh:call_stack_handlers calling handler at 0x7bc9de17 code=c0000005
flags=0
0023:trace:seh:call_stack_handlers handler at 0x7bc9de17 returned 0
...
--- snip ---

The CheatEngine debugger was attached to 'notepad' process.

--- snip ---
Wine-dbg>info process

 pid      threads  executable (all id:s are in hex)
 00000027 1        'notepad.exe'
 00000022 3        'cheatengine-i386.exe'
 00000020 1        'explorer.exe'
 0000000e 5        'services.exe'
 00000019 3        \_ 'plugplay.exe'
 00000012 4        \_ 'winedevice.exe'

Wine-dbg>info thread

process  tid      prio (all id:s are in hex)
...
00000022 cheatengine-i386.exe
    0000002b    0
    00000024    0
    00000023    0
00000027 notepad.exe
    00000028    0 
--- snip ---

Running the debugger under a debugger yields the following:

--- snip ---
Unhandled exception: page fault on write access to 0xd000db06 in 32-bit code
(0x00410464).
Register dump:
 CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b
 EIP:00410464 ESP:01b8e9f0 EBP:01b8ea5c EFLAGS:00210282(  R- --  I S - - - )
 EAX:0000000b EBX:040341a8 ECX:d000dafe EDX:001c9071
 ESI:040341a4 EDI:001c9071
Stack dump:
0x01b8e9f0:  000000b0 0000000b 040341a4 000000b0
0x01b8ea00:  0423c2e8 0423c2ec 004105ee 0000004c
0x01b8ea10:  0423c2e8 00410bdd 0000001c 0423c2e8
0x01b8ea20:  00000414 0040fa88 006426a9 0423c2e8
0x01b8ea30:  0410a7f8 00000414 006429b7 0423c2e8
0x01b8ea40:  0410a7f8 006427ad 001b2ba8 00000000
000c: sel=0067 base=00000000 limit=00000000 16-bit --x
Backtrace:
=>0 0x00410464 in cheatengine-i386 (+0x10464) (0x01b8ea5c)
  1 0x007011b4 in cheatengine-i386 (+0x3011b3) (0x01b8ea70)
  2 0x0050bc97 in cheatengine-i386 (+0x10bc96) (0x01b8f368)
  3 0x0050c155 in cheatengine-i386 (+0x10c154) (0x01b8f6a0)
  4 0x0044b868 in cheatengine-i386 (+0x4b867) (0x01b8f6b8)
  5 0x00452019 in cheatengine-i386 (+0x52018) (0x01b8f728)
  6 0x004fd312 in cheatengine-i386 (+0xfd311) (0x01b8f7ac)
  7 0x005013c1 in cheatengine-i386 (+0x1013c0) (0x01b8f824)
  8 0x0058ef28 in cheatengine-i386 (+0x18ef27) (0x01b8f898)
  9 0x006e7668 in cheatengine-i386 (+0x2e7667) (0x01b8faa8)
  10 0x7eb8fb5e WINPROC_wrapper+0x19() in user32 (0x01b8fad8)
...
0x00410464: movl    $0x0,0x8(%ecx)
--- snip ---

The app is open source: https://code.google.com/p/cheat-engine

--- snip ---
$ svn checkout http://cheat-engine.googlecode.com/svn/trunk/
cheat-engine-read-only
--- snip ---

'Last location:41' part of error message gives a hint:

htps://code.google.com/p/cheat-engine/source/browse/trunk/Cheat%20Engine/debugeventhandler.pas#180

--- snip ---
procedure TDebugThreadHandler.VisualizeBreak;
begin
  TDebuggerthread(debuggerthread).execlocation:=41;
  if processhandler.SystemArchitecture=archx86 then
    MemoryBrowser.lastdebugcontext:=context^
  else
    MemoryBrowser.lastdebugcontextarm:=armcontext;

  WaitingToContinue:=not lua_onBreakpoint(context);

  if WaitingToContinue then //no lua script or it returned 0
    MemoryBrowser.UpdateDebugContext(self.Handle, self.ThreadId);

end;
--- snip ---

The crashes happens during update of stacktrace listview, after a couple of
'dbghelp.StackWalk64' calls.

'TMemoryBrowser.UpdateDebugContext' -> 'TfrmStacktrace.stacktrace'

https://code.google.com/p/cheat-engine/source/browse/trunk/Cheat%20Engine/frmstacktraceunit.pas#120

The crash address is an indirect reference from ECX = 0xd000dafe (+8) .. a
value which corresponds to Wine's 'frame->KdHelp.KiCallUserMode' magic value.

The stack frame data structure passed to 'StackWalk64' is allocated from
internal Delphi heap and initialized.

--- snip ---
procedure TfrmStacktrace.stacktrace(threadhandle:thandle;context:_context);
var
stackframe: PStackframe64;
cxt:_context;
wow64ctx: CONTEXT32;
a,b,c,d: dword;
sa,sb,sc,sd:string;
machinetype: dword;

cp: pointer;

found: boolean;
begin

...
getmem(stackframe,sizeof(tstackframe));
zeromemory(stackframe,sizeof(tstackframe));
stackframe^.AddrPC.Offset:=context.{$ifdef cpu64}rip{$else}eip{$endif};
stackframe^.AddrPC.mode:=AddrModeFlat;

stackframe^.AddrStack.Offset:=context.{$ifdef cpu64}rsp{$else}esp{$endif};
stackframe^.AddrStack.Mode:=addrmodeflat;

stackframe^.AddrFrame.Offset:=context.{$ifdef cpu64}rbp{$else}ebp{$endif};
stackframe^.AddrFrame.Mode:=addrmodeflat;
...
--- snip ---

The corresponding disassembly, annotated:

--- snip ---
0050BBD1     8D45 F8          LEA EAX,DWORD PTR SS:[EBP-8]
0050BBD4     BA A4000000      MOV EDX,0A4            ; sizeof(tstackframe)
0050BBD9     E8 323EF0FF      CALL cheateng.0040FA10 ; getmem()
0050BBDE     68 A4000000      PUSH 0A4               ; sizeof(tstackframe)
0050BBE3     FF75 F8          PUSH DWORD PTR SS:[EBP-8]
0050BBE6     E8 C5121600      CALL cheateng.0066CEB0 ; zeromemory()
0050BBEB     8B4D F8          MOV ECX,DWORD PTR SS:[EBP-8]
0050BBEE     8B95 38F8FFFF    MOV EDX,DWORD PTR SS:[EBP-7C8]
0050BBF4     B8 00000000      MOV EAX,0
0050BBF9     8911             MOV DWORD PTR DS:[ECX],EDX ; stackframe^.AddrPC..
0050BBFB     8941 04          MOV DWORD PTR DS:[ECX+4],EAX
--- snip ---

0xA4 is a bit too small for 'STACKFRAME64' structure.

MSDN:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms680646%28v=vs.85%29.aspx

My guess is that Delphi/Pascal's definition of 'tstackframe' doesn't include
the 'KDHELP64' part which is reserved for kernel debuggers.

The problem is that Wine writes magic values into an area that should be left
untouched since we're dealing with usermode debugging.
That corrupts the internal heap.

Source:
http://source.winehq.org/git/wine.git/blob/61a9eef9a1c0a72e6571742dbb830f7b22c05230:/dlls/dbghelp/stack.c#l210

--- snip ---
...
242     /* we don't handle KdHelp */
243     frame->KdHelp.Thread = 0xC000FADE;
244     frame->KdHelp.ThCallbackStack = 0x10;
245     frame->KdHelp.ThCallbackBStore = 0;
246     frame->KdHelp.NextCallback = 0;
247     frame->KdHelp.FramePointer = 0;
248     frame->KdHelp.KiCallUserMode = 0xD000DAFE;
249     frame->KdHelp.KeUserCallbackDispatcher = 0xE000F000;
250     frame->KdHelp.SystemRangeStart = 0xC0000000;
251     frame->KdHelp.Reserved[0] /* KiUserExceptionDispatcher */ = 0xE0005000;
...
--- snip ---

The code that writes the magic values was added 8 years ago:

http://source.winehq.org/git/wine.git/commitdiff/558130a696a1e6c11a84f3d1f12515c74b9ef17f

Not sure what the intention was since usermode debuggers can't deal with these
things anyway.

With that part fixed, CheatEngine can debug remote processes after attaching.

$ sha1sum CheatEngine64.exe 
8cb06bca312ed2bfa02c7f9344f2717d02ecd931  CheatEngine64.exe

$ du -sh CheatEngine64.exe 
8.7M    CheatEngine64.exe

$ wine --version
wine-1.7.26-44-gb10b391

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