Sunday, October 6, 2013

Cuckoo sandbox hardening (virtualbox)

When analyzing malware, it is always interesting to have a sandbox environment to speed up dynamic analysis. You can always use public (or private) system on the internet (like malwr.com or threatexpert.com) but you miss the complete control of the system (live internet callbacks) and more important you give the sample to the "cloud".
This is the reason why I wanted to test cuckoo sandbox as this is python based and opensource (http://www.cuckoosandbox.org/).

After some time following the (good) official guide, I finished with a fully working virtualbox based sandbox environment.
After firing some sample that I never had time to really analyze, I have to say that I was a little bit disappointed, a lot of sample didn't run at all. I was suspecting that the anti-vm included in actual malware were detecting the virtualbox (or the cuckoo processes?).

There are some articles on how to harden cuckoo running on virtualbox so I started with alienvault blog post (http://www.alienvault.com/open-threat-exchange/blog/hardening-cuckoo-sandbox-against-vm-aware-malware) but it is a bit outdated. I finally found a more recent post (version 0.6) (http://kromer.pl/malware-analysis/installing-and-hardening-latest-cuckoo-sandbox-on-gentoo-linux/). As I'm on  debian or ubuntu I had to modify a bit but this was a good start.

I used the netlog branch, patched the cuckoomon dll (btw if you are on ubuntu change the Makefile (CC parameter) on line 2 with: CC = i586-mingw32msvc-gcc).
After sending the famous "pafish.exe" to my Virtualbox sandbox I was surprised to see that it detects the virtual machine through a registry key "VideoBiosVersion":

Ok, so we could simply add a hook for this registry key but it makes me feel that pafish is not exhaustive in regards to virtualbox detection. To try to have a full list of virtualbox detection I refer to the research of WALIEDASSAR (@waleedassar) that published 9 methods to detect Virtualbox (http://pastebin.com/RU6A2UuB).
To compile it "out of the box" on ubuntu use this code (I modified it a bit to better view the possible detected method in the running VM). I also removed method 9 as this is related to "Shared folder" and I don't have any on the sandbox VM:

//http://waleedassar.blogspot.com - (@waleedassar)
#include <windows.h>


void ToLower(unsigned char* Pstr)
{
char* P=(char*)Pstr;
unsigned long length=strlen(P);
for(unsigned long i=0;i<length;i++) P[i]=tolower(P[i]);
return;
}

int main(int argc, char* argv[])
{
//method 1
HKEY HK=0;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"HARDWARE\\ACPI\\DSDT\\VBOX__",0,KEY_READ,&HK)==ERROR_SUCCESS)
{
        printf("VirtualBox detected Method 1\n");
system("pause");
ExitProcess(1);
}

//method 2 -- requires Guest Additions to be installed.
HANDLE hF1=CreateFile("\\\\.\\VBoxMiniRdrDN",GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,0,OPEN_EXISTING,0,0);
if(hF1!=INVALID_HANDLE_VALUE)
{
                printf("VirtualBox detected Method 2\n");
                system("pause");
ExitProcess(2);
}


//method 3 -- requires Guest Additions to be installed
HMODULE hM1=LoadLibrary("VBoxHook.dll");
if(hM1)
{
                printf("VirtualBox detected Method 3\n");
                system("pause");
ExitProcess(3);
}

//method 4 -- requires Guest Additions to be installed
HK=0;
if( (ERROR_SUCCESS==RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Oracle\\VirtualBox Guest Additions",0,KEY_READ,&HK)) && HK)
{

printf("VirtualBox detected Method 4\n");
                system("pause");
RegCloseKey(HK);
ExitProcess(4);
}

//method 5
HK=0;
char* subkey="SYSTEM\\CurrentControlSet\\Enum\\IDE";
if( (ERROR_SUCCESS==RegOpenKeyEx(HKEY_LOCAL_MACHINE,subkey,0,KEY_READ,&HK)) && HK )
{
unsigned long n_subkeys=0;
unsigned long max_subkey_length=0;
if(ERROR_SUCCESS==RegQueryInfoKey(HK,0,0,0,&n_subkeys,&max_subkey_length,0,0,0,0,0,0))
{
if(n_subkeys)  //Usually n_subkeys are 2
{
     char* pNewKey=(char*)LocalAlloc(LMEM_ZEROINIT,max_subkey_length+1);
 for(unsigned long i=0;i<n_subkeys;i++)  //Usually n_subkeys are 2
 {
     memset(pNewKey,0,max_subkey_length+1);
     HKEY HKK=0;
                          if(ERROR_SUCCESS==RegEnumKey(HK,i,pNewKey,max_subkey_length+1))
 {
  if((RegOpenKeyEx(HK,pNewKey,0,KEY_READ,&HKK)==ERROR_SUCCESS)  && HKK)
  {
    unsigned long nn=0;
    unsigned long maxlen=0;
    RegQueryInfoKey(HKK,0,0,0,&nn,&maxlen,0,0,0,0,0,0);
                                     char* pNewNewKey=(char*)LocalAlloc(LMEM_ZEROINIT,maxlen+1);
if(RegEnumKey(HKK,0,pNewNewKey,maxlen+1)==ERROR_SUCCESS)
{
      HKEY HKKK=0;
          if(RegOpenKeyEx(HKK,pNewNewKey,0,KEY_READ,&HKKK)==ERROR_SUCCESS)
  {
       unsigned long size=0xFFF;
       unsigned char ValName[0x1000]={0};
                   if(RegQueryValueEx(HKKK,"FriendlyName",0,0,ValName,&size)==ERROR_SUCCESS)
{
        ToLower(ValName);
        if(strstr((char*)ValName,"vbox"))
{
               printf("VirtualBox detected Method 5\n");
               system("pause");

       ExitProcess(5);
}
}
RegCloseKey(HKKK);
  }
}
LocalFree(pNewNewKey);
RegCloseKey(HKK);
  }
 }
 }
 LocalFree(pNewKey);
}
}
RegCloseKey(HK);
}

//method 6
HK=0;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",0,KEY_READ,&HK)==ERROR_SUCCESS)
{
unsigned long type=0;
unsigned long size=0x100;
char* systembiosversion=(char*)LocalAlloc(LMEM_ZEROINIT,size+10);
if(ERROR_SUCCESS==RegQueryValueEx(HK,"SystemBiosVersion",0,&type,(unsigned char*)systembiosversion,&size))
{
 ToLower((unsigned char*)systembiosversion);
 if(type==REG_SZ||type==REG_MULTI_SZ)
 {
 if(strstr(systembiosversion,"vbox"))
 {
       printf("VirtualBox detected Method 6 v1\n");
               system("pause");

ExitProcess(6);
 }
 }
}
LocalFree(systembiosversion);

type=0;
size=0x200;
char* videobiosversion=(char*)LocalAlloc(LMEM_ZEROINIT,size+10);
if(ERROR_SUCCESS==RegQueryValueEx(HK,"VideoBiosVersion",0,&type,(unsigned char*)videobiosversion,&size))
{
if(type==REG_MULTI_SZ)
{
char* video=videobiosversion;
while(*(unsigned char*)video)
{
ToLower((unsigned char*)video);
if(strstr(video,"oracle")||strstr(video,"virtualbox") )
{
       printf("VirtualBox detected Method 6 v2: %s\n",video);
               system("pause");

ExitProcess(6);
}
video=&video[strlen(video)+1];
}
}
}
LocalFree(videobiosversion);
RegCloseKey(HK);
}
//method 7 - requires guest additions to be installed.
HANDLE hxx=CreateFile("\\\\.\\pipe\\VBoxTrayIPC",GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
if(hxx!=INVALID_HANDLE_VALUE)
{
               printf("VirtualBox detected Method 7\n");
               system("pause");

CloseHandle(hxx);
ExitProcess(7);
}
        //method 8 - requires guest additions installed
        HWND hY1=FindWindow("VBoxTrayToolWndClass",0);
HWND hY2=FindWindow(0,"VBoxTrayToolWnd");
if(hY1 || hY2)
{
printf("VirtualBox detected Method 8\n");
                system("pause");

ExitProcess(8);
}

printf("Nothing detected\n");
system("pause");

}

To compile it use this:
i586-mingw32msvc-gcc -Wall -std=c99 -s -O2 -lws2_32 -lshlwapi -o waleedassar_detectvbox.exe waleedassar_detectvbox.c


You should have a running .exe to send to the sandbox:

VM detected with method 1.
When you look at the code you can see that method 1 is looking at a registry key under HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT with the name VBOX__:

so let's add a hook for this detection. Open "hook_reg.c" add this lines under the hook of "RegOpenKeyExA" (I added also some possible detection):

    else if (strstr(lpSubKey, "VBOX") != NULL) {
        ret = 1;
        LOQ("s", "Hardening", "Faked RegOpenKeyExA return");
    }
    else if (strstr(lpSubKey, "vbox") != NULL) {
        ret = 1;
        LOQ("s", "Hardening", "Faked RegOpenKeyExA return");
    }
    else if (strstr(lpSubKey, "oracle") != NULL) {
        ret = 1;
        LOQ("s", "Hardening", "Faked RegOpenKeyExA return");
    }
    else if (strstr(lpSubKey, "virtualbox") != NULL) {
        ret = 1;
        LOQ("s", "Hardening", "Faked RegOpenKeyExA return");
    }

Let's do the same with the "VideoBiosVersion" that we saw earlier with "pafish.exe". Add this under the hook of "RegQueryValueExA" and "RegQueryValueExW":

    else if (strstr(lpValueName, "VideoBiosVersion") != NULL) {
        ret = ERROR_SUCCESS;
        LOQ("s", "Hardening", "Faked RegQueryValueExA return");
    }

Compile the cuckoomon dll again and you should have an hardened sandbox that will give you "hopefully" more interesting results:



Feel free to comment. Happy sandboxing !