Understanding Managed Code Rootkits

March 16, 2015

Rootkits are scary, but, like most malware I encounter, there is a mysterious intrigue and alluring nature that accompanies the fear. Just like that urge to leave one eye open during scary movies. It is this feeling that drives my thirst for discovery and analysis. In this post, we will explain the basics of managed code rootkits that threaten the billions of devices running managed code environments as well as briefly review the potential defensive mechanisms currently available to combat this evil.

A little background...


Let's start with a quick breakdown of managed code and what rootkits really are before we jump into combining the two. Code, or source code, is the human-readable language that programmers use to communicate with computers. During the development of computer software, programmers write code in a particular programming language that will eventually be translated into machine code during a process called compilation. There are many different types of programming languages, but most can be classified as using either managed or unmanaged code. Languages that utilize unmanaged code must be compiled specifically for a particular operating system (i.e. software compiled for Windows will not run on Mac OS and vise versa). On the other hand, managed code requires the presence of a runtime environment, a sort of intermediary piece of software that sits between the managed code and whichever operating system it is being executed on. Chances are pretty high that you have used or may have even written a program that utilizes managed code - Java, C#, Visual Basic .Net and Flash ActionScript are all examples of languages that use managed code and rely on a runtime environment such as the Java Runtime Environment (JRE) or Microsoft's Common Language Runtime (CLR). Even Applications installed on Google Android devices utilize managed code and run inside a runtime environment known as Dalvik.

Since managed code is executed within a platform independent runtime environment, or virutal machine as it is sometimes referred, during the development process it is first compiled into an easily distributed runtime-specific intermediate language (IL) bytecode. This IL bytecode is later processed on the fly during execution by a just-in-time (JIT) compiler. The JIT compiler uses the locally installed runtime library binaries to interpret the IL bytecode into machine language specific to the operating system on which it is being run. As we shall soon see, these local runtime library binaries can be modified by users and other programs with administrative or root privileges.

Now let's demystify rootkits.


Rootkits are a particularly nasty type of malware, or malicious software, that modify code in another piece of software to control that software's logic. When implemented against operating systems, rootkits can provide attackers with full control over the infected system - often masquerading its own existence, modifying files and processes and stealing sensitive information. Rootkits are usually utilized by criminals who wish to maintain control of an already compromised system or rogue programmers wanting to install backdoors in software they are developing. Organizations and governments have also utilized rootkits in the past, as seen in 2005 when Sony BMG Music Entertainment attempted to thwart piracy of their CDs by employing rootkits that would modify the code of the Windows operating system to prevent unauthorized duplication [1] or the Stuxnet worm which is thought to have been developed by the United States and Israeli Governments to disrupt Iran's nuclear program by making slight adjustments to the speed of their centrifuges [2]. Due to their evasiveness, rootkits can be difficult to detect and completely destroy the trustworthiness of the infected software. The best course of action to take if a rootkit has been identified is to completely re-install the software from a trusted source.

So what's the deal with managed code rootkits you ask? Much like rootkits that target operating systems, managed code rootkits seek to control the runtime environments of managed code programming languages. Once infected, the trust-based relationship between the runtime and any applications that it executes is broken.

Here's one example illustrating the basics of managed code rootkits: Imagine a simple program written in C# that outputs one line of the text "Hello, World!". Along with some other basic code, the command "System.Console.WriteLine("Hello, World!")" would be used to achieve this.

1
2
3
4
5
6
7
8
// HelloWorld.cs
public class Hello
{
    public static void Main()
    {
        System.Console.WriteLine("Hello, World!");
    }
}
After compilation to IL bytecode, the developer distributes this program to his friend's computer who happens to have a version of the .NET Framework installed. This is a good thing because the .NET Framework contains the CLR runtime needed to execute the program. But when the programmer's friend runs the program, unexpected behavior occurs. Instead of the program printing only one line of the text "Hello, World!", it actually prints the text twice! Why does this happen? The code the programmer wrote only invokes "System.Console.WriteLine()" once. It turns out that the friend's runtime class library files, specifically the mscorlib.dll which is utilized by the runtime environment during execution to convert the IL bytecode for "System.Console.WriteLine()" to appropriate machine language, has been modified!

This seemingly harmless modification was achieved by disassembling mscorlib.dll to it's own IL bytecode, duplicating a handful of lines in the "WriteLine(String)" method of that bytecode, reassembling it back into a .dll file and then properly deploying the modified file so that the runtime uses it instead of the original. The modification will change the behavior of any program using the "System.Console.WriteLine()" command executed on that computer, basically changing the behavior of the programming language without the developer or runtime knowing.

The potential uses of managed code rootkits are vast. The predominant threat involves the ability to change the meaning of an entire programming language to suit an attacker's needs. Managed code rootkits can also be used as a vector for further infection or penetration into a system through its interactions with the operating system, but this is less likely as elevated permissions are required for the implementation of managed code rootkits. It should be emphasized that the existence of a managed code rootkit on a system most likely indicates that a major compromise has occurred. Upon identification, action should be taken to segregate any infected system and, if necessary, proper forensic investigation should be performed.

What can we do?


Now, before you frantically reach for your computer's power cable and exclaim "We're all pwned!" there are several possible solutions available, most of which focus on deterrence as opposed to outright prevention. The goal, as with many security technologies, is to make this specific type of attack less appealing to an attacker. Here are some possible security measures that could be implemented to combat managd code rootkits:


  • There currently exist methods of signature based verification of the runtime binary files which is not very effective and can be easily bypassed by an attacker.
  • A very strong alternative to the above could be a mechanism for the randomization of binaries at runtime similar to what has been used in address space layout randomization (ASLR) techniques to combat buffer overflow attacks.
  • Third-party solutions exist that provide obfuscation of runtime binaries for many of the runtime environments. This type of defense makes it much more difficult for a potential attacker to disassemble the binaries of a runtime.
  • The implementation of critical system file monitoring could also be expanded to notify of any changes made to the runtime.
As best practices dictate, a defense-in-depth solution should be pursued to ensure the security of a system and effectively defend against an attack of this caliber. 

In this crazy technology dependent world that we have fostered, awareness of a given threat is an integral part of the defensive posture; Knowing when and where vulnerabilities exist is the first step towards detecting and fixing them. As new threats continue to develop and mature, security practitioners must stay ahead of the curve by developing sound security models and employ capable, well tuned monitoring technologies in order to ensure the confidentiality, integrity and avaliability of the information they protect.

If you are interested in additional information on rootkits or managed code rootkits then I highly recommend picking up Managed Code Rootkits: Hooking into Runtime Environments by Eraz Metula (ISBN 978-1-59749-574-5) and Rootkits: Subverting the Windows Kernel by Greg Hoglund and James Butler (ISBN 0-321-29431-9). Both of these books go into great detail on the development of rootkits and the solutions available to defend against them.

Information and material in our blog posts are provided "as is" with no warranties either expressed or implied. Each post is an individual expression of our Sparkies. Should you identify any such content that is harmful, malicious, sensitive or unnecessary, please contact marketing@sparkhound.com.

Meet Sparkhound

Review our capabilities and services, meet the leadership team, see our valued partnerships, and read about the hardware we've earned.

Learn How We Work

See how our Plan/Build/Run methodology drives real client success, and gain our team's perspectives on timely tech topics.

Engage With Us

Get in touch any of our offices, or checkout our open career positions and consider joining Sparkhound's dynamic team.