An inherently unsafe way of hooking

Apr 14, 2011 at 6:59 PM

EasyHook is an interesting demonstration and experimentation platform. However I'm sorry, I have to say EasyHook is inherently unsafe from a computer science point of view. It may work well in many cases, it can detect some cases that are unsafe and refuse to hook. And finally after reviewing install.c and reloc.c I see some unsafe cases which are not detected, and what is more: it is nearly impossible to detect all those cases.

We are talking about crashing the processes that are hooked!

The problem is the way EasyHook installs hooks. It modifies the first bytes of the function to hook. They are replaced with a jump instruction, while the original assembler instructions are moved to a new location - and have to be adjusted to this location.

Modifying unknown code in memory is non-trivial. Here are just a few cases that are not covered:

1) what if the hooked function jumps back to the first, second, third, etc. assembler instruction? All replaced instructions are concerned. Jumping to the first instruction may be ok, if you don't mind to count that as a recursive call. However it may not be what the user expects. Jumping back to the second instruction will most likely crash the process.

If you analyze/disassemble the hooked code deep enough, you may detect some of these cases. But I doubt you can do it completely, especially if obfuscation technologies are applied to the code, e.g. it is encrypted. Or just assume the jump uses a calculated address from a table... crash!

And once you assume other tools and APIs may modify code at run time, all kind of additional nasty possibilities have to be considered.

There is a good reason why the "int 3" debugger break instruction is just one byte long - precisely to prevent these difficulties when setting a break point. Which leads to a second scenario:

2) what if break points are placed in the relocated code? Break points are not only used by debuggers, but also by tracing and hooking tools. If the function EasyHook hooks is already hooked by such a tool, the other hook is broken. The other tool can no longer handle the resulting break exception properly - and it will most likely pass the exception to the process, which then terminates unexpectedly. Crash!

This kind of problem could be detected (but currently it is not, as far I can see). However hooking a function that currently has a break point is impossible with EasyHook.

3) Is EasyHook otherwise safe to use with other hooking apis? I don't think so. For one thing how to remove a hook without accidentally unhooking a hook from another tool? The only safe way would be not to unhook. Again there may be some situations where you can detect your hook code was modified (hooked) and refrain from unhookin. In general I think just deactivating the hook and leaving it in place is the safe way to go.

Finally some minor notes:

4) There is an obvious memory leak in RtlMoveMemory() in EasyHook_2.5_Beta_Source_Code\EasyHookDll\Rtl\memory.c.

5) Are you sure assigning a 64 bit variable in C is atomic? I would assume it depends very much on compiler and processor used. Why not play it safe and use the InterlockedExchange primitives in install.c? Otherwise there may be another source for rare and hard to explain crashes if two threads (on different CPU cores) try to hook the same function at the same time.

Christoph, I would be glad if you can prove me completely wrong. But what I have seen in the code scares me a lot. If it usually works, that is because other developers are conservative and do not use risky techniques, especially not one like this.

EasyHook as it is is a nice project to experiment, it may be good for some tests, it sure is a cool demonstrator for this kind of hooking, but it clearly shows the limits of this approach, so please don't make developers use it in software that some day might be running on my computer. Windows got a bad name for almost-working solutions that are nearly impossible to fix and cause occasional instability. Please don't add to this!

Coordinator
Apr 14, 2011 at 9:09 PM
Edited Apr 15, 2011 at 11:02 PM

First I'd like to say that your approach to comment/vote on free projects seems really bold. That said you get a proper bold response back. I know this is a childish behavior, but after all you are following big footsteps when you manage to stay a child...

To prevent everyone else from wasting his/her time, I already did this by posting here, the conclusion is that how someone can even think, while all documentation shipping with EasyHook everywhere claims the instabilities involved in hooking (especially in general and not just for EasyHook), about writing such a post like above is beyond me...

> However I'm sorry, I have to say EasyHook is inherently unsafe from a computer science point of view.

Well whats up with you? Do you have even any idea what you are talking about? I guess not. No, EasyHook is not safe, neither is any hooking library out there. BTW this is clearly stated in the "Security advisor" within the "Tutorial and Introduction"... Hooking is unsafe itself and is the main reason for windows to be unstable. The main reason why PatchGuard has been introduced because Microsoft want's to get rid of all these 3rd party kernel manipulations, hookings having 90% of all blue screens caused by 3rd party drivers... I wonder why Microsoft even allows hooking at all. Well and voting one star because you don't understand all of this is very interesting ;).

> It may work well in many cases, it can detect some cases that are unsafe and refuse to hook. 

Yeah and often you may walk blindfolded over a minefield and sometimes you might be blown...

> it is nearly impossible to detect all those cases.

Oh really? Hmm that's interesting, so you are saying your post makes no sense at all? Well in that case I really have nothing to add :).

> We are talking about crashing the processes that are hooked!

Well that is what everyone knows when starting the whole hooking thing... And now even you have discovered it yourself.

>1) what if the hooked function jumps back to the first, second, third, etc. assembler instruction?

Nothing, because code that can't be dynamically adjusted is not relocated. If you mean a function jumping back from somewhere internal... Well considered it as covered by the following: Hooking encrypted code with EasyHook, yeah? Again the evidence that you don't know what you are talking about... Why not stating that you shouldn't use EasyHook to fix bugs in nuclear plant software? Maybe I am now responsible for latest disasters right? I even have various claims within the license and the tutorial so in fact EasyHook, as well as any other hooking software and in fact most other software too, is something like a cigarette. Everyone, except you who ignores all security advisors, knows that it can be dangerous but they use it anyway on their convenience...

>But I doubt you can do it completely, especially if obfuscation technologies are applied to the code, e.g. it is encrypted.

You guy seem to be a real genius. But keep thinking and guessing, this is a free world...

> And once you assume other tools and APIs may modify code at run time, all kind of additional nasty possibilities have to be considered.

No they don't have to because hooking itself is inherently unstable. What you are pointing out here is what you should know before actually starting API hooking.

>3) Is EasyHook otherwise safe to use with other hooking apis? I don't think so.

Well again thanks for pointing out the obvious...

> In general I think just deactivating the hook and leaving it in place is the safe way to go.

EasyHook is doing this if the entry point has changed.

>4) There is an obvious memory leak in RtlMoveMemory() in EasyHook_2.5_Beta_Source_Code\EasyHookDll\Rtl\memory.c.

If it is so obvious why not correct it instead of just crying?

>Otherwise there may be another source for rare and hard to explain crashes if two threads (on different CPU cores) try to hook the same function at the same time.

Yeah right, and if you step some more left in Iraq you might actually get blown up by a bomb instead of getting shot in the head. Great logic here, again.

>Christoph, I would be glad if you can prove me completely wrong.

You already did it yourself. You whole post refers to the general issue of API hooking and has NOTHING to do with EasyHook in specific.

>But what I have seen in the code scares me a lot.

What I read here scares me a lot.

> If it usually works, that is because other developers are conservative and do not use risky techniques, especially not one like this.

No most developers might know what they are doing and hooking is actually a risky technique and it makes simply no sense to use it in any security software or stable software at all. And those who don't why should I care?

> 5) Are you sure assigning a 64 bit variable in C is atomic?

Ignoring the fact that thread are suspended, who cares? This is not rocket science it is hooking, god dammit.

> so please don't make developers use it in software that some day might be running on

*Abrakadaba* May all developers be enlightened... Me, the god has spoken!

>but it clearly shows the limits of this approach,

Hell yes, so because the approach is limited, which in fact has nothing to do with EasyHook, that's the reason to vote one star and write such a post? In fact because it shows the limits, you should thank it for doing so, since most commercial products keep you in illusion that hooking is safe. So what are you doing here at all?

Your way of "contributing" to free OpenSource software which in fact does its job better (or at least did it by the time it has been released) than most commercial products out there can mean either one of three things:

1) You don't understand what you are talking about

2) You are from one of these competing commercial products.

3) Or you are just ****** nuts...

The only thing that intrigues me at present is why, even though you seem to have at least some technical knowledge, you are totally messing up facts and concepts and produce such a garbage and offending post (this is what you get in return; especially because of your vote without even asking first if your concerns do make any sense at all)? BTW most of the general facts about hooking you have pointed out are indeed true. But obviously you have no idea what to do with this "knowledge" except to start some senseless flaming and discussions... Or did you just wanted to throw in some decoupled "knowledge" of your own to show that Axel666 is also there and has an opinion?

Well what am I doing here I am just wasting my time, but after all you made my day xD...

Apr 16, 2011 at 5:19 PM

Christoph,

have you read your web pages lately? What they tell is:

- EasyHook is the easy way to use hooks; everyone can use it (implying everyone should use it)

- EasyHook is licensed so you can use it in your commercial products (implying it should be used)

- EasyHook has all kinds of safety features and is stable (implying it is safe)

From some questions in the discussions section it appears there are actually users that don't know much about hooking.

So you are selling your software to the unsuspecting public without a clear disclaimer. A disclaimer saying it is unsafe. Its good you know it, but it has to be said loud and clear.

That is why I rate EasyHook poorly, and with good reason, I believe.

I'm going to ignore the insults you used so freely with regard to my person and my abilities. Let me just emphasize I did not insult you personally, and if you feel I did it was not intended and I apologize for being unclear.

There is a lot more to say, but not before you understood my main concern with this hooking method.

>>1) what if the hooked function jumps back to the first, second, third, etc. assembler instruction?

>Nothing, because code that can't be dynamically adjusted is not relocated.

I believe you are wrong here. I see a fundamental problem in the concept used. Why should it be impossible for the DLL of the hooked function to contain a jump to the second instruction? If it does, and the first instruction opcode is short... do you see it? Now, how do you detect a DLL will never do such a jump? The jump does not have to be in the instructions you relocate, it doesn't even have to be in the "function" that is hooked. It could be a calculated jump, etc. pp.

Cheers
Axel

Apr 18, 2011 at 7:21 AM
Edited Apr 18, 2011 at 7:28 AM

API Hooking is not safe.  As a serious user of the library, I think the author has stated the point clear enough, at least for me, in the source codes and documents of the project.  That's why I visit the forum regularly and pay extra attention to the issues like Axel just reported.

 

If Axel's 1st case (Jump to 2nd instruction) is valid, (I think it is), would the case be at least detectable if the hooked functions are limited to Windows standard API?

 

I have an impression which could be wrong.  Please correct if I do.  The followings are accomplished by some kind of API detour: (I am sure it is not by EasyHook)

- Running program under Windows compatibility mode

- Running 32bit program on x64 Windows

- Adobe Reader sandbox

Is the mentioned case possibly affect those system?

May 20, 2011 at 2:27 PM

fonsoon,

> If Axel's 1st case (Jump to 2nd instruction) is valid, (I think it is), would the case be at least detectable if the hooked functions are limited to Windows standard API?

reading some of the Detours publication I noticed they claim Detours is safe for the windows core DLLs. (I found no claim that it is safe for all DLLs, so reading between the lines I assume they know it is not safe.) I guess they had a way to check the DLLs for this problem. Being part of Microsoft may help to do so.

Proving this from the outside I think is harder. If the API is well behaved, i.e. it uses only documented op-codes, refrains from dynamically created or self-modifying code, doesn't use calculated jump points only in ways more complex like using a table, etc. it may be possible to prove it is safe for a given instance of the DLL. Of course you will never know if it is still true after the next Windows update.

Maybe if it can be shown that EasyHooks detour code is never larger than the one of Detour, it may be valid to conclude it is safe for those Windows core DLLs Detours supports, assuming Microsoft will take care to keep Detours working, as it is a commercial product they are responsible/liable for.

As a general remark, it seems to me that for hooking arbitrary code, using break points appears be the safest way. Followed by jump table hooking, which is faster, but less powerful. The advantage of break point hooking is that it uses a single byte opcode specifically invented to avoid the jump-crash problem, and a documented API. The drawback of course is, that attaching a debugger process is serious overhead and does not scale, because there can be only one debugger attached. (I wonder if there could be a safe way to hook the debug interrupt vector, so break points can be used without a debugger attached, but I guess trying that just opens up another can of worms, wouldn't it?)

Best
Axel

May 20, 2011 at 6:06 PM

> reading some of the Detours publication I noticed they claim Detours is safe
> for the windows core DLLs. (I found no claim that it is safe for all DLLs,
> so reading between the lines I assume they know it is not safe.) I guess
> they had a way to check the DLLs for this problem. Being part of Microsoft
> may help to do so.

IIRC, microsoft intentionally rebuild windows (XP SP2 perhaps) to
allow for safe(er) hooking ( think by adding NOP padding) . I can't
find an offical reference anymore though...

Ben