A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #17143  by p4r4n0id
 Wed Dec 12, 2012 1:50 pm
Hi Guys,

Are you familiar with a technique to monitor process exceptions in x64 without bypassing patchguard? Does signing a driver will allow me patching the IDT / SSDT? (msdn says no but maybe you guys know better :))

Thx,

p4r4n0id
 #17151  by feryno
 Thu Dec 13, 2012 10:18 am
using hypervisor you can intercept exceptions, handle them as you like and then you can inject them back to OS (or even discard them)
but there is a problem in identifying processes in host mode (hypervisor) - you e.g. know CR3 at the time of intercepting exception, but that doesn't mean that process owning this memory mapping is in context
you can load hypervisor as driver from running OS (easier to develop) or you can load it before OS (similar to bootkits, harder to develop)
 #17152  by p4r4n0id
 Thu Dec 13, 2012 11:03 am
feryno wrote:using hypervisor you can intercept exceptions, handle them as you like and then you can inject them back to OS (or even discard them)
but there is a problem in identifying processes in host mode (hypervisor) - you e.g. know CR3 at the time of intercepting exception, but that doesn't mean that process owning this memory mapping is in context
you can load hypervisor as driver from running OS (easier to develop) or you can load it before OS (similar to bootkits, harder to develop)

Hi feryno!

Hypervisor is definitely an option. Thought maybe there are other techs besides IDT patching that will do the job...

Thx bro!
p4r4n0id
 #17154  by p4r4n0id
 Thu Dec 13, 2012 11:14 am
p4r4n0id wrote:
feryno wrote:using hypervisor you can intercept exceptions, handle them as you like and then you can inject them back to OS (or even discard them)
but there is a problem in identifying processes in host mode (hypervisor) - you e.g. know CR3 at the time of intercepting exception, but that doesn't mean that process owning this memory mapping is in context
you can load hypervisor as driver from running OS (easier to develop) or you can load it before OS (similar to bootkits, harder to develop)

Hi feryno!

Hypervisor is definitely an option. Thought maybe there are other techs besides IDT patching that will do the job...

Thx bro!
p4r4n0id


BTW, regarding the context problem u have mentioned above, is it possiable to return to e.g a function of mine in the OS?
 #17169  by feryno
 Fri Dec 14, 2012 10:29 am
is it possible to return to e.g a function of mine in the OS
Hi, I didn't tried such method - so the next are only my thoughts:
it depends on whether the exception is in the same process and in the same ring as return address

[0] exception address and address of your procedure are in the same process and the same ring
you change guest RIP while in hypervisor and that should be enough to jump to your function, to return back from your function to the address of exception you do only IRET/IRETQ (some exceptions push error code on the stack in that case remove the error code with something like add esp,4 \ add rsp,8 before IRET \ IRETQ)
care must be taken if exception and your function are in the same process but in different threads of the process (stack spaces and stack pointers of both threads are different, you are in different thread but you are using stack of original thread)

[1] exception address and return address are in the same process but rings are different
you must change guest RIP to address of your function but you also need to change selectors (at least CS, SS, maybe more, this is not problem as they are know, e.g. CS=33h for ring3 under win x64, CS base may be extracted from GDT and so on), but I see here a problem how to adjust stack pointer (new guest ESP \ RSP is not known)

[2] exception and return address are in different processes
I'm now saying it is impossible but I'm guessing a nightmare here. Not only how to change stack pointer but also reload guest CR3 (both processes have different paging tables), also adjusting various kernel internals (what OS does during switching processes/threads)

I vote for placing your function in ring0 so you can access if from any process and use method [1] or [0]. It also needs to think out some method of loading stack.
All such work is research activity, sometimes you may spend few months working hard and not to see any progress. It requires something which will motivate you to continue even unsuccessful tries (e.g. you will do the work for somebody who will pay you regularly) else there is high probability that you resign.
regarding the context problem u have mentioned above
My problem with context was caused by situations like this:

- hypervisor intercepted pagefault exception (typically that means some memory page is in swap file or is even in RAM but not yet mapped into virtual memory - e.g. only header and few parts of exe/dll are yet mapped and the rest is mapped on demand as code executes and accesses various data/code that hits #PF and OS maps them as requested - such design is for performance)
- hypervisor knew CR3 at the time of exception
- I thought that it is enough to identify process (every process has different CR3, I tried to extract PID from process internals - some magic offsets and create pairs of CR3-PID)
- but sometimes I found there is a mismatch in CR3 and PID (extracted from specific offsets in kernel internals)

the explanation was simple: another process was accessing memory space of first process. In such situations (e.g. ring3 function ReadProcessMemory/WriteProcessMemory) OS loads the CR3 of another process but PID of original process stays in kernel internals (at some magic offsets) - e.g. the above ring3 example leads into ring0 procedures like
KeStackAttachProcess
http://msdn.microsoft.com/en-us/library ... 85%29.aspx
and similar clones (...Detach..., ...Unstack...)
PID (at magic internal offsets) changes only when doing full swap (which leads into SwapContext procedure where CR3 is also changed and TEB also and also much more things)

In 1 sentence - when your hypervisor records CR3 you can't trust that a thread of process owning the CR3 is in Context (additional validation is required).

I hope that explains some problems which you have to defeat.