08 Apr 2015

Catch me when you can

Introduction

Exception filters have been part of ECMA-335 specification since the very beginning. I'm guessing, they were added because Visual Basic used them extensively and therefore Visual Basic.NET had to support them as well. They look something like this:

Until now C# supported try/catch but did not have support for filters. That's going to change in C# 6.0/VS2015.

How does it work

In early versions of VS2015 the syntax was "catch-if", as you can see in the initial announcement. In the latest VS2015 CTP builds, they changed syntax to "catch-when", and there's a good reason for it.

So, how does it work and what does it mean for reversers?

It's a compiler-level feature

As I mentioned before, .NET Framework has supported exception filters since the very beginning. So, this feature works even in .NET 2.0 - if you decide to target .NET 2.0 Framework in VS2015 project settings. Not that you really want to do that..

It's very useful for debugging

catch-when is implemented as an IL exception filter. So, when an exception is thrown, exception filters are processed before the stack is unwound. This means that filter method has created an error report that included the current stack trace, it would show the frame in which the exception occurred. Sounds complicated? It isn't.

Let's implement exception filtering in the "old" way:

and this is how the stack looks when we get to filter(ex):
stack_trace_old
You can't see much here. All the context is gone, you must rely on exception stack trace and message. That's what we've always done, right? smile

If we write it in a "new" way, the code looks like this:

and stack trace will give us full context of exception:
stack_trace_new
Much better, isn't it? You can see which method threw the exception, on which line, you have access to local variables and everything else. Yummy! smile

Decompiler support for exception filters is crappy

They say, a picture is worth thousand words.. In a very simple example, Reflector gets the code structure right, just filter conditions are missing:
catch_when_reflector
ILSpy handles it slightly worse, filters are messed up and unreadable. Filter code is gone, too:
catch_when_ilspy
And the latest JustDecompile just throws an exception:
catch_when_justdecompile

Have fun with it!

Here is a small keygen-me for you to play with: https://www.mediafire.com/?k5b9vy0p9dfgb97

The difficulty is 2/10, you should be able to solve it in 30 minutes or so. The entire protection is designed to show you try-catch-when feature, so avoid patching - you can't learn anything by nopping-out few instructions. wink