A look at anti-virtualization in malware samples

In previous posts, I described PuppetMaster, a way to dynamically detect and control CPU-based VMM detection methods in malware samples. We ran it on 2 sets of malware samples, and here are the results.

1. 60k samples from a Nepenthes honeypot

  • 62498 samples on the honeypot
  • 59554 of them being executable files
  • 48404 were analysed “correctly”
  • 13409 samples were terminated due to a 2 minutes timeout

The number of samples trying to detect virtualization is surprisingly low:

  • 71 (0.15%) binaries used at least one anti-virtualization technique
  • 65 (0.13%) binaries used the SIDT anti-virtualization technique
  • 0 (0.00%) binaries used the STR anti-virtualization technique
  • 0 (0.00%) binaries used the SLDT anti-virtualization technique
  • 0 (0.00%) binaries used the SGDT anti-virtualization technique
  • 14 (0.03%) binaries used the VMware channel anti-virtualization technique

2. 25k samples from uh… somewhere

These samples were shared by Paul Royal, so thanks Paul :)

  • 25118 samples
  • 23104 of them being executable files
  • 18670 were analysed “correctly”
  • 8298 samples were terminated due to a 2 minutes timeout

Again, the number of samples trying to detect virtualization is very low:

  • 117 (0.63%) binaries used at least one anti-virtualization technique
  • 56 (0.30%) binaries used the SIDT anti-virtualization technique
  • 0 (0.00%) binaries used the STR anti-virtualization technique
  • 2 (0.01%) binaries used the SLDT anti-virtualization technique
  • 6 (0.03%) binaries used the SGDT anti-virtualization technique
  • 58 (0.31%) binaries used the VMware channel anti-virtualization technique

Conclusion

There are a few potential reasons why the numbers are so low:

  1. the samples used other techniques that we do not support (such as detecting the VMware tools, or hardware version)
  2. or the samples we got are really not representative of malware samples in the wild. Indeed, our 60k samples contain mostly Allaple samples.
  3. or anti-virtualization techniques are not that common in actual malware samples…

It would be interesting to run the test on better malware repositories, unfortunately this is not something obvious to get our hands on. So if you have a big malware repo ready to be dissected, and you would like to share them with an academic lab for free, I’d be glad to hear from you: reynaudd at loria dot fr.

Advertisements

Puppet Master… or how to poison Red Pill

Today we’ve been working with Vincent Mussot on a way to prevent VMM detection with red pill. We implemented it as a simple pintool:

// see the PIN manual for compilation instructions
#include <iostream>
#include <string>
#include "pin.H"

unsigned long int fake_idt = 0;

VOID poison(unsigned int* m) {
    *(unsigned int*)((*m)+2) = fake_idt;
}

VOID Instruction(INS ins, VOID *v) {
    string dis = INS_Disassemble(ins);
    if (dis.substr(0,4)=="sidt") {       
        unsigned int rpill = INS_Address(ins);
        unsigned int* m = (unsigned int *)(((char *)rpill)+3);
        INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)poison, IARG_PTR, m, IARG_END);
    }   
}

// omitted for brevity
// parses the command line and sets fakeidt
int parseArguments(int argc, char **argv);

int main(int argc, char * argv[]) {
    if(parseArguments(argc, argv)) {
        printf("Usage: pin -f <toolname> <fake_idt> -- <binary> [arguments]\n");
        exit(1);
    }
    PIN_Init(argc, argv);
    INS_AddInstrumentFunction(Instruction, 0);
    PIN_StartProgram();   
    return 0;
}

Definitely not easy to read, but we followed the red pill coding standards ;) It waits for red pill to execute the SIDT instruction and then overwrites the memory location containing the value of the interrupt descriptor table register (IDTR) with an arbitrary value, given on the command line.

> redpill.exe
idt base: 0xff03f400
Inside Matrix!

> pin -t puppetmaster.dll 0x2501 -- redpill.exe
idt base: 0x2501
Not in Matrix.