Escaping the Matrix—How Malware Evades Researchers (Part 3 of 3)
In the first and second parts of this blog series, we looked at means of detecting debuggers and common sandboxing environments. This post could be seen as a part of sandboxing detection – detecting a possible sandbox by detecting the virtualized environment. While this can lead to false positives (detecting the environment as a sandbox when, in fact, it's a virtualized desktop) the added security (or reconnaissance of the target – knowing that they don't use desktop virtualization) can justify the decision to add these.
VM detection has been thoroughly investigated as a means of protecting against analysis. Before the age of high-scale virtualization, many people thought all malware would start to incorporate such protection mechanisms. The prevalence of virtualized systems has caused malware authors to be more permissive of VMs. Not all of them, of course. A sophisticated attacker aiming for a target that he knows only uses physical machines for the systems of interest will implement all possible VM detections. Ransomware authors sometimes avoid VMs since most home users (their main target) use physical machines. Avoiding a VM in this case can mean evading analysis and a longer duration until security appliances start detecting the malware strain.
Just like sandboxing environments, there are many possible giveaways for virtualized environments.
Don't Be Cheap (With Your VMs)
Since the VMs running malware don't do anything but run malware, there isn't any point in adding too many resources or needless hardware, right? Wrong! Here’s a check for a reduced size of the hard disk drive:
Basically, if you have less than 60GB of HDD space, the malware will stop. Similar checks are done in Paranoid Fish for the number of CPUs, physical RAM, and others. One trick used by TeslaCrypt is checking for an audio device. Originally discovered by Joe Sandbox, it will exit if none is available:
So the key takeaway from this is—don't be cheap when configuring your VMs, or at least give them the impression that they have the necessary hardware.
Checking for Known Files
The easiest of all is if the hypervisor comes with a set of host-specific additions (VirtualBox Guest Additions, VMWare Tools, etc.). One example from Paranoid Fish:
Checking for a file is a bit more difficult when you don't know whether you're on 32- or 64-bit Windows and the system folders might have been redirected. Luckily, Paranoid Fish hides that from us with a trustworthy helper. So if you've installed the VirtualBox guest additions, malware will know, if you don't install them, you might have a generic monitor with a low resolution so malware will also be able to detect. Files aren't the only giveaway, running processes can also be traced.
VMware happily advertises itself if you ask nicely:
Basically, you use the IN instruction (which should read a value) to supply the hypervisor with two magic values and expect it to change a third register to a magic value. This is completely different from the way the IN instruction should work.
Note: this is a feature, not a bug!
Most hypervisors use specific strings when introducing the hardware they emulate. QEMU, for example, names its IDE strings "QEMU HARDDISK ATA Device" and the default CPU is named "QEMU Virtual CPU". VirtualBox and VMware do similarly. The BIOS name and vendor can also be giveaways. There are multiple ways to detect these - WMI, Windows registry and others - and these get reset by Windows when starting, so to hide your VM, you'll need to convince the hypervisor to introduce other device names or change the relevant registry keys and revert to snapshot, avoiding a reboot. Sometimes a reboot is required so the problem becomes more difficult.
Here's an example (again, aided by Pafish helpers) of checking the VideoBIOSVersion data in the Windows registry:
VirtualBox also gives itself away in the DeviceId fields for emulated devices. Here’s an example using WMI queries via the helpers in Pafish:
Most hypervisors also use a specific set of MAC addresses for the network adapters:
Note: This is customizable on almost every hypervisor, so fixing this issue should be easy.
There are a lot of different fields to check and most are specific to the hypervisor involved. See more examples in the Paranoid Fish source.
Reading the Timestamp Counters
Timekeeping on VMs is notoriously hard. This can be an issue both when emulating time passage in software and when timekeeping instructions are executed inside the VM. Here are the default two examples from Paranoid Fish using the RDTSC (read timestamp counter) asm instruction, which returns a 64-bit value representing the timestamp in EDX:EAX:
The first two functions compute the difference in counter values in two different ways—one by chaining the RDTSC instructions, the other by executing a CPUID in-between. When running inside a VM, the cpu_rdtsc() function will take a lot more (on average) than when running inside a physical machine. Some hypervisors will—by various means—track the TSC value so that this check will fail to detect them. However, the second check—cpu_rdtsc_force_vmexit—exploits the fact that the hypervisor will cause a trap when executing CPUID (which will change context from the VM to the hypervisor), severely delaying the operation. This problem is extremely hard to solve on any hypervisor and changing its behavior could easily leak VM info in other places.
These conditions might seem esoteric—they are. Most of the time they rely on trial and error and may easily fail from specifics in hypervisor implementation, system load and others. Take, for instance, the following code that Forcepoint recovered from a Locky sample dated June 2016:
What this does is use an empirical observation that CloseHandle should only be slightly slower than GetProcessHeap on a physical machine than on a VM—the limit of 10 is definitely empirical and could even fail on a physical machine! The code does a good job of detection most of the time. However, using VT-x in virtualization will typically fool this check because of the improved execution speed. Note that this check is not limited to these two functions—any pair of functions can be used as long as they can be trusted to reliably execute differently between a virtual and physical environment.
Who Are You, CPU?
Since I brought the CPUID instruction into discussion earlier, I might as well touch on a second means of VM detection using it. CPUID gives capability-related CPU information. It's an instruction that can be used legitimately by an application to check whether specific functionality is available in hardware.
CPUID receives a parameter (EAX register) called a leaf in Intel-speak. Two specific leaves are of interest here:
- 0x01—will return a "hypervisor" bit in ECX that is set when a hypervisor is present; QEMU allows for this bit to be changed (hiding the hypervisor)
- 0x40000000—will return the hypervisor name; KVM can disable this
This was a very long post. I'm really happy if you managed to make it so far. If you didn't and just skipped to the conclusions don't worry—I could probably have condensed this or searched for simpler examples, but I'm afraid I wouldn't have correctly captured the numerous options at the disposal of malware writers (as well as the level of knowledge and sophistication required for some).
There are a lot of different ways for malware to evade detection software as well as analysis environments, and something new can come along at any time. One recent example is Furtim, which was documented in the past couple of months. The level of protection encountered in this malware is extremely high— probably as a result of the improved security measures malware authors have to bypass for their software to survive long enough.
Malware creators and analyzers are constantly playing a game of cat and mouse. Our job is to think ahead of the next steps a malware writer will attempt to use to avoid detection and be prepared to respond when it comes. By looking at techniques used today to detect sandboxes and analysis engines, we are able to build better tools that detect more malware earlier. That way, the next time a new evasion comes out, we aren’t already on the back foot in analysis.
Leverage Subscription Service to Stay Ahead of Attacks
The Ixia BreakingPoint Application and Threat Intelligence (ATI) Subscription provides bi-weekly updates of the latest application protocols and attacks for use with Ixia platforms.