More on Exception Handlers

Sitting here at "Blue Hat" watching David Maynor present – pretty cool working for a company that can host its own security conference just to educate employees…

A comment just came in that was a good question, and deserves a detailed answer –

Arkon asked:

well, you are mostly correct, but here's an exception-

what about catching the exceptions so you can write a mini dump and send it to a server for later analysis? (and then you can un/safely crash)

There are a few things you can do, and all of them have some degree of risk. All the work that's been done to protect exception handlers is trying to stop two attacks – the first is an arbitrary pointer overwrite – exception handlers are good targets, because if I can subvert an exception handler, all I have to do is cause an exception – pretty easy bar to hit. The second is that until the latest compiler, an unbounded overwrite could hit an exception handler, and /GS wouldn't save you – this is really well documented by David Litchfield. The latest compiler will save you for a couple of reasons, and I covered that in WSCV.

One of the points David makes is my main point here – anything you do, except crash, once an app has been corrupted is dangerous. We did have a function you could call to handle /GS exceptions – David showed conclusively that this can't be done safely, and we don't allow that any longer. Anything done by an exception handler thus has some degree of risk.

That said, there's some good reasons to do things – we have to have crash dumps in order to fix bugs, though that's best done by attaching a debugger or something that behaves like a debugger (e.g., Watson). If your process is frozen, and something else is dissecting it, that's a more secure situation. There are other things, like document recovery that need to run in-process – that's an inherently dangerous thing to do, but it provides a LOT of value to the customer. Like everything else in security, it isn't about risk avoidance, it's about risk management. You're right that there are sometimes valid reasons to catch a crash, run some code, and then go ahead and exit – but every time you do that, you're raising your risk.

The main point of my previous post is that blindly handling structured exceptions is just a horrible thing to do – you're taking this to an extreme in that case – your app has been corrupted, you have no idea what happened, but you're just going to go about your business anyway. There is some risk to creating a crash dump in-proc, more risk to doc recovery, but those are calculated risks that have business reasons. Catching exceptions just because you're too lazy to figure out where the real problems are (or because you're under the very mistaken belief that you really fixed the problem), just defeats ASLR and will get you hacked. There are very good reasons to catch very specific exceptions (see the comments on MapViewOfFile for one example), but if you don't understand exactly what you're handling and why, don't handle exceptions.

As an example, you could do this:

__try

{
SafeInt< int > si = x;
x *= y;

}
__except( IsIntException() )
{
return E_FAIL;
}

Please note that C++ exceptions are a whole different topic, and assuming you haven't mapped SEH exceptions to C++ exceptions, catch( … ) isn't always a bad thing.