open atlas
↑ Back to track
Offensive Security RED · 04 · 02

Payloads and shells

A shell is the code that runs once an exploit lands. Reverse vs bind is a question of who dials whom — and that single choice is exactly what egress filtering and EDR are built to catch. Learn the mechanism so you can break the channel.

RED Middle ◷ 15 min
Level
FoundationsJuniorMiddleSenior

On the authorized engagement, the exploit lands. The instruction pointer is yours — but a hijacked return address is a thread that runs for a few microseconds and then the process either crashes or moves on. You have control of execution and almost nothing to do with it. What you actually want is a conversation: a terminal you can type into, from across the network, that survives the function returning. That second stage — the code that turns a fleeting moment of control into a durable, interactive session — is the payload, and the session it gives you is the shell. The interesting part is not writing it. It is that the instant your payload tries to open that conversation, it has to make a network connection or open a port — and that is the one thing the defender’s firewall and EDR were built, byte for byte, to notice.

By the end of this lesson you’ll know what a payload and a shell actually are, why “reverse vs bind” comes down to who dials whom, and how egress filtering and EDR detect the channel — so you can reason about breaking it from either side.

Authorization first — this is mechanism, not a weapon

Everything below is the theory of how a post-exploitation channel forms and how defenders see it. There is no working payload here and there is no need for one: you can fully understand reverse shells, bind shells, and how they get caught without ever pointing one at a system you don’t own. The only legitimate places to watch a shell connect back are a CTF box, a deliberately vulnerable VM you stood up, or an in-scope engagement with written authorization. In MITRE ATT&CK terms, the exploit bought us a foothold; the payload is what establishes Execution and then Persistence (TA0003) — keeping that code reachable. We study the connection and the process tree precisely so a defender can break the chain at the narrowest point. Run a shell at a target you have no authorization for and you are not learning security — you are committing a crime.

A payload is the what-runs-next; a shell is the conversation

The exploit answers “how do I redirect execution.” The payload answers “execution is mine — now do what?” In a stack overflow, the bytes that overwrote the return address pointed somewhere; the payload is the code waiting at that destination. Historically that was raw shellcode injected into the same buffer; on modern systems with non-executable stacks it is more often a chain that calls an existing function to spawn a child process. Either way, the goal of the most common payload is humble and devastating: launch a command interpreter — /bin/sh, bash, cmd.exe, powershell — and wire its standard input and output to a network socket. That wiring is the whole game. A local shell is useless to a remote attacker; a shell whose keyboard and screen are a TCP connection is a remote terminal.

A shell, then, is just an interactive command interpreter whose I/O has been redirected over the network. Once you have it, you type a command on your machine, it executes on theirs, and the output comes back. Everything else in post-exploitation — escalating privilege, moving laterally, staging tools — happens through that channel. Which is why the channel itself is where the entire detection battle is fought.

Reverse vs bind: who dials whom

There are two ways to wire that socket, and the difference is entirely about the direction the connection is initiated — which turns out to be the single most important fact for whether it survives a real network.

A bind shell opens a listening port on the victim and waits. The attacker connects inbound to that port. It is conceptually the simplest, and it is almost always wrong in practice: inbound connections from the internet to a random high port on an internal host are exactly what a perimeter firewall and NAT exist to block. The victim is usually behind NAT with no public IP and no inbound port forwarding, so there is nothing to connect to.

A reverse shell flips the direction. The victim dials out to the attacker, who is listening. This sails past the two things that kill bind shells: NAT (outbound connections are how every normal client works) and inbound firewall rules (which usually permit outbound traffic by default). This is why “reverse” is the default in nearly every real engagement — not because it is stealthier, but because it is the only one that connects. The attacker often listens on 443 so the traffic blends with HTTPS and tends to be allowed out.

How the defender catches it: egress filtering and EDR

A reverse shell only works because of one usually-true assumption: outbound traffic is allowed by default. Most networks tightly control what comes in and barely look at what goes out. Egress filtering is the defender’s correction — treating outbound traffic with the same suspicion as inbound. Done well, it means a host can only reach an explicit allowlist of destinations and ports; everything else is dropped. Against that, the victim dials out and the packet hits a wall: the attacker’s listener is not on the allowlist, so the connection never completes. The reverse shell’s entire advantage — “outbound is free” — evaporates. This is also why attackers tunnel over 443, DNS, or a real cloud service: they are trying to look like the traffic the allowlist already permits.

The second line is EDR (Endpoint Detection and Response) — an agent watching the host itself, not the wire. Even a perfectly TLS-encrypted reverse shell on 443 leaves fingerprints on the endpoint that the network never sees:

  • An anomalous process tree. A web server process (nginx, php-fpm, java) should not be the parent of /bin/sh or cmd.exe. That parent-child edge is one of the highest-signal detections in existence: it means a service that handles requests just spawned an interactive shell.
  • A shell with a socket as its standard I/O. A normal bash has a terminal on its file descriptors. A reverse shell has a network socket on stdin/stdout. An EDR that inspects what a shell’s descriptors point at sees that immediately.
  • Behavioral sequence. Shell spawned, then whoami, then network discovery, then a download — the post-exploitation playbook itself is a signature.
Shell typeWho initiatesBeats NAT / inbound firewall?What stops it
Bind shellAttacker dials in (inbound)No — inbound to a high port is blockedPerimeter firewall + NAT (already)
Reverse shellVictim dials out (outbound)Yes — rides outbound-allow-by-defaultEgress filtering (outbound allowlist)
Reverse over 443/DNSVictim dials out, looks like HTTPS/DNSYes — blends with allowed trafficEgress + EDR (process tree, socket-as-stdio)
Why this works

Why do attackers keep moving up the stack — raw TCP, then 443, then DNS tunneling, then a Slack/Telegram/Discord webhook as the command channel? Because each move is an answer to egress filtering. A flat outbound block kills raw TCP to a random port. So the channel migrates to ports that must be open (443, 53) and then to destinations that are already on the allowlist (a SaaS API the company genuinely uses). The defender’s counter has to climb too: not just “is the port allowed” but “is this host supposed to be talking to this destination, in this volume, with this timing.” This is exactly why modern detection leans on EDR and behavioral baselines rather than port rules alone — the channel can always borrow a port, but it has a much harder time faking a process tree.

How a senior reasons about it

Whether you are the attacker on an authorized engagement or the defender, the lesson is the same: the payload is easy; the channel is the choke point. An attacker who only knows “reverse shell on 443” gets stopped cold by a network with an egress allowlist and EDR. A defender who only blocks inbound has left the reverse-shell door wide open. The durable mental model is to think in terms of the connection’s direction, destination, and the process that owns it — because every one of those is a place to either hide or detect. Defaults matter most here: a network that allows all outbound is a network that assumes a reverse shell will work, and a host whose web server can spawn a shell unobserved is a host that assumes a payload will run silently.

Pick the best fit

You're hardening an internal app server so that even if it's compromised, a reverse shell can't phone home. The host sits behind NAT with a default-allow outbound policy. Pick the control that actually breaks the reverse-shell channel.

Quiz

Why is a reverse shell the default choice over a bind shell in almost every real engagement?

Quiz

An attacker runs a fully TLS-encrypted reverse shell out over port 443, so the network can't read the payload. How can EDR still flag it on the endpoint?

Order the steps

Order the stages of a reverse shell being established and then detected, from first to last:

  1. 1 Exploit lands and execution is redirected to the payload
  2. 2 Payload spawns a command interpreter (e.g. /bin/sh)
  3. 3 Interpreter's stdin/stdout are wired to an outbound socket
  4. 4 Victim dials out to the attacker's listener on 443
  5. 5 Egress allowlist drops the connection or EDR flags the process tree
Recall before you leave
  1. 01
    Explain the difference between a bind shell and a reverse shell, and why reverse is the default in real engagements.
  2. 02
    A reverse shell is fully TLS-encrypted and goes out over 443. Name the two defensive layers that can still stop or detect it, and what each one keys on.
Recap

A payload is the code that runs the instant an exploit redirects execution; the most common one spawns a command interpreter and wires its standard input and output to a network socket, giving the attacker a shell — a remote, interactive terminal. The choice between a bind shell (victim listens, attacker connects inbound) and a reverse shell (victim dials outbound to the attacker) is purely about connection direction, and reverse wins in practice because NAT and default-allow-outbound firewalls let the outbound connection through while killing the inbound one; attackers often ride 443 to blend with HTTPS. The defender has two counters that map exactly onto what the channel exposes: egress filtering turns outbound into a default-deny allowlist so the reverse connection has nowhere to go, and EDR ignores the encrypted wire to watch the host — flagging the anomalous process tree (a web server parenting /bin/sh), the shell whose descriptors are a socket, and the post-exploitation behavioral sequence. So when you see a host with all-outbound-allowed and a web server that can spawn a shell unobserved, your first question is: which direction does the connection go, where is it allowed to go, and what process owns it — because that is where you either hide the channel or break it.

Practice

Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.

recallapplystretch0 of 6 done
Connected lessons

Something unclear?

Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.

shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.