Code Encryption vs Code Virtualization

Published 10.09.2019

Code Encryption vs Code Virtualization

Today we will be presenting the differences between Code Encryption and Code Virtualization.

When looking for an obfuscator, customers often see two terms "Code Encryption" and "Code Virtualization", at first glance, both names sound similar, but there is quite a difference with them.

Today we will be analyzing what each feature does in your application, ensuring that what you're getting is what you want.

Code encryption usually comes together with "military-grade encryption." (another term which in the future we will analyze ).

These two terms together make it seem as if what was in front of us was the final solution to protecting code. However, is that the case?

What code encryption means in short terms is that the body of the methods is stored safely in the application and decrypted later upon execution.

That's right, to execute the encrypted code, you need to decrypt it, meaning that in memory, your code resides freely and becomes an easy target for attackers.

There are various tricks that protectors apply to mitigate this flag so that just dumping the application from memory won't leak the real code.

The most common example is the well-known DynamicMethod Class, which allows us to create methods from IL code.

Initially, this technique was successful and could withstand most attackers.

In the end, no procedure lasts for good in this world; nowadays, attackers re-construct the body of the methods by hooking into the very DynamicMethod instance and retrieve our original code.

On the other hand, we have protectors that modify the JIT. This technique is the best approach that an obfuscator can do when it comes to code encryption.

To decrypt the code in this scenario, you're forcing the attacker to statically decrypt the code  (which tends to be extremely tedious) or to be familiar with the JIT compiler.

So far so good, nonetheless there are still a couple of things to note:

Instability as a passive risk, when modifying the JIT, we're going into a zone where we're not supposed to. 

Compatibility problems, changing the JIT behavior require us to focus on specific versions of the .NET Framework. Usually, we will end up with our application only working on particular environments (typically Windows and latest versions of the .NET Framework).

The concept is excellent; nevertheless, the results that we observe on the market have opted for a conservative system in which innovation is prime for its lacking.

We can't blame them since, as stated, maintaining JIT customizations can be complicated when serving to a broad public.

Here at Cyphor, we had an initial proof of concept where we would implement this powerful technique but improved for those who develop Windows applications.

However, we decided to focus on those features that work in all environments. In the future, we may potentially add this feature, depending on the demand and feedback we see from customers.

Finally, we have Code Virtualization, considered the peak of obfuscation as of now.

In general terms, when you virtualize your code, you're not executing it as standard IL, you have a virtual machine attached to your program emulating a new set of instructions that are equivalent to your original piece of code.

By doing this, the recovery process becomes arduous and time-consuming for an attacker that wants to get the original code, there is no way around or "tricks" that they can do to retrieve it back, they have to deal with the new language and translate it back to IL.

If, on top of this process, you encrypt the custom machine code, you have a nearly bulletproof solution.

We at Cyphor have opted for this approach; the code of our virtual machine is encrypted and gives a different output on each protected file.

As a result, we have one of the best implementations of Code Virtualization on the market.

There is an obvious drawback in this protection; you should not apply it to the whole application.

The performance impact is considerable as we're not taking advantage of all the operations the JIT does to optimize our code. 

We recommend using Virtualization on those methods that require a higher level of protection, such as authentification, encryption, integrity checks, etc.

We sincerely hope that this article was helpful to you. Stay tuned to our blog as more posts are on the way.

Newest Blog Posts

Your application was hacked
Your application was hacked

Published on 26.11.2019

Read More »
How to Decompile .NET Applications
How to Decompile .NET Applications

Published on 15.11.2019

Read More »
Code Encryption vs Code Virtualization
Code Encryption vs Code Virtualization

Published on 10.09.2019

Read More »