Last updated at Wed, 07 Feb 2024 19:56:15 GMT

I hear a lot of questions concerning antivirus evasion with Metasploit, so I'd like to share some the information critical to understanding this problem. This blog post is not designed to give you surefire antivirus (AV) evasion techniques, but rather to help you understand the fundamentals of the issue.

A Quick Glossary

Before we begin, let's define a few terms. This will be important for understanding some of the things we will discuss.

Payload: A payload is the actual code that is being delivered to a victim by an exploit.

Signature: In the antivirus world, signatures are the most basic form of detection. A signature is a set of rules or pattern match against code. Signatures are based on known examples of malicious code. For a real life analogy, think of those artists sketches the police put on the news when they are looking for a criminal. They are meant to convey enough detail so that people can easily recognize someone who is known to be dangerous.

Heuristics: Heuristics are the attempt to identify malicious code by matching specific behavior instead of exact patterns in that code. It watches the way the code runs, and determines dangerous behavior based on more complex sets of rules.

Sandbox: AV sandboxes are protected segments in the operating system, where code can be run safely. It prevents that code from harming important parts of the OS. AV can run malicious code in a sandbox while it uses heuristic detection to determine if it's safe. Because these sandboxes could seriously slow down operation of the system, it usually only runs for a brief period then releases the code if nothing malicious is detected.

Payloads

The first thing we need to understand is how payloads work in Metasploit. When talking about payloads, there are two different kinds of payload we need to understand.

Singles: A single payload is a piece of standalone shellcode that is generated in one step and that performs a single discrete task, for example the Windows Add User Payload.

Staged: Staged payloads are componentized payloads, which are used to get larger more complex payloads to the target when there isn't enough space in the exploit. Staged payloads are broken down into stages, hence the name.

  • Stage 1: Also know as ‘the stager', is a relatively small bit of shellcode that opens a communication channel back to a payload handler running in Metasploit. The handler then sends the stager back the next stage of the payload, which is placed into memory and executed. Examples of stagers include: bind_tcp, reverse_tcp, reverse_http, and reverse_https among others.
  • Stage 2: Is what will actually be setting up our payload to run in memory. In the case of Meterpreter, this will load the basic Meterpreter skeleton into memory, which downloads the Meterpreter libraries and extensions from Metasploit.

Many times when people say that AV is catching Meterpreter, it is actually the stager that is getting flagged. These stagers are fairly recognizable, and are the easiest path for AV to try and block our payloads.

Executable Templates

In many scenarios, the exploit directly writes the stager into the memory of the application being exploited. However, in some cases Metasploit has to deliver payloads through vulnerabilities other than memory corruption. This is where executable templates come in handy. We cannot simply write a blob of shellcode to the machine and expect it to execute; we need a properly formatted executable file that will handle this for us.

An executable template is primarily responsible for one job: It grabs space in memory, writes stager shellcode (or a single payload) into that space, and executes it. These executable templates come in many flavors, but PECoff (executable file) and ELF binaries are the most common.

When an executable payload is generated in Metasploit as part of an exploit, or generated through something like MSFVenom, a set of default templates are used. Most of the AV vendors have added static signatures for these default templates. These signatures don't even look for a payload; they just look for the executable template. Look what happens when we upload one of these empty templates to VirusTotal:

There is nothing actually malicious in that executable but 33 different AV products pick it up. This is a lazy but effective technique on the AV Vendors' parts. Since they know a lot of Metasploit payloads will be wrapped in these specific binaries, they create some static signatures and then go on to other things.

How do we get around this issue? Well the most obvious answer is to use a different executable template. When using an exploit that leverages an executable payload, there are advanced options available for the use of custom templates. To see this, select the psexec module and hit ‘show advanced'. You'll see these options under advanced options:

There are a lot of different considerations when selecting an executable template: You could try to use an existing executable that is known to be safe, and try to hide your payload there. Some of the advanced options above exactly do that. For more information on this approach, I also highly recommend Chris Gates' blog post: Carnal0wnage; Attack Research Blog: Msfencode a Msfpayload Into An Existing Executable

You could also write and compile your own template, enabling you to do all sorts of complex and dirty tricks in your template. We'll talk a little more on this later on when we discuss the dynamic executable option available in Metasploit Pro.

The Encoder Myth

Many users seem to be confused about what encoders are for: “AV keeps picking up my payload no matter what encoder I try.” Encoders are not meant to evade AV but handle bad characters. When dealing with memory corruption exploits some characters may break your exploit. In most cases, a null byte anywhere in the payload will cause it to fail. Depending on the protocol, other characters may cause unintended results. Common characters for this are space, tab, carriage return, and line feed, among others.

Encoders are designed to modify the payload so that it will work for a given exploit, avoiding a known set of bad characters and size limitation. There are many different ways we can go about this.

Newer, more advanced encoders actually use a rolling XOR encoding to create polymorphic code. The encoder uses a rolling XOR on the payload creating an encoded data stream. It then prepends a decoder stub to it. When the payload is delivered, the decoder stub triggers first, decoding the payload back into executable shell code in memory. The payload is unrecognizable until it runs. This has, in the past, created the unintended side effect of helping to evade antivirus, and is probably responsible for the creation of the Encoder Myth.

However, any decent heuristic detection inside AV will not be fooled by this simple obfuscation. Furthermore the decoder stub itself will tend to be fairly recognizable and could potentially be caught with signature-based detection.

Another way to evade AV is through the creation of new polymorphic encoders, obfuscating the code and creating currently unrecognized decoder stubs. This is a stopgap measure, as AV eventually creates signatures for the new decoder stubs, and is still not be particularly effective against heuristic detection.

Dynamic Executable Templates in Metasploit Pro

Starting with version 4.4, Metasploit Pro offers the option to dynamically generate executable templates when using the psexec module, which can be selected from Advanced Options when running the PSExec module, or Payload Settings in the Bruteforcer when selecting SMB.

The Dynamic EXE Option for PSExec

Dynamic EXE Option in the Bruteforcer

A dynamic EXE can also be generated manually using the exploits/pro/windows/dynamic_exe module. This will generate a dynamic exe on Metasploit Pro's local file system. The payload can then be delivered by various out-of-band methods.

The purpose of the dynamic executable generator is to avoid AV detection. It generates the C code for the executable template, and includes the payload directly, instead of injecting it after the template has been generated. The C code is written in a random, on-the-fly fashion and compiled with Metasm. It uses several techniques to try and evade AV.

Dynamic Nature

The code is completely different every time it is generated, using randomized procedurally created C functions, which are then assembled into randomized call trees. This means that the code is different every time; the execution flow also doesn't fall into any predictable patterns either. Metasploit Pro initializes random variables and scrambles them with other, required variables so that the significant variables are never mapped into the same place in memory. The actual functions are different every time, the execution flow is different every time, and the memory layout is different every time. This makes it virtually impossible for AV vendors to create a static signature for detection of these payloads.

You could say we are exploiting the fundamental flaw with signature based detection. The amount of work to maintain signatures becomes overwhelming, and signatures are quickly outdated.

Appear harmless

The randomly generated C functions also fill the call tree with completely harmless, innocuous operations, which is especially important for sandboxing. As you already know, sandboxes run for a limited time and eventually release the payload. By performing only legitimate actions during that time, the sandbox will have no choice but to release our payload, at which point we can safely execute the actual payload.

Hide the payload

You are probably tired of seeing the word random, but here we go again: Metasploit Pro actually randomizes its payload in memory. The payload is read into memory completely scrambled. We then unscramble the payload only right before we execute it. This scramble is randomized each run, making it very hard to detect the payload sitting in memory.

Detect debuggers

Like with AV, the code can detect debuggers and stop any malicious activity, making reverse engineering of the payload much more difficult (though far from impossible).

Dynamic run-time linking

Antivirus solutions also often look at the imports table of the executable. Metasploit Pro evades detection through dynamic runtime linking of all required functions, keeping the imports table almost completely empty. It also makes it harder to recognize what functions the code is actually calling.

These methods make life difficult, though not impossible, for reverse engineers and antivirus solutions to analyze Metasploit payloads. In fact, Metasploit does get caught by some AV solutions, with detection rates varying from run to run.

Antivirus evasion is never done. We will never be satisfied with what we've achieved. Watch this space for updates on the arms race. We intend to work hard to stay a few steps ahead.

Further Reading

This has been a quick, high level, overview of some of the concepts. For more detailed work, check out some of these links:

Why Encoding Does not Matter and How Metasploit Generates EXEs; Thoughts on Security

Facts and myths about antivirus evasion with Metasploit

Pentest Geek; Using Metasm To Avoid Antivirus Detection (Ghost Writing ASM)