Log in

View Full Version : how can i obtain a ring3 thread context in ring0


_d_
May 15th, 2005, 08:12
hi,

i'm new in win32 driver coding so maybe anybody can help me.
a function in my driver get called if a new process starts, now i have the process id of the parent, with this id it is easy to obtain the eprocess, but i now i need the full register set of the ring3 process....

are there any ring0 debugger sources out there ?
how can e.g syser obtain the thread context ?

best regards, _d

blabberer
May 15th, 2005, 08:27
the question sounds simililar to some one who posted it in rootkit.com
but he was looking for nt4 compatibility
take a look there and a look at KeAttachProcess ,KeStackAttachProcess
or look for valerinos posts (especially his calling userland functions from kernel one
might be helpful

_d_
May 15th, 2005, 11:38
KeAttackProcess is no solution because then i only switch into virtual memory
but i don't can read any register values from the ring3 process...

and injecting shellcode into the userland process is too heavy ..i don't think softice or syser injecting code into the process

Kayaker
May 15th, 2005, 14:04
Hi

I'm making the assumption you're using PsSetCreateProcessNotifyRoutine or PsSetCreateThreadNotifyRoutine to register a callback function. Since the callback is notified sometime during process/thread creation or deletion, depending on how you declared them, I don't see how getting the full register set at that point in time is of much use really. For example, they will not be the values that exist when the thread actually starts, and I don't think you will be able to change them to what you want, if that's what you had in mind.

If you examine either of the exported ntoskrnl PsxxNotifyRoutine functions they seem fairly simple, it looks like the callback address is stored in a table, and there seems to be a maximum of 8 for each type. Checking where occurrences of the table pointer is used again shows them being used (i.e. where your callback routine is called) somewhere in the middle of thread/process creation/deletion code.

Chances are the final register values for a thread are determined somewhat later during thread creation. Even the EPROCESS may not be fully defined at the point your callback gets to it. Try tracing through your callback back into ntoskrnl code to see where it leads.

I think this is one of those "how do I hook a process immediately before execution" questions. I don't think one of the system defined callbacks will give you complete control over that. The final steps of thread initialization involve queuing a user APC to load ntdll, then other required dlls. (See Inside Win2k chap.6). Maybe some more info on what you're trying to do might help.

Cheers,
Kayaker

_d_
May 15th, 2005, 14:40
Quote:

For example, they will not be the values that exist when the thread actually starts,


i don't want obtain the context from the child, instead i need the one from the parent...

you asked form more information....
you are right i use the PsProsessNotifyRoutine(), no i can easily get all values i need Eprocess of the parent threadid of the parent etc... i also can attach to the virtual memory, but i also need the full register set of the ring 3 process before it get switch into the kernel mode, and i think this should be possible because all kernel debugger have this feature, but i think they get a message from the kernel driver then the ring3 part of the debugger attach to the process and do the rest.....

do you have another estimation???

best regards _d

Kayaker
May 15th, 2005, 20:25
So to clarify then, you're trying to get at the parent process identified in EPROCESS.InheritedFromUniqueProcessId is that right? I believe the "switch" into kernel mode that begins creation of the child process then would be at ntdll!ZwCreateProcess, or INT 2E (EAX=29). You can set a 'BPINT 2E if EAX==29' in Softice, start up notepad for example, and trace the entire process creation routine from there if you wish.

If that's where you want the ring3 register/context information that's probably where to get it. You could combine a hook to ZwCreateProcess (or elsewhere in the code that follows), with your callback routine. The PID hasn't been defined yet, you might have to match up in your callback via the process name (which is a trick in itself), unless you know you are monitoring a certain hParentProcess.


NTAPI
NtCreateProcess(
OUT PHANDLE phProcess,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN HANDLE hParentProcess,
IN BOOLEAN bInheritParentHandles,
IN HANDLE hSection OPTIONAL,
IN HANDLE hDebugPort OPTIONAL,
IN HANDLE hExceptionPort OPTIONAL
);


I'm not sure of your comment about the kernel debugger. A ring3 debugger if attached kicks in at the very end of the thread creation routine.

Kayaker

blabberer
May 16th, 2005, 04:07
well if you want to just see the disasembly and want to dabbele with
deadlisting you can use livekd in conjunction with windbg on w2k
or you can use local some thing in xp without livekd and
use x and uf to completely disassemble the functions like this

Code:

C:\Program Files\Debugging Tools for Windows>livekd -w

LiveKd v2.12 - Execute i386kd/windbg/dumpchk on a live system
Sysinternals - www.sysinternals.com
Copyright (C) 2000-2005 Mark Russinovich

Launching C:\Program Files\Debugging Tools for Windows\windbg.exe:


Code:

kd> x Nt!NtCreateF*
804a0c2d nt!NtCreateFile = <no type information>
kd> uf nt!ntCreateFile
nt!NtCreateFile:
804a0c2d 55 push ebp
804a0c2e 8bec mov ebp,esp
804a0c30 33c0 xor eax,eax
804a0c32 50 push eax
804a0c33 50 push eax
804a0c34 50 push eax
804a0c35 ff7530 push dword ptr [ebp+0x30]
804a0c38 ff752c push dword ptr [ebp+0x2c]
804a0c3b ff7528 push dword ptr [ebp+0x28]
804a0c3e ff7524 push dword ptr [ebp+0x24]
804a0c41 ff7520 push dword ptr [ebp+0x20]
804a0c44 ff751c push dword ptr [ebp+0x1c]
804a0c47 ff7518 push dword ptr [ebp+0x18]
804a0c4a ff7514 push dword ptr [ebp+0x14]
804a0c4d ff7510 push dword ptr [ebp+0x10]
804a0c50 ff750c push dword ptr [ebp+0xc]
804a0c53 ff7508 push dword ptr [ebp+0x8]
804a0c56 e8b06a0000 call nt!IoCreateFile (804a770b)
804a0c5b 5d pop ebp
804a0c5c c22c00 ret 0x2c


if you follow through you will be able to see IoCreate calls
mmuserprobe
call nt!ExAllocatePoolWithQuotaTag (804181da)
call nt!IoCheckEaBufferValidity (804b73d9)
call nt!ExAllocatePoolWithTag (80466c80)
call nt!IopUpdateOtherOperationCount (804005dc)
call nt!ObOpenObjectByName (804956fb)

and so on

_d_
May 18th, 2005, 01:03
mhhh maybe you don't understand my post or i don't understand ours
@Kayaker
>>I'm not sure of your comment about the kernel debugger. A ring3 debugger if >>attached kicks in at the very end of the thread creation routine.

yes i know...
but the driver can inform the ring3 debugger about a new process(PsProcessNotify), then the debugger can attach to the PARENT process, and do something like
openprocess(), getthreadcontext() ...

if there is a nother way to do this that would be great, but i need a documentated way to do this, because reversing some kernel stuff and hope that this is on every NT/win32/server 2003 the same is not reliable...

i looked at syser and i think the program, does it this way....

Kayaker
May 18th, 2005, 11:03
Quote:
[Originally Posted by _d_]mhhh maybe you don't understand my post or i don't understand ours

Hi

You're right, my clairvoyancy skills aren't very good and I guess I need some clue as to intent or purpose or relevant details, in order to understand a question. I guess I'm just old-fashioned that way
All kidding aside, it does help to make your intent clear when asking such questions. I wasn't trying to tell you things you already know, just trying to clarify things for the rest of us willing to help.

Maybe I misunderstood from the first post as to what point of view you were taking (your driver is part of a debugger, or it is a standalone app, or it is an anti-debugger approach, or...). To try to understand your question, these details seemed important.

The approach you describe sounds OK - get notified of a process starting and attach to the parent process. I don't know the details of "attaching" to a running process from/as a ring3 debugger, though I'm sure many others can help. My question now might be, what is wrong with this approach or what details are you specifically asking about?

Regards,
Kayaker

_d_
May 19th, 2005, 02:07
Quote:

The approach you describe sounds OK - get notified of a process starting and attach to the parent process. I don't know the details of "attaching" to a running process from/as a ring3 debugger, though I'm sure many others can help. My question now might be, what is wrong with this approach or what details are you specifically asking about?



Quote:

my clairvoyancy skills aren't very good


;-) ok ok my intent is doing a stack trace(from ring0 till ring3, if the programm uses stack frames of course ). and i know that this is possible, even if you only have a driver, because i seen a statck-trace picture in "Windows internals" , but there is no information how they get the ring3 context...

anyway thanks for your time, next time i try to shape my post better ...

Kayaker
May 19th, 2005, 18:32
Aah ;-) The closest I've come to programming a stack backtrace is through the use of the WINDBG_EXTENSION_APIS lpStackTraceRoutine function, implemented as a Softice KDExtension. This essentially gives you the same info as the STACK command.

There are 2 definitions for a stack trace in Windbg, one defined in wdbgext.h, a more extensive one in dbgeng.h.
Code:

// wdbgext.h
(WDBGAPI*PWINDBG_STACKTRACE_ROUTINE)(
ULONG FramePointer, // stack frame EBP (or 0)
ULONG StackPointer, // stack frame ESP (or 0)
ULONG ProgramCounter, // Instruction offset (or 0)
PEXTSTACKTRACE StackFrames, // return structure
ULONG Frames // number of frames to return (based
// on number of EXTSTACKTRACE structures)
);

The FramePointer and StackPointer are the ClientEBP and ClientESP which you can get from Windbg lpGetThreadContextRoutine. This function returns a pointer to a CONTEXT_FULL Context structure for the thread Id specified. In kernel mode you specify the processor number instead of the TID.


So, this is the way to do it using Windbg api's. It sounds like you want to program a fully manual stack backtracing routine. That's cool. An interesting programming challenge. You might be able to pick up some tricks from tracing an implemented Windbg stack trace routine, if you haven't already got something developed.

Where then is the starting point? You can get the StackBase and StackLimit from the TEB. "Walking" the stack manually can begin there then, or must you get at least one valid EBP value from a context structure? I don't know what problems one might encounter in doing a stack backtrace manually, how far could you go before you "lose" it? And then there's the context switch problem you mentioned.

Softice does do context switches in both the STACK command and the internal lpStackTraceRoutine function it exports for KDExtension use. In Softice, "context" is defined as a pointer to the KPROCESS structure and a "context switch" is based on it, I mentioned this in a previous post.


Back to your original question on how to get the ring3 context of the parent process, I'd actually have to reserve judgement to see what is *necessary* at the time, in terms of a stack backtrace implementation. For example, where and in what context are you starting the backtrace from and how far can you get? If indeed you would need to "jump over" an INT2E ZwCreateProcess to tap into the previous stack tracings to get at the parent, I'm really not sure the best approach at this time.

I'm not sure how much of this applies to your problem or question. It's an interesting topic though so if anyone has any further insights it would be useful. Perhaps you already have some procedures developed and might be willing to share in terms of implementing a stack backtrace. Maybe you can mention exactly where you saw this stack trace picture you spoke of.

Regards,
Kayaker

user
June 10th, 2005, 13:49
Quote:
[Originally Posted by _d_]a function in my driver get called if a new process starts, now i have the process id of the parent, with this id it is easy to obtain the eprocess, but i now i need the full register set of the ring3 process....
a process doesn't have a register context, only a thread does (that is, a register context is per thread, not process). if your target thread is executing in ring-3 at the time you want to look at its registers, then tough, you can't do it (and whatever you'd get would change the next clock cycle). if your target thread is not executing or it's executing in ring-0, then you have the ring-3 trap frame at the bottom of the ring-0 stack of the given thread, look that up (KTHREAD should have a pointer to the linked list of trap frames, it's a list because a thread can re-enter ring-0 pushing more trap frames on the same kernel stack).