ConfuserEx’s official release has finally come! Go over there and show your support for this awesome obfuscator. A lot of new cool features have been added as well such as JIT anti-tamper!
In my last post I released a project called SJITHook, which is basically just a small class to easily create a hook to the .NET just-in-time compiler in order to be able to modify or analyze methods at runtime. I’m sure a lot of you guys know how it works, but for those who don’t I’ll try to explain it right now. But before anything, you should read about the .NET just-in-time compiler to keep up.
There are 2 DLL’s used in every standard .NET application, either Mscorjit.dll or Clrjit.dll depending on what .NET version the assembly is targetting. Mscorjit targets 2.0 and below while Clrjit.dll target 4.0 and above. They have two things in common though, which makes it a lot easier for us to write hooks for them. They both have an export called “getJit” which returns the address of the V(irtual function)Table in a class called CILJit. If you’re unaware of what a VTable is then read: Virtual method table. They also both have the same signature for the function we’re gonna hook, called “compileMethod”. This method takes your raw IL code along with a LOT of metadata crap and other stuff and compiles it to native assembly code. So each time a function is ran for the first time, it’s ran through compileMethod, turned in to assembly code, and then if it’s called again it jumps straight to the assembly code. A lot of obfuscators and protections take advantage of this process. They do this by encrypting the IL method bodies in an assembly, so they are unreadable to a static decompiler and then decrypts the code in a compileMethod hook and then passes it on to the original compileMethod in clrjit/mscorjit.
I created a quick diagram to hopefully help visualize what this means:
Let’s take an example of the code in SJITHook where I retrieve the pointer to the VTable:
The returned pointer is the one referred to as “pVTable” in the diagram above too. So in order to get a pointer to the VTable (or more exactly, the first entry in the VTable) we dereference pVTable:
It’s a quite straight forward process from here on. It basically goes:
- Save original address of compileMethod. (See this)
- Overwrite the first entry in the VTable that points to original compileMethod, with our own function. It needs to have the exact same signature and calling convention to not mess up stack. (See this)
- In our hooked compileMethod function we can do whatever we want, but we have to call original compileMethod at the end. (See this)
- When we’re finished, we can unhook by rewriting address of original compileMethod into first entry in VTable. (See this)
If we take a look at the hook from a physical memory point of view, this is what the VTable looks like (first line is compileMethod pointer):
There are however a few things we have to keep in mind when doing this. Most importantly, we have to recognize that our own functions will trigger the JIT and in turn our hook which creates an infinite loop and crashes the application. This is why we have to ‘prepare’ our own defined methods before creating the hook. Using RuntimeHelpers.PrepareMethod/Delegate forces the method to be ran through the JIT even though it’s not executed:
Something to note is that there are numerous ways of hooking a function, this is just one of them. The reason I use this method is because it’s easy (automatic even) to make it support both x86 and x64 bit application with the usage of .NET’s IntPtr type. Read more about hooks here: http://en.wikipedia.org/wiki/Hooking#Runtime_modification.
I hope this gave you some insight on what SJITHook does and how it works internally. And if there’s still things that are unclear, feel free to leave a comment below and I’ll do my best to answer it. 🙂
Just a small little project I decided to release. It allows you to easily create a JIT hook in a .NET application. It can be used to do stuff like dynamic method decryption at runtime (commonly used in obfuscation). You can find the project here: SJITHook.
If you’re unsure how to use it, please read the ReadMe.
Example of what it can do:
I’ll soon release a blog entry here explaining exactly what this project does, and how it works more in depth. 🙂
Something I’ve wanted to write about for a while, and just recently got around to. This paper shows you how you can globally decrypt MSIL methods by dumping them from JIT.
Introduction If you’re not familiar with how the JIT compiler in the CLR runtime works, you should probably read http://geekswithblogs.net/ilich/archive/2013/07/09/.net-compilation-part-1.-just-in-time-compiler.aspx or any other article covering it to understand the basics. The reason this is global is because every .NET assembly that is compiled to IL code needs to be compiled into machine code (assembly) at runtime. This is done by either mscorjit.dll (.NET 3.5 and lower) or clrjit.dll (.NET 4 or higher). Both of these have a function called “compileMethod” that does the actual compiling. Basically the raw IL code is passed to compileMethod and from there a native method is created. This means that even if an obfuscator or protector completely encrypts the body of a method, it HAS to be passed to compileMethod as a clean (obfuscation may still be present), buffer of IL code. This is why we’re gonna take advantage of compileMethod in order to dump the clean bodies. The reason I say this is an almost global decryption method is because some protections use code virtualization, such as Agile.NET. This means the IL is converted to their own custom bytecode and never runs through the JIT compiler. So the method of decryption I’m about to show is useless against this sort of protection. However, if you’re interested in decrypting a custom bytecode such as Agile.NET’s you should take a look at de4dot. In this demonstration I will be using the most common ‘template’ for JIT hooking, created by Daniel Pistelli. You can find it here: http://www.codeproject.com/Articles/26060/NET-Internals-and-Code-Injection#JIT_Hooking_Example.
Read it here: Manual global decryption of MSIL methods