|
You last visited: Today at 17:11
Advertisement
SetThreadContext + CPU EFlags help please
Discussion on SetThreadContext + CPU EFlags help please within the General Coding forum part of the Coders Den category.
08/04/2009, 23:40
|
#1
|
elite*gold: 20
Join Date: Aug 2007
Posts: 1,749
Received Thanks: 2,199
|
SetThreadContext + CPU EFlags help please
Hey everyone. I'm having some problems with my homemade debugger, written in VB6, and I was hoping someone here could help me.
See, I'm writing this kind of debugger hack for Conquer Online. I'm using it to read the decrypted packets both incoming and outgoing. I'm using breakpoints at the "SendPacket()" and "ReceivePacket()" function inside the .exe and then I use the GetThreadContext API to read the register values and get the decrypted packets.
It works almost perfectly, although there's a tiny problem, and I was hoping someone here might know how to solve it. Whenever I hit a breakpoint, my tool is supposed to set the Resume Flag inside the CPU to 1 which should prevent exceptions from going into an infinite loop, but it does not work - the Resume Flag just won't change.
However, it works just fine on Windows Vista, which I cannot seem to understand why, I've google'd a million times, and still no luck. Here's the part of my code that's supposed to toggle the Resume Flag:
Code:
Do While bContinue
ContinueStatus = DBG_CONTINUE
If WaitForDebugEvent(DebugEvent, 0) Then
ExceptionAddress = DebugEvent.dwUnionData.ExceptionRecord.ExceptionAddress
ExceptionCode = DebugEvent.dwUnionData.ExceptionRecord.ExceptionCode
Select Case DebugEvent.dwDebugEventCode
Case EXCEPTION_DEBUG_EVENT
ContinueStatus = DBG_CONTINUE
If Not bSeenInitialBreakpoint And ExceptionCode = EXCEPTION_BREAKPOINT Then
ContinueStatus = DBG_CONTINUE
SetHardwareBreakpoint DebugEvent.dwProcessId
bSeenInitialBreakpoint = True
End If
If ExceptionCode = EXCEPTION_SINGLE_STEP Then
ContinueStatus = DBG_CONTINUE
ThreadHandle = OpenThread(THREAD_ALL_ACCESS, False, DebugEvent.dwThreadId)
' Debug.Print "Single step exception occured"
SuspendThread (ThreadHandle)
If DebugEvent.dwUnionData.ExceptionRecord.ExceptionAddress = SendPacketFunction Or DebugEvent.dwUnionData.ExceptionRecord.ExceptionAddress = RecvPacketFunction Then
ExceptionHandler ThreadHandle, ExceptionAddress
End If
ResumeThread (ThreadHandle)
CloseHandle (ThreadHandle)
End If
If ExceptionCode = EXCEPTION_BREAKPOINT Then
ContinueStatus = DBG_CONTINUE
End If
Case CREATE_THREAD_DEBUG_EVENT
'SetHardwareBreakpointInThread DebugEvent.dwThreadId
End Select
ContinueDebugEvent DebugEvent.dwProcessId, DebugEvent.dwThreadId, ContinueStatus
End If
DoEvents
Loop
End If
And this:
Code:
Public Sub ExceptionHandler(hThread As Long, ExceptionAddress As Long)
Dim cThread As CONTEXT
cThread.ContextFlags = CONTEXT_ALL
GetThreadContext hThread, cThread
cThread.EFlags = cThread.EFlags Or EFLAG_RF ' // EFLAG_RG = Resume Flag = &H10000
SetThreadContext hThread, cThread
Also, another quick question:
I'm using CreateRemoteThread to execute code inside the .exe (e.g. using a skill), but whenever I'm debugging the application (using DebugActiveProcess) it just freezes. Is there a way to prevent a debugged application from freezing when using CreateRemoteThread? At the moment I have to use this whenever I need to call a function:
Code:
DebugActiveProcessStop(ProcessID)
UseSkill SkillID, TargetID ' (Just an example)
DebugActiveProcess(ProcessID)
Thank you for your time  .
|
|
|
08/10/2009, 18:53
|
#2
|
elite*gold: 1
Join Date: Jul 2005
Posts: 553
Received Thanks: 454
|
Quote:
|
You last visited: 08-04-2009 at 01:19
|
Uh, was quite some time not online.
I don't know if you already solved your problem and additional
I'm not familiar with this topic so the only thing I can do is to guess but let's try though:
Others debuggers break on the next instructions when using HW BPs.
Try setting the RF and then get the flags anew.
You'll see it got cleared..
I don't know why but you seem to cannot set this flag.
Here's a newbish workaround which just came to my mind:
Check in STATUS_SINGLE_STEP if your HW BP got toggled, if so do some stuff, clear Dr7, set a variable and on top of that set the TF.
Call ContinueDebugEvent and WaitForDebugEvent (I would pass -1 as second param. Don't know if it changes something at all, as I said this is the first time I was faced with this topic :x), then check in STATUS_SINGLE_STEP if your variable was set to clear it and set Dr7 again.
Also to not open the thread over and over again I would catch CREATE_PROCESS_DEBUG_EVENT and save u.CreateProcessInfo.hThread.
Err, I certainly do not know how to solve your CreateRemoteThread-problem..
I thought it should work due to ContinueDebugEvent although I did not test it.
Btw. I'm curious how your SetHardwareBreakpoint looks like since it wants the PID. Could you please post it? (Does it use CreateToolhelp32Snapshot?)
|
|
|
08/10/2009, 21:49
|
#3
|
elite*gold: 20
Join Date: Aug 2007
Posts: 1,749
Received Thanks: 2,199
|
Quote:
Originally Posted by link
Uh, was quite some time not online.
I don't know if you already solved your problem and additional
I'm not familiar with this topic so the only thing I can do is to guess but let's try though:
Others debuggers break on the next instructions when using HW BPs.
Try setting the RF and then get the flags anew.
You'll see it got cleared..
I don't know why but you seem to cannot set this flag.
Here's a newbish workaround which just came to my mind:
Check in STATUS_SINGLE_STEP if your HW BP got toggled, if so do some stuff, clear Dr7, set a variable and on top of that set the TF.
Call ContinueDebugEvent and WaitForDebugEvent (I would pass -1 as second param. Don't know if it changes something at all, as I said this is the first time I was faced with this topic :x), then check in STATUS_SINGLE_STEP if your variable was set to clear it and set Dr7 again.
Also to not open the thread over and over again I would catch CREATE_PROCESS_DEBUG_EVENT and save u.CreateProcessInfo.hThread.
Err, I certainly do not know how to solve your CreateRemoteThread-problem..
I thought it should work due to ContinueDebugEvent although I did not test it.
Btw. I'm curious how your SetHardwareBreakpoint looks like since it wants the PID. Could you please post it? (Does it use CreateToolhelp32Snapshot?)
|
Thanks for the input, however I'm converting my project to VB.NET now, I'll see if it works later, and yes, it does call CreateToolHelp32Snapshot to get all the threads of the process.
Code:
Public Function SetHardwareBreakpoint(pid As Long)
Dim hSnap As Long
Dim te As THREADENTRY32
Dim bResult As Boolean
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, pid)
te.Size = Len(te)
bResult = Thread32First(hSnap, te)
Do While bResult
If te.ProcessID = pid Then
SetHardwareBreakpointInThread te.ThreadID
End If
bResult = Thread32Next(hSnap, te)
Loop
CloseHandle hSnap
End Function
Edit: Forgot to add, I was already clearing the DR7 flag after a breakpoint was met and then re-enabling the breakpoint after execution, however the amount of time it takes to call the SetThreadContext to set the DR7 flag back to enable the breakpoint means that I miss a lot of instructions, depending on how fast they're executed of course.
|
|
|
08/13/2009, 01:52
|
#4
|
elite*gold: 1
Join Date: Jul 2005
Posts: 553
Received Thanks: 454
|
Quote:
Originally Posted by IAmHawtness
Edit: Forgot to add, I was already clearing the DR7 flag after a breakpoint was met and then re-enabling the breakpoint after execution, however the amount of time it takes to call the SetThreadContext to set the DR7 flag back to enable the breakpoint means that I miss a lot of instructions, depending on how fast they're executed of course.
|
Just saw your edit:
The amount of instructions you actually miss is equal to 1 ;-)
That's why I mentioned the behaviour of debuggers when dealing with HW BPs.
I should have had commented it better...
I noticed my whole post is messed up (in language and remarks) and this one gets fucked up, too (hope it helps though).
My English-posts are just awful..
Nevertheless:
Quote:
|
Originally Posted by link
Check in STATUS_SINGLE_STEP if your HW BP got toggled, if so do some stuff, clear Dr7, set a variable and on top of that set the TF.
|
Remember the single-step mode :-)
A simple snippet to do so:
Code:
local SetBP, HWToggled
assume ebx : ptr DEBUG_EVENT
mov [SetBP], 1
mov [HWToggled], 0
lea ebx, [DebugEvent]
mov edi, [hThread]
;...
mov ecx, [ebx.u.Exception.ExceptionRecord.ExceptionCode]
cmp ecx, STATUS_BREAKPOINT
jne single_step
mov eax, [SetBP]
test eax, eax
jz already_bp
inv SuspendThread, edi
mov [cxt.ContextFlags], CONTEXT_DEBUG_REGISTERS
inv GetThreadContext, edi, offset cxt
mov [cxt.rDr0], 0DEADBEEFh
or [cxt.rDr7], 1
inv SetThreadContext, edi, offset cxt
inv ResumeThread, edi
xor eax, eax
mov [SetBP], eax
already_bp:
jmp continue_debugevent
single_step:
cmp ecx, STATUS_SINGLE_STEP
jne continue_debugevent
mov eax, 1
cmp [HWToggled], eax
jz toggled
mov [HWToggled], eax
inv SuspendThread, edi
mov [cxt.ContextFlags], CONTEXT_DEBUG_REGISTERS or CONTEXT_CONTROL
inv GetThreadContext, edi, offset cxt
and [cxt.rDr7], not 1
or [byte high word low cxt.EFlags], 1
inv SetThreadContext, edi, offset cxt
inv ResumeThread, edi
jmp continue_debugevent
toggled:
xor eax, eax
mov [HWToggled], eax
inv SuspendThread, edi
mov [cxt.ContextFlags], CONTEXT_DEBUG_REGISTERS
inv GetThreadContext, edi, offset cxt
or [cxt.rDr7], 1
inv SetThreadContext, edi, offset cxt
inv ResumeThread, edi
jmp continue_debugevent
;...
inv ContinueDebugEvent...
|
|
|
All times are GMT +1. The time now is 17:11.
|
|