Today I had a chance to fast-read two interesting papers. I want to mention them here on this blog post for two reasons. First of all to not forget about them (so as a personal memo :-)) and secondly because maybe someone will find them interesting as well.
The first one called "Control-Flow Integrity Principles, Implementations, and Applications" describes the CFI (Control-Flow Integrity) mitigation technique. Security policy used in CFI dictates that software execution must follow a path of a Control-Flow Graph (CFG) which is determined ahead of time. They provide the CFG information in this case by using static analysis. The rest of the process is pretty standard (static binary rewriting + code instrumentation). In the static binary rewriting part they are using a tool called VULCAN (also from Microsoft), which apparently is much more advanced that my own engine and in my humble opinion looks pretty awesome. As for the code instrumentation part it seems they are using emitted magic values (aka IDs) and runtime ID checks. So for example before the jump indirect gets executed the first four bytes of the destination-4 address are checked for the emitted value. If the magic value is not found the "error handling" procedure will be executed. Otherwise the control is transfered to the destination address. Similar technique was also described by the PaX guys as a mitigation against ret2libc attacks. I found this one really interesting since lately I was working on something similar. Anyway I'm not sure how this magic bytes emission (IDs) is synchronized among other modules since for me this seems like a pretty troublesome part. Maybe someone can give some hints here? :-)
Second paper called "Efficient Validation of Control Flow Integrity for Enhancing Computer System Security" utilizes some hardware features. Among other features they are using Last Branch Recording (LBR). So according to the paper they are monitoring every mis-predicted indirect branch instruction and every return instruction (because return instruction may not generate return address mis-prediction). Each time an indirect branch mis-prediction event happens their filtering interrupt-handler is executed. When security policy is violated (Table 3.1) the process gets terminated. For example the call indirect policy states: allow only if the destination address is a function entry point. And here it gets problematic since to obtain function entry points (or to be exact the Indirect Branch Pairs) they need to either use static analysis of the control flow graph of the program or perform the program profiling (something like running a learning process on a clean machine). I think this may cause some false-positives cases since in both of those solutions there is no guarantee that all paths will be traversed. Finally the most problematic things appears to be a fact that you can't use any of those hardware features in virtualized environments like VMmare etc. Obviously it heavily depends on hardware plus the performance is questionable.
I must confess I was also wondering about using this hardware feature in my engine (just limiting it to ring0) however it seems that disadvantages of this method are too significant.
Ok that would be all for today! Cheers!