MCH and SEH

c++ / delphi package - dll injection and api hooking
Post Reply
EaSy
Posts: 150
Joined: Tue Oct 23, 2012 12:33 pm

MCH and SEH

Post by EaSy »

Hi,
i'd like to solve an issue with MCH hooks breaking the SEH handling when the default setting.

Let's say we hook RPC function NdrClientCall2. RPC error reporting relies on exceptions. The problem is that MCH modifies return address to watch the hook counts. So once the exception is raised it does not propagate to the top of the stack and it ends as an unhandled exception.

Is there any way to enable SEH propagation in the MCH hooks? One way is to use NO_HOOK_COUNT flag, but that is only temporary solution, because app will then crash sometimes in manual unhooking.

One way would be to repair stack (that return address that MCH modifies) in the hook which i succesfully tried and it worked then. But the problem is the exception itself, because it does not call your "lower the hook count code" in the hook return so introducing a deadlock. It needs to be fixed by own exception handler that does calls your code "lower the hook count code" and then continues an exception.

It would nice to have some API for "fix ret address and handle SEH exception built-in MCH library". It would be also nice to have this feature available in all of the MCH hooks. Also debuggers stack trace will work better.

Any thoughts?

Sicerely
PP
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: MCH and SEH

Post by madshi »

Interesting problem. And a rather difficult one. Especially x64 will be tricky because the x64 exception handling is so much different. Basically each dll/exe has a list of except handlers. But the hook stubs installed by madExcept are dynamically created, so they don't have a registered except handler.

I'll add this as a possible feature to my madCodeHook 4.0 to do list, but I'm not sure yet if I'll be able to pull this off completely automatically in both x86 and x64.
EaSy
Posts: 150
Joined: Tue Oct 23, 2012 12:33 pm

Re: MCH and SEH

Post by EaSy »

Well,
as i think about that the best way would be not to modify ret address before the hook call, but at the end of that. So for the whole time of the hook and orig call the ret address will be original, but at the end of the hook we manually call function MchFixRetAddress. This function woud know the stack address of the last ret address of the caller of the hook and change it as your code does it now.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: MCH and SEH

Post by madshi »

But that wouldn't help with "in use" counter. It would still not be decreased, making madCodeHook believe that the hook callback function is still in use.
EaSy
Posts: 150
Joined: Tue Oct 23, 2012 12:33 pm

Re: MCH and SEH

Post by EaSy »

now:

caller calls Orig
jmp Hook, count++, modify ret address
Hook BC
call Orig
Hook AC
count--, jmp Orig Caller

new

caller calls Orig
jmp Hook, count++
Hook BC
call Orig
Hook AC, modify ret address
count--, jmp Orig Caller
EaSy
Posts: 150
Joined: Tue Oct 23, 2012 12:33 pm

Re: MCH and SEH

Post by EaSy »

i see, in case of wxception it wont work
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: MCH and SEH

Post by madshi »

An exception in the hooked API is really problematic. I think I do need to add an option to HookAPI() to enable "exception passthrough". But as I said, it will be *very* difficult to achieve, especially in x64.
EaSy
Posts: 150
Joined: Tue Oct 23, 2012 12:33 pm

Re: MCH and SEH

Post by EaSy »

what if we add try-finally in our hook and call some MCH api to lower the count?

and use function if AbnormalTermination
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: MCH and SEH

Post by madshi »

EaSy wrote:what if we add try-finally in our hook and call some MCH api to lower the count?
Hmmmm... Good thinking, I think that should work! At least as a workaround, until I (maybe) manage to implement this properly in madCodeHook.
EaSy
Posts: 150
Joined: Tue Oct 23, 2012 12:33 pm

Re: MCH and SEH

Post by EaSy »

Great,
are you able to add some support to the MCH beta for this? It would help us to use RPC calls with MCH hook counting enabled!

Thx.
EaSy
Posts: 150
Joined: Tue Oct 23, 2012 12:33 pm

Re: MCH and SEH

Post by EaSy »

One more problem comes in my mind is the EXCEPTION_CONTINUE_EXECUTION, does it mean that we will still need to have ret address fixed during the RaiseException? Because i think that finally is not called in this case during the exception.
EaSy
Posts: 150
Joined: Tue Oct 23, 2012 12:33 pm

Re: MCH and SEH

Post by EaSy »

so we need something like this?

now:

caller calls Orig
count++, modify ret address, jmp Hook
Hook BC
call Orig
Hook AC
ret
count--, jmp Orig Caller

new

caller calls Orig
count++, jmp Hook
try {
Hook BC
call Orig
Hook AC
}
finally { count-- }
modify ret address
ret
count--, jmp Orig Caller

EDIT: i changed the code, because finally behaves differently in SEH
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: MCH and SEH

Post by madshi »

Oh well, I think I misjudged it. For some reason I thought that your try..finally block would be "outside" of madCodeHook's hook stubs. But it would be inside, which makes things so much more complicated. I suppose you could use a try..except block instead of a try..finally block, and then in the except block decrease the "in use" counter *and* fix the return address, and then re-raise the exception. But that sounds really awful.
EaSy
Posts: 150
Joined: Tue Oct 23, 2012 12:33 pm

Re: MCH and SEH

Post by EaSy »

I was able to implement SEH handling using __finally. It is very very ugly since I have to abuse your counting trampoline and fix ret address during the origcall processing both for 32b and 64b and call that trampoline manually in case of exception. But it works and SEH is propagated up the stack now. :D

This won't be crash free 100% since the __finally handler is in our DLL and it is not part of your hook trampoline, but I think we can live with 99% for now.

The best solution would be to support propagating SEH exceptions natively in all MCH hooks, but that is something you need to implement something like __try _finally in your trampoline and fix the stack accordingly. On 64b you said it is harder, but you could use this function RtlInstallFunctionTableCallbackmto register that callback.

PP
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: MCH and SEH

Post by madshi »

Yes, I'm aware of RtlInstallFunctionTableCallback, it's still not an easy thing to implement in a dynamically created assembler stub. Not something I want to introduce in a minor madCodeHook 3.x build, especially since I'm already working on v4. But it's on my to do list...
Post Reply